From 08738c35faf64bdafc1a359614eebf7ec4a0aa1b Mon Sep 17 00:00:00 2001 From: Bo Ren Date: Mon, 25 Dec 2023 17:02:52 +0800 Subject: [PATCH 1/2] update to rust-1.71.1-1 Signed-off-by: Bo Ren --- ...rnal-builds-of-the-compiler-rt-profi.patch | 142 + ...ove-generating-Custom-entry-function.patch | 302 - ...variables-override-some-default-CPUs.patch | 53 + ...e-main-as-__main_void-on-wasm32-wasi.patch | 34 - ...ap-config-fix-version-comparison-bug.patch | 36 + 0001-cargo-CVE-2023-38497.patch | 321 - ...the-dylib-path-when-gathering-target.patch | 185 - 0001-update-vendor-tar-to-0.4.39.patch | 971 - 0001-vendor-cc-add-loongarch64-support.patch | 33 - ...ndor-libc-update-loongarch64-support.patch | 221 - 0003-vendor-psm-add-loongarch64-support.patch | 105 - ...endor-object-add-loongarch64-support.patch | 623 - 0005-llvm-update-loongarch64-support.patch | 70995 ---------------- 0006-rust-add-loongarch64-support.patch | 1691 - download | 4 +- rust.spec | 253 +- rustc-1.65.0-disable-libssh2.patch | 43 - rustc-1.65.0-no-default-pie.patch | 43 - ...ustc-1.70.0-rust-gdb-substitute-path.patch | 21 +- ....patch => rustc-1.71.0-disable-http2.patch | 90 +- rustc-1.71.0-disable-libssh2.patch | 42 + 21 files changed, 469 insertions(+), 75739 deletions(-) create mode 100644 0001-Allow-using-external-builds-of-the-compiler-rt-profi.patch delete mode 100644 0001-Improve-generating-Custom-entry-function.patch create mode 100644 0001-Let-environment-variables-override-some-default-CPUs.patch delete mode 100644 0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch create mode 100644 0001-bootstrap-config-fix-version-comparison-bug.patch delete mode 100644 0001-cargo-CVE-2023-38497.patch delete mode 100644 0001-compiletest-set-the-dylib-path-when-gathering-target.patch delete mode 100644 0001-update-vendor-tar-to-0.4.39.patch delete mode 100644 0001-vendor-cc-add-loongarch64-support.patch delete mode 100644 0002-vendor-libc-update-loongarch64-support.patch delete mode 100644 0003-vendor-psm-add-loongarch64-support.patch delete mode 100644 0004-vendor-object-add-loongarch64-support.patch delete mode 100644 0005-llvm-update-loongarch64-support.patch delete mode 100644 0006-rust-add-loongarch64-support.patch delete mode 100644 rustc-1.65.0-disable-libssh2.patch delete mode 100644 rustc-1.65.0-no-default-pie.patch rename rustc-1.61.0-rust-gdb-substitute-path.patch => rustc-1.70.0-rust-gdb-substitute-path.patch (44%) rename rustc-1.65.0-disable-http2.patch => rustc-1.71.0-disable-http2.patch (63%) create mode 100644 rustc-1.71.0-disable-libssh2.patch diff --git a/0001-Allow-using-external-builds-of-the-compiler-rt-profi.patch b/0001-Allow-using-external-builds-of-the-compiler-rt-profi.patch new file mode 100644 index 0000000..2b1ecb5 --- /dev/null +++ b/0001-Allow-using-external-builds-of-the-compiler-rt-profi.patch @@ -0,0 +1,142 @@ +From f2fd2d01f96b50b039402c9ab4278230687f7922 Mon Sep 17 00:00:00 2001 +From: Josh Stone +Date: Tue, 25 Jul 2023 13:11:50 -0700 +Subject: [PATCH] Allow using external builds of the compiler-rt profile lib + +This changes the bootstrap config `target.*.profiler` from a plain bool +to also allow a string, which will be used as a path to the pre-built +profiling runtime for that target. Then `profiler_builtins/build.rs` +reads that in a `LLVM_PROFILER_RT_LIB` environment variable. +--- + config.example.toml | 6 ++++-- + library/profiler_builtins/build.rs | 6 ++++++ + src/bootstrap/compile.rs | 4 ++++ + src/bootstrap/config.rs | 30 ++++++++++++++++++++++++------ + 4 files changed, 38 insertions(+), 8 deletions(-) + +diff --git a/config.example.toml b/config.example.toml +index d0eaa9fd7ffa..e0e991e679af 100644 +--- a/config.example.toml ++++ b/config.example.toml +@@ -745,8 +745,10 @@ changelog-seen = 2 + # This option will override the same option under [build] section. + #sanitizers = build.sanitizers (bool) + +-# Build the profiler runtime for this target(required when compiling with options that depend +-# on this runtime, such as `-C profile-generate` or `-C instrument-coverage`). ++# When true, build the profiler runtime for this target(required when compiling ++# with options that depend on this runtime, such as `-C profile-generate` or ++# `-C instrument-coverage`). This may also be given a path to an existing build ++# of the profiling runtime library from LLVM's compiler-rt. + # This option will override the same option under [build] section. + #profiler = build.profiler (bool) + +diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs +index 1b1f11798d74..d14d0b82229a 100644 +--- a/library/profiler_builtins/build.rs ++++ b/library/profiler_builtins/build.rs +@@ -6,6 +6,12 @@ + use std::path::Path; + + fn main() { ++ println!("cargo:rerun-if-env-changed=LLVM_PROFILER_RT_LIB"); ++ if let Ok(rt) = env::var("LLVM_PROFILER_RT_LIB") { ++ println!("cargo:rustc-link-lib=static:+verbatim={rt}"); ++ return; ++ } ++ + let target = env::var("TARGET").expect("TARGET was not set"); + let cfg = &mut cc::Build::new(); + +diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs +index 33addb90da37..1d8b3c6e5435 100644 +--- a/src/bootstrap/compile.rs ++++ b/src/bootstrap/compile.rs +@@ -305,6 +305,10 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car + cargo.env("MACOSX_DEPLOYMENT_TARGET", target); + } + ++ if let Some(path) = builder.config.profiler_path(target) { ++ cargo.env("LLVM_PROFILER_RT_LIB", path); ++ } ++ + // Determine if we're going to compile in optimized C intrinsics to + // the `compiler-builtins` crate. These intrinsics live in LLVM's + // `compiler-rt` repository, but our `src/llvm-project` submodule isn't +diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs +index e192cda9a9a7..a4803db0a470 100644 +--- a/src/bootstrap/config.rs ++++ b/src/bootstrap/config.rs +@@ -467,7 +467,7 @@ pub struct Target { + pub linker: Option, + pub ndk: Option, + pub sanitizers: Option, +- pub profiler: Option, ++ pub profiler: Option, + pub rpath: Option, + pub crt_static: Option, + pub musl_root: Option, +@@ -796,9 +796,9 @@ struct Dist { + } + } + +-#[derive(Debug, Deserialize)] ++#[derive(Clone, Debug, Deserialize)] + #[serde(untagged)] +-enum StringOrBool { ++pub enum StringOrBool { + String(String), + Bool(bool), + } +@@ -809,6 +809,12 @@ fn default() -> StringOrBool { + } + } + ++impl StringOrBool { ++ fn is_string_or_true(&self) -> bool { ++ matches!(self, Self::String(_) | Self::Bool(true)) ++ } ++} ++ + define_config! { + /// TOML representation of how the Rust build is configured. + struct Rust { +@@ -880,7 +886,7 @@ struct TomlTarget { + llvm_libunwind: Option = "llvm-libunwind", + android_ndk: Option = "android-ndk", + sanitizers: Option = "sanitizers", +- profiler: Option = "profiler", ++ profiler: Option = "profiler", + rpath: Option = "rpath", + crt_static: Option = "crt-static", + musl_root: Option = "musl-root", +@@ -1744,12 +1750,24 @@ pub fn any_sanitizers_enabled(&self) -> bool { + self.target_config.values().any(|t| t.sanitizers == Some(true)) || self.sanitizers + } + ++ pub fn profiler_path(&self, target: TargetSelection) -> Option<&str> { ++ match self.target_config.get(&target)?.profiler.as_ref()? { ++ StringOrBool::String(s) => Some(s), ++ StringOrBool::Bool(_) => None, ++ } ++ } ++ + pub fn profiler_enabled(&self, target: TargetSelection) -> bool { +- self.target_config.get(&target).map(|t| t.profiler).flatten().unwrap_or(self.profiler) ++ self.target_config ++ .get(&target) ++ .and_then(|t| t.profiler.as_ref()) ++ .map(StringOrBool::is_string_or_true) ++ .unwrap_or(self.profiler) + } + + pub fn any_profiler_enabled(&self) -> bool { +- self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler ++ self.target_config.values().any(|t| matches!(&t.profiler, Some(p) if p.is_string_or_true())) ++ || self.profiler + } + + pub fn rpath_enabled(&self, target: TargetSelection) -> bool { +-- +2.41.0 + diff --git a/0001-Improve-generating-Custom-entry-function.patch b/0001-Improve-generating-Custom-entry-function.patch deleted file mode 100644 index 77cb30e..0000000 --- a/0001-Improve-generating-Custom-entry-function.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 9f0a8620bd7d325e6d42417b08daff3e55cb88f6 Mon Sep 17 00:00:00 2001 -From: Ayush Singh -Date: Sat, 5 Nov 2022 14:36:38 +0530 -Subject: [PATCH] Improve generating Custom entry function - -This commit is aimed at making compiler generated entry functions -(Basically just C `main` right now) more generic so other targets can do -similar things for custom entry. This was initially implemented as part -of https://github.com/rust-lang/rust/pull/100316. - -Currently, this moves the entry function name and Call convention to the -target spec. - -Signed-off-by: Ayush Singh ---- - compiler/rustc_codegen_llvm/src/abi.rs | 40 +++++++++++-------- - compiler/rustc_codegen_llvm/src/context.rs | 10 ++++- - compiler/rustc_codegen_llvm/src/declare.rs | 22 ++++++++++ - .../src/back/symbol_export.rs | 3 +- - compiler/rustc_target/src/abi/call/mod.rs | 28 +++++++++++++ - compiler/rustc_target/src/json.rs | 25 ++++++++++++ - compiler/rustc_target/src/spec/mod.rs | 27 +++++++++++++ - 7 files changed, 135 insertions(+), 20 deletions(-) - -diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs -index d478efc863a9..a6fd2a7de6bd 100644 ---- a/compiler/rustc_codegen_llvm/src/abi.rs -+++ b/compiler/rustc_codegen_llvm/src/abi.rs -@@ -398,23 +398,7 @@ fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { - } - - fn llvm_cconv(&self) -> llvm::CallConv { -- match self.conv { -- Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv, -- Conv::RustCold => llvm::ColdCallConv, -- Conv::AmdGpuKernel => llvm::AmdGpuKernel, -- Conv::AvrInterrupt => llvm::AvrInterrupt, -- Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, -- Conv::ArmAapcs => llvm::ArmAapcsCallConv, -- Conv::Msp430Intr => llvm::Msp430Intr, -- Conv::PtxKernel => llvm::PtxKernel, -- Conv::X86Fastcall => llvm::X86FastcallCallConv, -- Conv::X86Intr => llvm::X86_Intr, -- Conv::X86Stdcall => llvm::X86StdcallCallConv, -- Conv::X86ThisCall => llvm::X86_ThisCall, -- Conv::X86VectorCall => llvm::X86_VectorCall, -- Conv::X86_64SysV => llvm::X86_64_SysV, -- Conv::X86_64Win64 => llvm::X86_64_Win64, -- } -+ self.conv.into() - } - - fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) { -@@ -596,3 +580,25 @@ fn get_param(&mut self, index: usize) -> Self::Value { - llvm::get_param(self.llfn(), index as c_uint) - } - } -+ -+impl From for llvm::CallConv { -+ fn from(conv: Conv) -> Self { -+ match conv { -+ Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv, -+ Conv::RustCold => llvm::ColdCallConv, -+ Conv::AmdGpuKernel => llvm::AmdGpuKernel, -+ Conv::AvrInterrupt => llvm::AvrInterrupt, -+ Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, -+ Conv::ArmAapcs => llvm::ArmAapcsCallConv, -+ Conv::Msp430Intr => llvm::Msp430Intr, -+ Conv::PtxKernel => llvm::PtxKernel, -+ Conv::X86Fastcall => llvm::X86FastcallCallConv, -+ Conv::X86Intr => llvm::X86_Intr, -+ Conv::X86Stdcall => llvm::X86StdcallCallConv, -+ Conv::X86ThisCall => llvm::X86_ThisCall, -+ Conv::X86VectorCall => llvm::X86_VectorCall, -+ Conv::X86_64SysV => llvm::X86_64_SysV, -+ Conv::X86_64Win64 => llvm::X86_64_Win64, -+ } -+ } -+} -diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs -index 79ddfd884dfa..f3ef618fff54 100644 ---- a/compiler/rustc_codegen_llvm/src/context.rs -+++ b/compiler/rustc_codegen_llvm/src/context.rs -@@ -570,8 +570,14 @@ fn apply_target_cpu_attr(&self, llfn: &'ll Value) { - } - - fn declare_c_main(&self, fn_type: Self::Type) -> Option { -- if self.get_declared_value("main").is_none() { -- Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type)) -+ let entry_name = self.sess().target.entry_name.as_ref(); -+ if self.get_declared_value(entry_name).is_none() { -+ Some(self.declare_entry_fn( -+ entry_name, -+ self.sess().target.entry_abi.into(), -+ llvm::UnnamedAddr::Global, -+ fn_type, -+ )) - } else { - // If the symbol already exists, it is an error: for example, the user wrote - // #[no_mangle] extern "C" fn main(..) {..} -diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs -index f79ef11720df..dc21a02cec44 100644 ---- a/compiler/rustc_codegen_llvm/src/declare.rs -+++ b/compiler/rustc_codegen_llvm/src/declare.rs -@@ -90,6 +90,28 @@ pub fn declare_cfn( - declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) - } - -+ /// Declare an entry Function -+ /// -+ /// The ABI of this function can change depending on the target (although for now the same as -+ /// `declare_cfn`) -+ /// -+ /// If there’s a value with the same name already declared, the function will -+ /// update the declaration and return existing Value instead. -+ pub fn declare_entry_fn( -+ &self, -+ name: &str, -+ callconv: llvm::CallConv, -+ unnamed: llvm::UnnamedAddr, -+ fn_type: &'ll Type, -+ ) -> &'ll Value { -+ let visibility = if self.tcx.sess.target.default_hidden_visibility { -+ llvm::Visibility::Hidden -+ } else { -+ llvm::Visibility::Default -+ }; -+ declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type) -+ } -+ - /// Declare a Rust function. - /// - /// If there’s a value with the same name already declared, the function will -diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs -index 752f6b1ef40c..22f534d909ab 100644 ---- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs -+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs -@@ -180,7 +180,8 @@ fn exported_symbols_provider_local<'tcx>( - .collect(); - - if tcx.entry_fn(()).is_some() { -- let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, "main")); -+ let exported_symbol = -+ ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref())); - - symbols.push(( - exported_symbol, -diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs -index 9e5f0e4d158b..c622bd36b00c 100644 ---- a/compiler/rustc_target/src/abi/call/mod.rs -+++ b/compiler/rustc_target/src/abi/call/mod.rs -@@ -3,6 +3,7 @@ - use crate::spec::{self, HasTargetSpec}; - use rustc_span::Symbol; - use std::fmt; -+use std::str::FromStr; - - mod aarch64; - mod amdgpu; -@@ -735,6 +736,33 @@ pub fn adjust_for_foreign_abi( - } - } - -+impl FromStr for Conv { -+ type Err = String; -+ -+ fn from_str(s: &str) -> Result { -+ match s { -+ "C" => Ok(Conv::C), -+ "Rust" => Ok(Conv::Rust), -+ "RustCold" => Ok(Conv::Rust), -+ "ArmAapcs" => Ok(Conv::ArmAapcs), -+ "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall), -+ "Msp430Intr" => Ok(Conv::Msp430Intr), -+ "PtxKernel" => Ok(Conv::PtxKernel), -+ "X86Fastcall" => Ok(Conv::X86Fastcall), -+ "X86Intr" => Ok(Conv::X86Intr), -+ "X86Stdcall" => Ok(Conv::X86Stdcall), -+ "X86ThisCall" => Ok(Conv::X86ThisCall), -+ "X86VectorCall" => Ok(Conv::X86VectorCall), -+ "X86_64SysV" => Ok(Conv::X86_64SysV), -+ "X86_64Win64" => Ok(Conv::X86_64Win64), -+ "AmdGpuKernel" => Ok(Conv::AmdGpuKernel), -+ "AvrInterrupt" => Ok(Conv::AvrInterrupt), -+ "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt), -+ _ => Err(format!("'{}' is not a valid value for entry function call convetion.", s)), -+ } -+ } -+} -+ - // Some types are used a lot. Make sure they don't unintentionally get bigger. - #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] - mod size_asserts { -diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs -index b5d926352122..75bb76a9de08 100644 ---- a/compiler/rustc_target/src/json.rs -+++ b/compiler/rustc_target/src/json.rs -@@ -89,3 +89,28 @@ fn to_json(&self) -> Json { - } - } - } -+ -+impl ToJson for crate::abi::call::Conv { -+ fn to_json(&self) -> Json { -+ let s = match self { -+ Self::C => "C", -+ Self::Rust => "Rust", -+ Self::RustCold => "RustCold", -+ Self::ArmAapcs => "ArmAapcs", -+ Self::CCmseNonSecureCall => "CCmseNonSecureCall", -+ Self::Msp430Intr => "Msp430Intr", -+ Self::PtxKernel => "PtxKernel", -+ Self::X86Fastcall => "X86Fastcall", -+ Self::X86Intr => "X86Intr", -+ Self::X86Stdcall => "X86Stdcall", -+ Self::X86ThisCall => "X86ThisCall", -+ Self::X86VectorCall => "X86VectorCall", -+ Self::X86_64SysV => "X86_64SysV", -+ Self::X86_64Win64 => "X86_64Win64", -+ Self::AmdGpuKernel => "AmdGpuKernel", -+ Self::AvrInterrupt => "AvrInterrupt", -+ Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt", -+ }; -+ Json::String(s.to_owned()) -+ } -+} -diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs -index 72b088d663b1..617de46a55aa 100644 ---- a/compiler/rustc_target/src/spec/mod.rs -+++ b/compiler/rustc_target/src/spec/mod.rs -@@ -34,6 +34,7 @@ - //! the target's settings, though `target-feature` and `link-args` will *add* - //! to the list specified by the target, rather than replace. - -+use crate::abi::call::Conv; - use crate::abi::Endian; - use crate::json::{Json, ToJson}; - use crate::spec::abi::{lookup as lookup_abi, Abi}; -@@ -1668,6 +1669,14 @@ pub struct TargetOptions { - /// Whether the target supports stack canary checks. `true` by default, - /// since this is most common among tier 1 and tier 2 targets. - pub supports_stack_protector: bool, -+ -+ // The name of entry function. -+ // Default value is "main" -+ pub entry_name: StaticCow, -+ -+ // The ABI of entry function. -+ // Default value is `Conv::C`, i.e. C call convention -+ pub entry_abi: Conv, - } - - /// Add arguments for the given flavor and also for its "twin" flavors -@@ -1884,6 +1893,8 @@ fn default() -> TargetOptions { - c_enum_min_bits: 32, - generate_arange_section: true, - supports_stack_protector: true, -+ entry_name: "main".into(), -+ entry_abi: Conv::C, - } - } - } -@@ -2401,6 +2412,18 @@ macro_rules! key { - } - } - } ); -+ ($key_name:ident, Conv) => ( { -+ let name = (stringify!($key_name)).replace("_", "-"); -+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { -+ match Conv::from_str(s) { -+ Ok(c) => { -+ base.$key_name = c; -+ Some(Ok(())) -+ } -+ Err(e) => Some(Err(e)) -+ } -+ })).unwrap_or(Ok(())) -+ } ); - } - - if let Some(j) = obj.remove("target-endian") { -@@ -2520,6 +2543,8 @@ macro_rules! key { - key!(c_enum_min_bits, u64); - key!(generate_arange_section, bool); - key!(supports_stack_protector, bool); -+ key!(entry_name); -+ key!(entry_abi, Conv)?; - - if base.is_builtin { - // This can cause unfortunate ICEs later down the line. -@@ -2770,6 +2795,8 @@ macro_rules! target_option_val { - target_option_val!(c_enum_min_bits); - target_option_val!(generate_arange_section); - target_option_val!(supports_stack_protector); -+ target_option_val!(entry_name); -+ target_option_val!(entry_abi); - - if let Some(abi) = self.default_adjusted_cabi { - d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json()); --- -2.38.1 - diff --git a/0001-Let-environment-variables-override-some-default-CPUs.patch b/0001-Let-environment-variables-override-some-default-CPUs.patch new file mode 100644 index 0000000..c394f78 --- /dev/null +++ b/0001-Let-environment-variables-override-some-default-CPUs.patch @@ -0,0 +1,53 @@ +From 6e2adb05860b72610291d3b0e8bd525c44cb0cc9 Mon Sep 17 00:00:00 2001 +From: Josh Stone +Date: Fri, 9 Jun 2023 15:23:08 -0700 +Subject: [PATCH] Let environment variables override some default CPUs + +--- + compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs | 2 +- + compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs | 2 +- + compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +index fd896e086b54..08d0c43d20b4 100644 +--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs ++++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +@@ -2,7 +2,7 @@ + + pub fn target() -> Target { + let mut base = super::linux_gnu_base::opts(); +- base.cpu = "ppc64le".into(); ++ base.cpu = option_env!("RUSTC_TARGET_CPU_PPC64LE").unwrap_or("ppc64le").into(); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.max_atomic_width = Some(64); + base.stack_probes = StackProbeType::Inline; +diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +index f2c722b9a89d..17a14d10b27e 100644 +--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs ++++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +@@ -5,7 +5,7 @@ pub fn target() -> Target { + let mut base = super::linux_gnu_base::opts(); + base.endian = Endian::Big; + // z10 is the oldest CPU supported by LLVM +- base.cpu = "z10".into(); ++ base.cpu = option_env!("RUSTC_TARGET_CPU_S390X").unwrap_or("z10").into(); + // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector + // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we + // also strip v128 from the data_layout below to match the older LLVM's expectation. +diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +index 9af1049b8702..68f876dd18c3 100644 +--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs ++++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +@@ -2,7 +2,7 @@ + + pub fn target() -> Target { + let mut base = super::linux_gnu_base::opts(); +- base.cpu = "x86-64".into(); ++ base.cpu = option_env!("RUSTC_TARGET_CPU_X86_64").unwrap_or("x86-64").into(); + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.stack_probes = StackProbeType::X86; +-- +2.40.1 + diff --git a/0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch b/0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch deleted file mode 100644 index 3f087ef..0000000 --- a/0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 98ae83daae67e9e7663b8345eced1de8c667271f Mon Sep 17 00:00:00 2001 -From: Dan Gohman -Date: Thu, 8 Dec 2022 10:35:46 -0800 -Subject: [PATCH] Mangle "main" as "__main_void" on wasm32-wasi - -On wasm, the age-old C trick of having a main function which can either have -no arguments or argc+argv doesn't work, because wasm requires caller and -callee signatures to match. WASI's current strategy is to have compilers -mangle main's name to indicate which signature they're using. Rust uses the -no-argument form, which should be mangled as `__main_void`. - -This is needed on wasm32-wasi as of #105395. ---- - compiler/rustc_target/src/spec/wasm32_wasi.rs | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs -index 6f0bbf0672d4..a0476d542e64 100644 ---- a/compiler/rustc_target/src/spec/wasm32_wasi.rs -+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs -@@ -104,6 +104,10 @@ pub fn target() -> Target { - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - -+ // And, WASI mangles the name of "main" to distinguish between different -+ // signatures. -+ options.entry_name = "__main_void".into(); -+ - Target { - llvm_target: "wasm32-wasi".into(), - pointer_width: 32, --- -2.38.1 - diff --git a/0001-bootstrap-config-fix-version-comparison-bug.patch b/0001-bootstrap-config-fix-version-comparison-bug.patch new file mode 100644 index 0000000..f0c4e55 --- /dev/null +++ b/0001-bootstrap-config-fix-version-comparison-bug.patch @@ -0,0 +1,36 @@ +From a627c8f54cab6880dc7d36c55092a94c6f750a6e Mon Sep 17 00:00:00 2001 +From: Ariadne Conill +Date: Thu, 3 Aug 2023 15:05:40 -0700 +Subject: [PATCH] bootstrap: config: fix version comparison bug + +Rust requires a previous version of Rust to build, such as the current version, or the +previous version. However, the version comparison logic did not take patch releases +into consideration when doing the version comparison for the current branch, e.g. +Rust 1.71.1 could not be built by Rust 1.71.0 because it is neither an exact version +match, or the previous version. + +Adjust the version comparison logic to tolerate mismatches in the patch version. + +Signed-off-by: Ariadne Conill +(cherry picked from commit 31a81a08786826cc6e832bd0b49fb8b934e29648) +--- + src/bootstrap/config.rs | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs +index e192cda9a9a7..2b5d0b94e968 100644 +--- a/src/bootstrap/config.rs ++++ b/src/bootstrap/config.rs +@@ -1805,7 +1805,8 @@ pub fn check_build_rustc_version(&self) { + .unwrap(); + if !(source_version == rustc_version + || (source_version.major == rustc_version.major +- && source_version.minor == rustc_version.minor + 1)) ++ && (source_version.minor == rustc_version.minor ++ || source_version.minor == rustc_version.minor + 1))) + { + let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1); + eprintln!( +-- +2.41.0 + diff --git a/0001-cargo-CVE-2023-38497.patch b/0001-cargo-CVE-2023-38497.patch deleted file mode 100644 index c86f4f6..0000000 --- a/0001-cargo-CVE-2023-38497.patch +++ /dev/null @@ -1,321 +0,0 @@ -From 13030f7009233e040c2d9c52d8b61d8c53a71662 Mon Sep 17 00:00:00 2001 -From: Liwei Ge -Date: Wed, 16 Aug 2023 11:00:14 +0800 -Subject: [PATCH] fix CVE-2023-38497 - -backport from https://github.com/rust-lang/cargo/commit/ -d78bbf4bde3c6b95caca7512f537c6f9721426ff ---- - .../cargo/src/cargo/sources/registry/mod.rs | 55 +++++++- - src/tools/cargo/src/cargo/util/mod.rs | 18 +++ - src/tools/cargo/tests/testsuite/registry.rs | 130 +++++++++++++++++- - src/tools/cargo/tests/testsuite/vendor.rs | 5 +- - 4 files changed, 197 insertions(+), 11 deletions(-) - -diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs -index cabd4f9c6..6e0e97350 100644 ---- a/src/tools/cargo/src/cargo/sources/registry/mod.rs -+++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs -@@ -161,17 +161,21 @@ - use std::borrow::Cow; - use std::collections::BTreeMap; - use std::collections::HashSet; -+use std::fs; - use std::fs::{File, OpenOptions}; -+use std::io; -+use std::io::Read; - use std::io::Write; - use std::path::{Path, PathBuf}; - use std::task::Poll; - - use anyhow::Context as _; --use cargo_util::paths::exclude_from_backups_and_indexing; -+use cargo_util::paths::{self, exclude_from_backups_and_indexing}; - use flate2::read::GzDecoder; - use log::debug; - use semver::Version; - use serde::Deserialize; -+use serde::Serialize; - use tar::Archive; - - use crate::core::dependency::{DepKind, Dependency}; -@@ -198,6 +202,14 @@ const LOWER_PREFIX_TEMPLATE: &str = "{lowerprefix}"; - const CHECKSUM_TEMPLATE: &str = "{sha256-checksum}"; - const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024; - -+/// The content inside `.cargo-ok`. -+/// See [`RegistrySource::unpack_package`] for more. -+#[derive(Deserialize, Serialize)] -+struct LockMetadata { -+ /// The version of `.cargo-ok` file -+ v: u32, -+} -+ - /// A "source" for a local (see `local::LocalRegistry`) or remote (see - /// `remote::RemoteRegistry`) registry. - /// -@@ -608,18 +620,32 @@ impl<'cfg> RegistrySource<'cfg> { - // unpacked. - let package_dir = format!("{}-{}", pkg.name(), pkg.version()); - let dst = self.src_path.join(&package_dir); -- dst.create_dir()?; - let path = dst.join(PACKAGE_SOURCE_LOCK); - let path = self.config.assert_package_cache_locked(&path); - let unpack_dir = path.parent().unwrap(); -- if let Ok(meta) = path.metadata() { -- if meta.len() > 0 { -- return Ok(unpack_dir.to_path_buf()); -- } -+ match fs::read_to_string(path) { -+ Ok(ok) => match serde_json::from_str::(&ok) { -+ Ok(lock_meta) if lock_meta.v == 1 => { -+ return Ok(unpack_dir.to_path_buf()); -+ } -+ _ => { -+ if ok == "ok" { -+ log::debug!("old `ok` content found, clearing cache"); -+ } else { -+ log::warn!("unrecognized .cargo-ok content, clearing cache: {ok}"); -+ } -+ // See comment of `unpack_package` about why removing all stuff. -+ paths::remove_dir_all(dst.as_path_unlocked())?; -+ } -+ }, -+ Err(e) if e.kind() == io::ErrorKind::NotFound => {} -+ Err(e) => anyhow::bail!("unable to read .cargo-ok file at {path:?}: {e}"), - } -+ dst.create_dir()?; - let gz = GzDecoder::new(tarball); - let gz = LimitErrorReader::new(gz, max_unpack_size()); - let mut tar = Archive::new(gz); -+ set_mask(&mut tar); - let prefix = unpack_dir.file_name().unwrap(); - let parent = unpack_dir.parent().unwrap(); - for entry in tar.entries()? { -@@ -673,7 +699,9 @@ impl<'cfg> RegistrySource<'cfg> { - .write(true) - .open(&path) - .with_context(|| format!("failed to open `{}`", path.display()))?; -- write!(ok, "ok")?; -+ -+ let lock_meta = LockMetadata { v: 1 }; -+ write!(ok, "{}", serde_json::to_string(&lock_meta).unwrap())?; - - Ok(unpack_dir.to_path_buf()) - } -@@ -872,3 +900,16 @@ mod tests { - assert_eq!(make_dep_prefix("aBcDe"), "aB/cD"); - } - } -+ -+/// Set the current [`umask`] value for the given tarball. No-op on non-Unix -+/// platforms. -+/// -+/// On Windows, tar only looks at user permissions and tries to set the "read -+/// only" attribute, so no-op as well. -+/// -+/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html -+#[allow(unused_variables)] -+fn set_mask(tar: &mut Archive) { -+ #[cfg(unix)] -+ tar.set_mask(crate::util::get_umask()); -+} -diff --git a/src/tools/cargo/src/cargo/util/mod.rs b/src/tools/cargo/src/cargo/util/mod.rs -index 9881332ec..7fb491622 100644 ---- a/src/tools/cargo/src/cargo/util/mod.rs -+++ b/src/tools/cargo/src/cargo/util/mod.rs -@@ -122,3 +122,21 @@ pub fn truncate_with_ellipsis(s: &str, max_width: usize) -> String { - } - prefix - } -+/// Get the current [`umask`] value. -+/// -+/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html -+#[cfg(unix)] -+pub fn get_umask() -> u32 { -+ // SAFETY: Syscalls are unsafe. Calling `umask` twice is even unsafer for -+ // multithreading program, since it doesn't provide a way to retrive the -+ // value without modifications. We use a `lazy_static` here to ensure -+ // it only gets call once during the entire program lifetime. -+ lazy_static::lazy_static! { -+ static ref UMASK: libc::mode_t = unsafe { -+ let umask = libc::umask(0o022); -+ libc::umask(umask); -+ umask -+ }; -+ } -+ *UMASK as u32 // it is u16 on macos -+} -diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs -index 60c52fd54..ad95e1437 100644 ---- a/src/tools/cargo/tests/testsuite/registry.rs -+++ b/src/tools/cargo/tests/testsuite/registry.rs -@@ -2594,7 +2594,7 @@ fn package_lock_inside_package_is_overwritten() { - .join("bar-0.0.1") - .join(".cargo-ok"); - -- assert_eq!(ok.metadata().unwrap().len(), 2); -+ assert_eq!(ok.metadata().unwrap().len(), 7); - } - - #[cargo_test] -@@ -2634,7 +2634,7 @@ fn package_lock_as_a_symlink_inside_package_is_overwritten() { - let librs = pkg_root.join("src/lib.rs"); - - // Is correctly overwritten and doesn't affect the file linked to -- assert_eq!(ok.metadata().unwrap().len(), 2); -+ assert_eq!(ok.metadata().unwrap().len(), 7); - assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}"); - } - -@@ -2941,3 +2941,129 @@ required by package `foo v0.1.0 ([ROOT]/foo)` - .with_status(101) - .run(); - } -+ -+#[cfg(unix)] -+#[cargo_test] -+fn set_mask_during_unpacking() { -+ use std::os::unix::fs::MetadataExt; -+ -+ Package::new("bar", "1.0.0") -+ .file_with_mode("example.sh", 0o777, "#!/bin/sh") -+ .file_with_mode("src/lib.rs", 0o666, "") -+ .publish(); -+ -+ let p = project() -+ .file( -+ "Cargo.toml", -+ r#" -+ [package] -+ name = "foo" -+ version = "0.1.0" -+ -+ [dependencies] -+ bar = "1.0" -+ "#, -+ ) -+ .file("src/lib.rs", "") -+ .build(); -+ -+ p.cargo("fetch") -+ .with_stderr( -+ "\ -+[UPDATING] `dummy-registry` index -+[DOWNLOADING] crates ... -+[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) -+", -+ ) -+ .run(); -+ let src_file_path = |path: &str| { -+ glob::glob( -+ paths::home() -+ .join(".cargo/registry/src/*/bar-1.0.0/") -+ .join(path) -+ .to_str() -+ .unwrap(), -+ ) -+ .unwrap() -+ .next() -+ .unwrap() -+ .unwrap() -+ }; -+ -+ let umask = cargo::util::get_umask(); -+ let metadata = fs::metadata(src_file_path("src/lib.rs")).unwrap(); -+ assert_eq!(metadata.mode() & 0o777, 0o666 & !umask); -+ let metadata = fs::metadata(src_file_path("example.sh")).unwrap(); -+ assert_eq!(metadata.mode() & 0o777, 0o777 & !umask); -+} -+ -+#[cargo_test] -+fn unpack_again_when_cargo_ok_is_unrecognized() { -+ Package::new("bar", "1.0.0").publish(); -+ -+ let p = project() -+ .file( -+ "Cargo.toml", -+ r#" -+ [package] -+ name = "foo" -+ version = "0.1.0" -+ -+ [dependencies] -+ bar = "1.0" -+ "#, -+ ) -+ .file("src/lib.rs", "") -+ .build(); -+ -+ p.cargo("fetch") -+ .with_stderr( -+ "\ -+[UPDATING] `dummy-registry` index -+[DOWNLOADING] crates ... -+[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) -+", -+ ) -+ .run(); -+ -+ let src_file_path = |path: &str| { -+ glob::glob( -+ paths::home() -+ .join(".cargo/registry/src/*/bar-1.0.0/") -+ .join(path) -+ .to_str() -+ .unwrap(), -+ ) -+ .unwrap() -+ .next() -+ .unwrap() -+ .unwrap() -+ }; -+ -+ // Change permissions to simulate the old behavior not respecting umask. -+ let lib_rs = src_file_path("src/lib.rs"); -+ let cargo_ok = src_file_path(".cargo-ok"); -+ let mut perms = fs::metadata(&lib_rs).unwrap().permissions(); -+ assert!(!perms.readonly()); -+ perms.set_readonly(true); -+ fs::set_permissions(&lib_rs, perms).unwrap(); -+ let ok = fs::read_to_string(&cargo_ok).unwrap(); -+ assert_eq!(&ok, r#"{"v":1}"#); -+ -+ p.cargo("fetch").with_stderr("").run(); -+ -+ // Without changing `.cargo-ok`, a unpack won't be triggered. -+ let perms = fs::metadata(&lib_rs).unwrap().permissions(); -+ assert!(perms.readonly()); -+ -+ // Write "ok" to simulate the old behavior and trigger the unpack again. -+ fs::write(&cargo_ok, "ok").unwrap(); -+ -+ p.cargo("fetch").with_stderr("").run(); -+ -+ // Permission has been restored and `.cargo-ok` is in the new format. -+ let perms = fs::metadata(lib_rs).unwrap().permissions(); -+ assert!(!perms.readonly()); -+ let ok = fs::read_to_string(&cargo_ok).unwrap(); -+ assert_eq!(&ok, r#"{"v":1}"#); -+} -diff --git a/src/tools/cargo/tests/testsuite/vendor.rs b/src/tools/cargo/tests/testsuite/vendor.rs -index 8e985e265..db6f114ca 100644 ---- a/src/tools/cargo/tests/testsuite/vendor.rs -+++ b/src/tools/cargo/tests/testsuite/vendor.rs -@@ -890,10 +890,11 @@ fn vendor_preserves_permissions() { - - p.cargo("vendor --respect-source-config").run(); - -+ let umask = cargo::util::get_umask(); - let metadata = fs::metadata(p.root().join("vendor/bar/src/lib.rs")).unwrap(); -- assert_eq!(metadata.mode() & 0o777, 0o644); -+ assert_eq!(metadata.mode() & 0o777, 0o644 & !umask); - let metadata = fs::metadata(p.root().join("vendor/bar/example.sh")).unwrap(); -- assert_eq!(metadata.mode() & 0o777, 0o755); -+ assert_eq!(metadata.mode() & 0o777, 0o755 & !umask); - } - - #[cargo_test] --- -2.27.0 - diff --git a/0001-compiletest-set-the-dylib-path-when-gathering-target.patch b/0001-compiletest-set-the-dylib-path-when-gathering-target.patch deleted file mode 100644 index 54185a7..0000000 --- a/0001-compiletest-set-the-dylib-path-when-gathering-target.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 2bdbc5fbf7f84c62f8c7b1007f3b6fd6d3da06f6 Mon Sep 17 00:00:00 2001 -From: Josh Stone -Date: Fri, 14 Oct 2022 16:11:28 -0700 -Subject: [PATCH] compiletest: set the dylib path when gathering target cfg - -If the compiler is built with `rpath = false`, then it won't find its -own libraries unless the library search path is set. We already do that -while running the actual compiletests, but #100260 added another rustc -command for getting the target cfg. - - Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) - thread 'main' panicked at 'error: failed to get cfg info from "[...]/build/x86_64-unknown-linux-gnu/stage1/bin/rustc" - --- stdout - - --- stderr - [...]/build/x86_64-unknown-linux-gnu/stage1/bin/rustc: error while loading shared libraries: librustc_driver-a2a76dc626cd02d2.so: cannot open shared object file: No such file or directory - ', src/tools/compiletest/src/common.rs:476:13 - -Now the library path is set here as well, so it works without rpath. - -(cherry picked from commit f8a0cc2ca8a644ddb63867526711ba17cb7508c8) ---- - src/tools/compiletest/src/common.rs | 20 +++++++++++--------- - src/tools/compiletest/src/runtest.rs | 27 +++------------------------ - src/tools/compiletest/src/util.rs | 23 +++++++++++++++++++++++ - 3 files changed, 37 insertions(+), 33 deletions(-) - -diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs -index 0260f6848386..9a432f11f82f 100644 ---- a/src/tools/compiletest/src/common.rs -+++ b/src/tools/compiletest/src/common.rs -@@ -2,11 +2,12 @@ - - use std::ffi::OsString; - use std::fmt; -+use std::iter; - use std::path::{Path, PathBuf}; - use std::process::Command; - use std::str::FromStr; - --use crate::util::PathBufExt; -+use crate::util::{add_dylib_path, PathBufExt}; - use lazycell::LazyCell; - use test::ColorConfig; - -@@ -385,8 +386,7 @@ pub fn run_enabled(&self) -> bool { - } - - fn target_cfg(&self) -> &TargetCfg { -- self.target_cfg -- .borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target, &self.target_rustcflags)) -+ self.target_cfg.borrow_with(|| TargetCfg::new(self)) - } - - pub fn matches_arch(&self, arch: &str) -> bool { -@@ -457,21 +457,23 @@ pub enum Endian { - } - - impl TargetCfg { -- fn new(rustc_path: &Path, target: &str, target_rustcflags: &Vec) -> TargetCfg { -- let output = match Command::new(rustc_path) -+ fn new(config: &Config) -> TargetCfg { -+ let mut command = Command::new(&config.rustc_path); -+ add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); -+ let output = match command - .arg("--print=cfg") - .arg("--target") -- .arg(target) -- .args(target_rustcflags) -+ .arg(&config.target) -+ .args(&config.target_rustcflags) - .output() - { - Ok(output) => output, -- Err(e) => panic!("error: failed to get cfg info from {:?}: {e}", rustc_path), -+ Err(e) => panic!("error: failed to get cfg info from {:?}: {e}", config.rustc_path), - }; - if !output.status.success() { - panic!( - "error: failed to get cfg info from {:?}\n--- stdout\n{}\n--- stderr\n{}", -- rustc_path, -+ config.rustc_path, - String::from_utf8(output.stdout).unwrap(), - String::from_utf8(output.stderr).unwrap(), - ); -diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs -index 8af5f1da694b..f8903f754f09 100644 ---- a/src/tools/compiletest/src/runtest.rs -+++ b/src/tools/compiletest/src/runtest.rs -@@ -13,7 +13,7 @@ - use crate::header::TestProps; - use crate::json; - use crate::read2::read2_abbreviated; --use crate::util::{logv, PathBufExt}; -+use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt}; - use crate::ColorConfig; - use regex::{Captures, Regex}; - use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; -@@ -26,6 +26,7 @@ - use std::hash::{Hash, Hasher}; - use std::io::prelude::*; - use std::io::{self, BufReader}; -+use std::iter; - use std::path::{Path, PathBuf}; - use std::process::{Child, Command, ExitStatus, Output, Stdio}; - use std::str; -@@ -72,19 +73,6 @@ fn disable_error_reporting R, R>(f: F) -> R { - f() - } - --/// The name of the environment variable that holds dynamic library locations. --pub fn dylib_env_var() -> &'static str { -- if cfg!(windows) { -- "PATH" -- } else if cfg!(target_os = "macos") { -- "DYLD_LIBRARY_PATH" -- } else if cfg!(target_os = "haiku") { -- "LIBRARY_PATH" -- } else { -- "LD_LIBRARY_PATH" -- } --} -- - /// The platform-specific library name - pub fn get_lib_name(lib: &str, dylib: bool) -> String { - // In some casess (e.g. MUSL), we build a static -@@ -1811,16 +1799,7 @@ fn compose_and_run( - - // Need to be sure to put both the lib_path and the aux path in the dylib - // search path for the child. -- let mut path = -- env::split_paths(&env::var_os(dylib_env_var()).unwrap_or_default()).collect::>(); -- if let Some(p) = aux_path { -- path.insert(0, PathBuf::from(p)) -- } -- path.insert(0, PathBuf::from(lib_path)); -- -- // Add the new dylib search path var -- let newpath = env::join_paths(&path).unwrap(); -- command.env(dylib_env_var(), newpath); -+ add_dylib_path(&mut command, iter::once(lib_path).chain(aux_path)); - - let mut child = disable_error_reporting(|| command.spawn()) - .unwrap_or_else(|_| panic!("failed to exec `{:?}`", &command)); -diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs -index e5ff0906be8a..ec36f1e4fb72 100644 ---- a/src/tools/compiletest/src/util.rs -+++ b/src/tools/compiletest/src/util.rs -@@ -2,6 +2,7 @@ - use std::env; - use std::ffi::OsStr; - use std::path::PathBuf; -+use std::process::Command; - - use tracing::*; - -@@ -111,3 +112,25 @@ fn with_extra_extension>(&self, extension: S) -> PathBuf { - } - } - } -+ -+/// The name of the environment variable that holds dynamic library locations. -+pub fn dylib_env_var() -> &'static str { -+ if cfg!(windows) { -+ "PATH" -+ } else if cfg!(target_os = "macos") { -+ "DYLD_LIBRARY_PATH" -+ } else if cfg!(target_os = "haiku") { -+ "LIBRARY_PATH" -+ } else { -+ "LD_LIBRARY_PATH" -+ } -+} -+ -+/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. -+/// If the dylib_path_var is already set for this cmd, the old value will be overwritten! -+pub fn add_dylib_path(cmd: &mut Command, paths: impl Iterator>) { -+ let path_env = env::var_os(dylib_env_var()); -+ let old_paths = path_env.as_ref().map(env::split_paths); -+ let new_paths = paths.map(Into::into).chain(old_paths.into_iter().flatten()); -+ cmd.env(dylib_env_var(), env::join_paths(new_paths).unwrap()); -+} --- -2.38.1 - diff --git a/0001-update-vendor-tar-to-0.4.39.patch b/0001-update-vendor-tar-to-0.4.39.patch deleted file mode 100644 index 4bb2eb4..0000000 --- a/0001-update-vendor-tar-to-0.4.39.patch +++ /dev/null @@ -1,971 +0,0 @@ -From 705af5d2e609e685d4a5bc0ed68fc9d0cafafb8c Mon Sep 17 00:00:00 2001 -From: Liwei Ge -Date: Thu, 17 Aug 2023 15:25:40 +0800 -Subject: [PATCH] update vendor tar to 0.4.39 - ---- - Cargo.lock | 4 +- - src/bootstrap/Cargo.lock | 4 +- - src/tools/cargo/Cargo.toml | 4 +- - vendor/tar/.cargo-checksum.json | 2 +- - vendor/tar/Cargo.lock | 207 +++++++++++++++++++++----------- - vendor/tar/Cargo.toml | 18 ++- - vendor/tar/src/archive.rs | 29 +++++ - vendor/tar/src/entry.rs | 180 ++++++++++++++++++++++++--- - vendor/tar/tests/all.rs | 107 ++++++++++++++++- - vendor/tar/tests/entry.rs | 31 +++++ - 10 files changed, 485 insertions(+), 101 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index f89c3e3a8..216874ee8 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -4792,9 +4792,9 @@ dependencies = [ - - [[package]] - name = "tar" --version = "0.4.38" -+version = "0.4.39" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" -+checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" - dependencies = [ - "filetime", - "libc", -diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock -index baecca44c..5b0147b1d 100644 ---- a/src/bootstrap/Cargo.lock -+++ b/src/bootstrap/Cargo.lock -@@ -622,9 +622,9 @@ dependencies = [ - - [[package]] - name = "tar" --version = "0.4.38" -+version = "0.4.39" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" -+checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" - dependencies = [ - "filetime", - "libc", -diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml -index 4b4f328e1..78a8f5fdf 100644 ---- a/src/tools/cargo/Cargo.toml -+++ b/src/tools/cargo/Cargo.toml -@@ -58,7 +58,7 @@ serde-value = "0.7.0" - sha1 = "0.10.5" - shell-escape = "0.1.4" - strip-ansi-escapes = "0.1.0" --tar = { version = "0.4.38", default-features = false } -+tar = { version = "0.4.39", default-features = false } - tempfile = "3.0" - termcolor = "1.1" - toml_edit = { version = "0.15.0", features = ["serde", "easy", "perf"] } -@@ -108,7 +108,7 @@ snapbox = { version = "0.3.0", features = ["diff", "path"] } - - [build-dependencies] - flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } --tar = { version = "0.4.38", default-features = false } -+tar = { version = "0.4.39", default-features = false } - - [[bin]] - name = "cargo" -diff --git a/vendor/tar/.cargo-checksum.json b/vendor/tar/.cargo-checksum.json -index 508f784e8..792994f55 100644 ---- a/vendor/tar/.cargo-checksum.json -+++ b/vendor/tar/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"8353c71aa4d394efa7aaeac3004d0a16fd0c7124b7bd57ea91ba87a7b2015f15","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"85a0091e02690c62379137988cd9b2689009536a0b941f1ab0581db26e9ebce6","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"705016636f7fdcad4fe20d7d2672be2b94cc53bb05e47628f5212b89e17a40fe","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"567a05d54e369d22efe40f3507a26e21f7878b95bd05c811250b2c350761791b","tests/entry.rs":"c1411ee09da9edb659b508867f0960e804966dfd33801f4a7afaefda331479dd","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"} -\ No newline at end of file -+{"files":{"Cargo.lock":"a074bb3491e0d988605218e794859ddb067bb624e793a053645fbbabadde83f6","Cargo.toml":"638559bf51f1b89359ece700138f774bc0a5c1513046e306d6109dc045799b84","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"9238c58f5a253034f490ede4c42de6e1b89986ee6db343920ee34b3dcfa5b238","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"0e4b0438cbc4cbec30a821ce8f23619fe9e53c17022a022de609d642e220193c","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"7a64869cd99a4642f2db71aa7d283633199e59b88ccca112cb467b0739e64e83","tests/entry.rs":"af12d84160e5459ebaee6ecdd68e0c811438c37c0cb881ad210e7f94132b9739","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96"} -\ No newline at end of file -diff --git a/vendor/tar/Cargo.lock b/vendor/tar/Cargo.lock -index dd53b90b5..f63a631ad 100644 ---- a/vendor/tar/Cargo.lock -+++ b/vendor/tar/Cargo.lock -@@ -2,12 +2,24 @@ - # It is not intended for manual editing. - version = 3 - -+[[package]] -+name = "autocfg" -+version = "1.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -+ - [[package]] - name = "bitflags" - version = "1.3.2" - source = "registry+https://github.com/rust-lang/crates.io-index" - checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -+[[package]] -+name = "cc" -+version = "1.0.79" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" -+ - [[package]] - name = "cfg-if" - version = "1.0.0" -@@ -15,101 +27,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" - checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - - [[package]] --name = "filetime" --version = "0.2.15" -+name = "errno" -+version = "0.3.1" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" -+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" - dependencies = [ -- "cfg-if", -+ "errno-dragonfly", - "libc", -- "redox_syscall", -- "winapi", -+ "windows-sys", - ] - - [[package]] --name = "getrandom" --version = "0.2.3" -+name = "errno-dragonfly" -+version = "0.1.2" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" - dependencies = [ -- "cfg-if", -+ "cc", - "libc", -- "wasi", - ] - - [[package]] --name = "libc" --version = "0.2.103" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" -- --[[package]] --name = "ppv-lite86" --version = "0.2.10" -+name = "fastrand" -+version = "1.9.0" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" -+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -+dependencies = [ -+ "instant", -+] - - [[package]] --name = "rand" --version = "0.8.4" -+name = "filetime" -+version = "0.2.21" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -+checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" - dependencies = [ -+ "cfg-if", - "libc", -- "rand_chacha", -- "rand_core", -- "rand_hc", -+ "redox_syscall 0.2.16", -+ "windows-sys", - ] - - [[package]] --name = "rand_chacha" --version = "0.3.1" -+name = "hermit-abi" -+version = "0.3.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" -+ -+[[package]] -+name = "instant" -+version = "0.1.12" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" - dependencies = [ -- "ppv-lite86", -- "rand_core", -+ "cfg-if", - ] - - [[package]] --name = "rand_core" --version = "0.6.3" -+name = "io-lifetimes" -+version = "1.0.11" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" - dependencies = [ -- "getrandom", -+ "hermit-abi", -+ "libc", -+ "windows-sys", - ] - - [[package]] --name = "rand_hc" --version = "0.3.1" -+name = "libc" -+version = "0.2.147" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" -+ -+[[package]] -+name = "linux-raw-sys" -+version = "0.3.8" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" -+ -+[[package]] -+name = "redox_syscall" -+version = "0.2.16" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" - dependencies = [ -- "rand_core", -+ "bitflags", - ] - - [[package]] - name = "redox_syscall" --version = "0.2.10" -+version = "0.3.5" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" - dependencies = [ - "bitflags", - ] - - [[package]] --name = "remove_dir_all" --version = "0.5.3" -+name = "rustix" -+version = "0.37.23" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -+checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" - dependencies = [ -- "winapi", -+ "bitflags", -+ "errno", -+ "io-lifetimes", -+ "libc", -+ "linux-raw-sys", -+ "windows-sys", - ] - - [[package]] - name = "tar" --version = "0.4.38" -+version = "0.4.39" - dependencies = [ - "filetime", - "libc", -@@ -119,51 +150,89 @@ dependencies = [ - - [[package]] - name = "tempfile" --version = "3.2.0" -+version = "3.6.0" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -+checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" - dependencies = [ -+ "autocfg", - "cfg-if", -- "libc", -- "rand", -- "redox_syscall", -- "remove_dir_all", -- "winapi", -+ "fastrand", -+ "redox_syscall 0.3.5", -+ "rustix", -+ "windows-sys", - ] - - [[package]] --name = "wasi" --version = "0.10.2+wasi-snapshot-preview1" -+name = "windows-sys" -+version = "0.48.0" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" -+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -+dependencies = [ -+ "windows-targets", -+] - - [[package]] --name = "winapi" --version = "0.3.9" -+name = "windows-targets" -+version = "0.48.1" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -+checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" - dependencies = [ -- "winapi-i686-pc-windows-gnu", -- "winapi-x86_64-pc-windows-gnu", -+ "windows_aarch64_gnullvm", -+ "windows_aarch64_msvc", -+ "windows_i686_gnu", -+ "windows_i686_msvc", -+ "windows_x86_64_gnu", -+ "windows_x86_64_gnullvm", -+ "windows_x86_64_msvc", - ] - - [[package]] --name = "winapi-i686-pc-windows-gnu" --version = "0.4.0" -+name = "windows_aarch64_gnullvm" -+version = "0.48.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -+ -+[[package]] -+name = "windows_aarch64_msvc" -+version = "0.48.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -+ -+[[package]] -+name = "windows_i686_gnu" -+version = "0.48.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -+ -+[[package]] -+name = "windows_i686_msvc" -+version = "0.48.0" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - - [[package]] --name = "winapi-x86_64-pc-windows-gnu" --version = "0.4.0" -+name = "windows_x86_64_gnu" -+version = "0.48.0" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -+ -+[[package]] -+name = "windows_x86_64_gnullvm" -+version = "0.48.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -+ -+[[package]] -+name = "windows_x86_64_msvc" -+version = "0.48.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - - [[package]] - name = "xattr" --version = "0.2.2" -+version = "0.2.3" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -+checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" - dependencies = [ - "libc", - ] -diff --git a/vendor/tar/Cargo.toml b/vendor/tar/Cargo.toml -index 23771b564..6225b778f 100644 ---- a/vendor/tar/Cargo.toml -+++ b/vendor/tar/Cargo.toml -@@ -12,23 +12,35 @@ - [package] - edition = "2018" - name = "tar" --version = "0.4.38" -+version = "0.4.39" - authors = ["Alex Crichton "] - exclude = ["tests/archives/*"] --description = "A Rust implementation of a TAR file reader and writer. This library does not\ncurrently handle compression, but it is abstract over all I/O readers and\nwriters. Additionally, great lengths are taken to ensure that the entire\ncontents are never required to be entirely resident in memory all at once.\n" -+description = """ -+A Rust implementation of a TAR file reader and writer. This library does not -+currently handle compression, but it is abstract over all I/O readers and -+writers. Additionally, great lengths are taken to ensure that the entire -+contents are never required to be entirely resident in memory all at once. -+""" - homepage = "https://github.com/alexcrichton/tar-rs" - documentation = "https://docs.rs/tar" - readme = "README.md" --keywords = ["tar", "tarfile", "encoding"] -+keywords = [ -+ "tar", -+ "tarfile", -+ "encoding", -+] - license = "MIT/Apache-2.0" - repository = "https://github.com/alexcrichton/tar-rs" -+ - [dependencies.filetime] - version = "0.2.8" -+ - [dev-dependencies.tempfile] - version = "3" - - [features] - default = ["xattr"] -+ - [target."cfg(unix)".dependencies.libc] - version = "0.2" - -diff --git a/vendor/tar/src/archive.rs b/vendor/tar/src/archive.rs -index 1bed51249..c7a9d9803 100644 ---- a/vendor/tar/src/archive.rs -+++ b/vendor/tar/src/archive.rs -@@ -22,8 +22,10 @@ pub struct Archive { - - pub struct ArchiveInner { - pos: Cell, -+ mask: u32, - unpack_xattrs: bool, - preserve_permissions: bool, -+ preserve_ownerships: bool, - preserve_mtime: bool, - overwrite: bool, - ignore_zeros: bool, -@@ -52,8 +54,10 @@ impl Archive { - pub fn new(obj: R) -> Archive { - Archive { - inner: ArchiveInner { -+ mask: u32::MIN, - unpack_xattrs: false, - preserve_permissions: false, -+ preserve_ownerships: false, - preserve_mtime: true, - overwrite: true, - ignore_zeros: false, -@@ -106,6 +110,20 @@ impl Archive { - me._unpack(dst.as_ref()) - } - -+ /// Set the mask of the permission bits when unpacking this entry. -+ /// -+ /// The mask will be inverted when applying against a mode, similar to how -+ /// `umask` works on Unix. In logical notation it looks like: -+ /// -+ /// ```text -+ /// new_mode = old_mode & (~mask) -+ /// ``` -+ /// -+ /// The mask is 0 by default and is currently only implemented on Unix. -+ pub fn set_mask(&mut self, mask: u32) { -+ self.inner.mask = mask; -+ } -+ - /// Indicate whether extended file attributes (xattrs on Unix) are preserved - /// when unpacking this archive. - /// -@@ -126,6 +144,15 @@ impl Archive { - self.inner.preserve_permissions = preserve; - } - -+ /// Indicate whether numeric ownership ids (like uid and gid on Unix) -+ /// are preserved when unpacking this entry. -+ /// -+ /// This flag is disabled by default and is currently only implemented on -+ /// Unix. -+ pub fn set_preserve_ownerships(&mut self, preserve: bool) { -+ self.inner.preserve_ownerships = preserve; -+ } -+ - /// Indicate whether files and symlinks should be overwritten on extraction. - pub fn set_overwrite(&mut self, overwrite: bool) { - self.inner.overwrite = overwrite; -@@ -304,10 +331,12 @@ impl<'a> EntriesFields<'a> { - long_pathname: None, - long_linkname: None, - pax_extensions: None, -+ mask: self.archive.inner.mask, - unpack_xattrs: self.archive.inner.unpack_xattrs, - preserve_permissions: self.archive.inner.preserve_permissions, - preserve_mtime: self.archive.inner.preserve_mtime, - overwrite: self.archive.inner.overwrite, -+ preserve_ownerships: self.archive.inner.preserve_ownerships, - }; - - // Store where the next entry is, rounding up by 512 bytes (the size of -diff --git a/vendor/tar/src/entry.rs b/vendor/tar/src/entry.rs -index 8f0b62acf..c81554fcb 100644 ---- a/vendor/tar/src/entry.rs -+++ b/vendor/tar/src/entry.rs -@@ -31,6 +31,7 @@ pub struct EntryFields<'a> { - pub long_pathname: Option>, - pub long_linkname: Option>, - pub pax_extensions: Option>, -+ pub mask: u32, - pub header: Header, - pub size: u64, - pub header_pos: u64, -@@ -38,6 +39,7 @@ pub struct EntryFields<'a> { - pub data: Vec>, - pub unpack_xattrs: bool, - pub preserve_permissions: bool, -+ pub preserve_ownerships: bool, - pub preserve_mtime: bool, - pub overwrite: bool, - } -@@ -230,6 +232,20 @@ impl<'a, R: Read> Entry<'a, R> { - self.fields.unpack_in(dst.as_ref()) - } - -+ /// Set the mask of the permission bits when unpacking this entry. -+ /// -+ /// The mask will be inverted when applying against a mode, similar to how -+ /// `umask` works on Unix. In logical notation it looks like: -+ /// -+ /// ```text -+ /// new_mode = old_mode & (~mask) -+ /// ``` -+ /// -+ /// The mask is 0 by default and is currently only implemented on Unix. -+ pub fn set_mask(&mut self, mask: u32) { -+ self.fields.mask = mask; -+ } -+ - /// Indicate whether extended file attributes (xattrs on Unix) are preserved - /// when unpacking this entry. - /// -@@ -444,13 +460,51 @@ impl<'a> EntryFields<'a> { - - /// Returns access to the header of this entry in the archive. - fn unpack(&mut self, target_base: Option<&Path>, dst: &Path) -> io::Result { -+ fn set_perms_ownerships( -+ dst: &Path, -+ f: Option<&mut std::fs::File>, -+ header: &Header, -+ mask: u32, -+ perms: bool, -+ ownerships: bool, -+ ) -> io::Result<()> { -+ // ownerships need to be set first to avoid stripping SUID bits in the permissions ... -+ if ownerships { -+ set_ownerships(dst, &f, header.uid()?, header.gid()?)?; -+ } -+ // ... then set permissions, SUID bits set here is kept -+ if let Ok(mode) = header.mode() { -+ set_perms(dst, f, mode, mask, perms)?; -+ } -+ -+ Ok(()) -+ } -+ -+ fn get_mtime(header: &Header) -> Option { -+ header.mtime().ok().map(|mtime| { -+ // For some more information on this see the comments in -+ // `Header::fill_platform_from`, but the general idea is that -+ // we're trying to avoid 0-mtime files coming out of archives -+ // since some tools don't ingest them well. Perhaps one day -+ // when Cargo stops working with 0-mtime archives we can remove -+ // this. -+ let mtime = if mtime == 0 { 1 } else { mtime }; -+ FileTime::from_unix_time(mtime as i64, 0) -+ }) -+ } -+ - let kind = self.header.entry_type(); - - if kind.is_dir() { - self.unpack_dir(dst)?; -- if let Ok(mode) = self.header.mode() { -- set_perms(dst, None, mode, self.preserve_permissions)?; -- } -+ set_perms_ownerships( -+ dst, -+ None, -+ &self.header, -+ self.mask, -+ self.preserve_permissions, -+ self.preserve_ownerships, -+ )?; - return Ok(Unpacked::__Nonexhaustive); - } else if kind.is_hard_link() || kind.is_symlink() { - let src = match self.link_name()? { -@@ -522,7 +576,14 @@ impl<'a> EntryFields<'a> { - ), - ) - })?; -- }; -+ if self.preserve_mtime { -+ if let Some(mtime) = get_mtime(&self.header) { -+ filetime::set_symlink_file_times(dst, mtime, mtime).map_err(|e| { -+ TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) -+ })?; -+ } -+ } -+ } - return Ok(Unpacked::__Nonexhaustive); - - #[cfg(target_arch = "wasm32")] -@@ -553,9 +614,14 @@ impl<'a> EntryFields<'a> { - // Only applies to old headers. - if self.header.as_ustar().is_none() && self.path_bytes().ends_with(b"/") { - self.unpack_dir(dst)?; -- if let Ok(mode) = self.header.mode() { -- set_perms(dst, None, mode, self.preserve_permissions)?; -- } -+ set_perms_ownerships( -+ dst, -+ None, -+ &self.header, -+ self.mask, -+ self.preserve_permissions, -+ self.preserve_ownerships, -+ )?; - return Ok(Unpacked::__Nonexhaustive); - } - -@@ -618,35 +684,105 @@ impl<'a> EntryFields<'a> { - })?; - - if self.preserve_mtime { -- if let Ok(mtime) = self.header.mtime() { -- // For some more information on this see the comments in -- // `Header::fill_platform_from`, but the general idea is that -- // we're trying to avoid 0-mtime files coming out of archives -- // since some tools don't ingest them well. Perhaps one day -- // when Cargo stops working with 0-mtime archives we can remove -- // this. -- let mtime = if mtime == 0 { 1 } else { mtime }; -- let mtime = FileTime::from_unix_time(mtime as i64, 0); -+ if let Some(mtime) = get_mtime(&self.header) { - filetime::set_file_handle_times(&f, Some(mtime), Some(mtime)).map_err(|e| { - TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) - })?; - } - } -- if let Ok(mode) = self.header.mode() { -- set_perms(dst, Some(&mut f), mode, self.preserve_permissions)?; -- } -+ set_perms_ownerships( -+ dst, -+ Some(&mut f), -+ &self.header, -+ self.mask, -+ self.preserve_permissions, -+ self.preserve_ownerships, -+ )?; - if self.unpack_xattrs { - set_xattrs(self, dst)?; - } - return Ok(Unpacked::File(f)); - -+ fn set_ownerships( -+ dst: &Path, -+ f: &Option<&mut std::fs::File>, -+ uid: u64, -+ gid: u64, -+ ) -> Result<(), TarError> { -+ _set_ownerships(dst, f, uid, gid).map_err(|e| { -+ TarError::new( -+ format!( -+ "failed to set ownerships to uid={:?}, gid={:?} \ -+ for `{}`", -+ uid, -+ gid, -+ dst.display() -+ ), -+ e, -+ ) -+ }) -+ } -+ -+ #[cfg(unix)] -+ fn _set_ownerships( -+ dst: &Path, -+ f: &Option<&mut std::fs::File>, -+ uid: u64, -+ gid: u64, -+ ) -> io::Result<()> { -+ use std::convert::TryInto; -+ use std::os::unix::prelude::*; -+ -+ let uid: libc::uid_t = uid.try_into().map_err(|_| { -+ io::Error::new(io::ErrorKind::Other, format!("UID {} is too large!", uid)) -+ })?; -+ let gid: libc::gid_t = gid.try_into().map_err(|_| { -+ io::Error::new(io::ErrorKind::Other, format!("GID {} is too large!", gid)) -+ })?; -+ match f { -+ Some(f) => unsafe { -+ let fd = f.as_raw_fd(); -+ if libc::fchown(fd, uid, gid) != 0 { -+ Err(io::Error::last_os_error()) -+ } else { -+ Ok(()) -+ } -+ }, -+ None => unsafe { -+ let path = std::ffi::CString::new(dst.as_os_str().as_bytes()).map_err(|e| { -+ io::Error::new( -+ io::ErrorKind::Other, -+ format!("path contains null character: {:?}", e), -+ ) -+ })?; -+ if libc::lchown(path.as_ptr(), uid, gid) != 0 { -+ Err(io::Error::last_os_error()) -+ } else { -+ Ok(()) -+ } -+ }, -+ } -+ } -+ -+ // Windows does not support posix numeric ownership IDs -+ #[cfg(any(windows, target_arch = "wasm32"))] -+ fn _set_ownerships( -+ _: &Path, -+ _: &Option<&mut std::fs::File>, -+ _: u64, -+ _: u64, -+ ) -> io::Result<()> { -+ Ok(()) -+ } -+ - fn set_perms( - dst: &Path, - f: Option<&mut std::fs::File>, - mode: u32, -+ mask: u32, - preserve: bool, - ) -> Result<(), TarError> { -- _set_perms(dst, f, mode, preserve).map_err(|e| { -+ _set_perms(dst, f, mode, mask, preserve).map_err(|e| { - TarError::new( - format!( - "failed to set permissions to {:o} \ -@@ -664,11 +800,13 @@ impl<'a> EntryFields<'a> { - dst: &Path, - f: Option<&mut std::fs::File>, - mode: u32, -+ mask: u32, - preserve: bool, - ) -> io::Result<()> { - use std::os::unix::prelude::*; - - let mode = if preserve { mode } else { mode & 0o777 }; -+ let mode = mode & !mask; - let perm = fs::Permissions::from_mode(mode as _); - match f { - Some(f) => f.set_permissions(perm), -@@ -681,6 +819,7 @@ impl<'a> EntryFields<'a> { - dst: &Path, - f: Option<&mut std::fs::File>, - mode: u32, -+ _mask: u32, - _preserve: bool, - ) -> io::Result<()> { - if mode & 0o200 == 0o200 { -@@ -706,6 +845,7 @@ impl<'a> EntryFields<'a> { - dst: &Path, - f: Option<&mut std::fs::File>, - mode: u32, -+ mask: u32, - _preserve: bool, - ) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) -diff --git a/vendor/tar/tests/all.rs b/vendor/tar/tests/all.rs -index 11103bd6b..8c5359c56 100644 ---- a/vendor/tar/tests/all.rs -+++ b/vendor/tar/tests/all.rs -@@ -579,10 +579,21 @@ fn extracting_malicious_tarball() { - t!(a.append(&header, io::repeat(1).take(1))); - }; - append("/tmp/abs_evil.txt"); -- append("//tmp/abs_evil2.txt"); -+ // std parse `//` as UNC path, see rust-lang/rust#100833 -+ append( -+ #[cfg(not(windows))] -+ "//tmp/abs_evil2.txt", -+ #[cfg(windows)] -+ "C://tmp/abs_evil2.txt", -+ ); - append("///tmp/abs_evil3.txt"); - append("/./tmp/abs_evil4.txt"); -- append("//./tmp/abs_evil5.txt"); -+ append( -+ #[cfg(not(windows))] -+ "//./tmp/abs_evil5.txt", -+ #[cfg(windows)] -+ "C://./tmp/abs_evil5.txt", -+ ); - append("///./tmp/abs_evil6.txt"); - append("/../tmp/rel_evil.txt"); - append("../rel_evil2.txt"); -@@ -757,6 +768,40 @@ fn backslash_treated_well() { - assert!(fs::metadata(td.path().join("foo\\bar")).is_ok()); - } - -+#[test] -+#[cfg(unix)] -+fn set_mask() { -+ use ::std::os::unix::fs::PermissionsExt; -+ let mut ar = tar::Builder::new(Vec::new()); -+ -+ let mut header = tar::Header::new_gnu(); -+ header.set_size(0); -+ header.set_entry_type(tar::EntryType::Regular); -+ t!(header.set_path("foo")); -+ header.set_mode(0o777); -+ header.set_cksum(); -+ t!(ar.append(&header, &[][..])); -+ -+ let mut header = tar::Header::new_gnu(); -+ header.set_size(0); -+ header.set_entry_type(tar::EntryType::Regular); -+ t!(header.set_path("bar")); -+ header.set_mode(0o421); -+ header.set_cksum(); -+ t!(ar.append(&header, &[][..])); -+ -+ let td = t!(TempBuilder::new().prefix("tar-rs").tempdir()); -+ let bytes = t!(ar.into_inner()); -+ let mut ar = tar::Archive::new(&bytes[..]); -+ ar.set_mask(0o211); -+ t!(ar.unpack(td.path())); -+ -+ let md = t!(fs::metadata(td.path().join("foo"))); -+ assert_eq!(md.permissions().mode(), 0o100566); -+ let md = t!(fs::metadata(td.path().join("bar"))); -+ assert_eq!(md.permissions().mode(), 0o100420); -+} -+ - #[cfg(unix)] - #[test] - fn nul_bytes_in_path() { -@@ -792,6 +837,10 @@ fn unpack_links() { - - let md = t!(fs::symlink_metadata(td.path().join("lnk"))); - assert!(md.file_type().is_symlink()); -+ -+ let mtime = FileTime::from_last_modification_time(&md); -+ assert_eq!(mtime.unix_seconds(), 1448291033); -+ - assert_eq!( - &*t!(fs::read_link(td.path().join("lnk"))), - Path::new("file") -@@ -1385,3 +1434,57 @@ fn header_size_overflow() { - err - ); - } -+ -+#[test] -+#[cfg(unix)] -+fn ownership_preserving() { -+ use std::os::unix::prelude::*; -+ -+ let mut rdr = Vec::new(); -+ let mut ar = Builder::new(&mut rdr); -+ let data: &[u8] = &[]; -+ let mut header = Header::new_gnu(); -+ // file 1 with uid = 580800000, gid = 580800000 -+ header.set_gid(580800000); -+ header.set_uid(580800000); -+ t!(header.set_path("iamuid580800000")); -+ header.set_size(0); -+ header.set_cksum(); -+ t!(ar.append(&header, data)); -+ // file 2 with uid = 580800001, gid = 580800000 -+ header.set_uid(580800001); -+ t!(header.set_path("iamuid580800001")); -+ header.set_cksum(); -+ t!(ar.append(&header, data)); -+ // file 3 with uid = 580800002, gid = 580800002 -+ header.set_gid(580800002); -+ header.set_uid(580800002); -+ t!(header.set_path("iamuid580800002")); -+ header.set_cksum(); -+ t!(ar.append(&header, data)); -+ t!(ar.finish()); -+ -+ let rdr = Cursor::new(t!(ar.into_inner())); -+ let td = t!(TempBuilder::new().prefix("tar-rs").tempdir()); -+ let mut ar = Archive::new(rdr); -+ ar.set_preserve_ownerships(true); -+ -+ if unsafe { libc::getuid() } == 0 { -+ assert!(ar.unpack(td.path()).is_ok()); -+ // validate against premade files -+ // iamuid580800001 has this ownership: 580800001:580800000 -+ let meta = std::fs::metadata(td.path().join("iamuid580800000")).unwrap(); -+ assert_eq!(meta.uid(), 580800000); -+ assert_eq!(meta.gid(), 580800000); -+ let meta = std::fs::metadata(td.path().join("iamuid580800001")).unwrap(); -+ assert_eq!(meta.uid(), 580800001); -+ assert_eq!(meta.gid(), 580800000); -+ let meta = std::fs::metadata(td.path().join("iamuid580800002")).unwrap(); -+ assert_eq!(meta.uid(), 580800002); -+ assert_eq!(meta.gid(), 580800002); -+ } else { -+ // it's not possible to unpack tar while preserving ownership -+ // without root permissions -+ assert!(ar.unpack(td.path()).is_err()); -+ } -+} -diff --git a/vendor/tar/tests/entry.rs b/vendor/tar/tests/entry.rs -index fa8eeaee7..62df663e8 100644 ---- a/vendor/tar/tests/entry.rs -+++ b/vendor/tar/tests/entry.rs -@@ -180,6 +180,37 @@ fn directory_maintains_permissions() { - assert_eq!(md.permissions().mode(), 0o40777); - } - -+#[test] -+#[cfg(unix)] -+fn set_entry_mask() { -+ use ::std::os::unix::fs::PermissionsExt; -+ -+ let mut ar = tar::Builder::new(Vec::new()); -+ -+ let mut header = tar::Header::new_gnu(); -+ header.set_size(0); -+ header.set_entry_type(tar::EntryType::Regular); -+ t!(header.set_path("foo")); -+ header.set_mode(0o777); -+ header.set_cksum(); -+ t!(ar.append(&header, &[][..])); -+ -+ let bytes = t!(ar.into_inner()); -+ let mut ar = tar::Archive::new(&bytes[..]); -+ let td = t!(Builder::new().prefix("tar").tempdir()); -+ let foo_path = td.path().join("foo"); -+ -+ let mut entries = t!(ar.entries()); -+ let mut foo = t!(entries.next().unwrap()); -+ foo.set_mask(0o027); -+ t!(foo.unpack(&foo_path)); -+ -+ let f = t!(File::open(foo_path)); -+ let md = t!(f.metadata()); -+ assert!(md.is_file()); -+ assert_eq!(md.permissions().mode(), 0o100750); -+} -+ - #[test] - #[cfg(not(windows))] // dangling symlinks have weird permissions - fn modify_link_just_created() { --- -2.27.0 - diff --git a/0001-vendor-cc-add-loongarch64-support.patch b/0001-vendor-cc-add-loongarch64-support.patch deleted file mode 100644 index 5c230cb..0000000 --- a/0001-vendor-cc-add-loongarch64-support.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 83e9097a192bf123df9b8313e9e8acd91e0c2e5d Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Thu, 7 Jul 2022 10:56:12 +0800 -Subject: [PATCH 1/6] vendor: cc: add loongarch64 support - ---- - vendor/cc/.cargo-checksum.json | 2 +- - vendor/cc/src/lib.rs | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/vendor/cc/.cargo-checksum.json b/vendor/cc/.cargo-checksum.json -index a7f8f2fe7..89b178159 100644 ---- a/vendor/cc/.cargo-checksum.json -+++ b/vendor/cc/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"Cargo.lock":"739aae86d1e7096fc84b9a6273cc49635503a4ee87b3a4b6601f569880866b29","Cargo.toml":"ccfa92dd53511178ef95aa87b2dcbdd45e23f9f8a8454e455d7da8e08feab4b5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"38970d678de0efb4b5e2978265daa8a613a1db35fc42e669621b03fc56d5b138","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"4645453198766c7486fc9b8782b06cfd0f94cbbcb3482413173e73234a447518","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"} -\ No newline at end of file -+{"files":{"Cargo.lock":"739aae86d1e7096fc84b9a6273cc49635503a4ee87b3a4b6601f569880866b29","Cargo.toml":"ccfa92dd53511178ef95aa87b2dcbdd45e23f9f8a8454e455d7da8e08feab4b5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"8313001f13ddc7b8959a81453cc8f1dcf0f95e47a283bb2c6048ba7b143acef8","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"4645453198766c7486fc9b8782b06cfd0f94cbbcb3482413173e73234a447518","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"} -diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs -index e3a2b98b0..30594a895 100644 ---- a/vendor/cc/src/lib.rs -+++ b/vendor/cc/src/lib.rs -@@ -2581,6 +2581,7 @@ impl Build { - ]), // explicit None if not found, so caller knows to fall back - "i686-unknown-linux-musl" => Some("musl"), - "i686-unknown-netbsd" => Some("i486--netbsdelf"), -+ "loongarch64-unknown-linux-gnu" => Some("loongarch64-linux-gnu"), - "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), - "mips-unknown-linux-musl" => Some("mips-linux-musl"), - "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), --- -2.41.0 - diff --git a/0002-vendor-libc-update-loongarch64-support.patch b/0002-vendor-libc-update-loongarch64-support.patch deleted file mode 100644 index 90e5c15..0000000 --- a/0002-vendor-libc-update-loongarch64-support.patch +++ /dev/null @@ -1,221 +0,0 @@ -From fa9cbadfe8bca161db1c2866dbb22219b4f7e48c Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Sun, 25 Jun 2023 16:15:14 +0800 -Subject: [PATCH 2/6] vendor: libc: update loongarch64 support - ---- - vendor/libc-0.2.126/.cargo-checksum.json | 2 +- - .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ - .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ - vendor/libc-0.2.127/.cargo-checksum.json | 2 +- - .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ - .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ - vendor/libc/.cargo-checksum.json | 2 +- - .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ - .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ - 9 files changed, 102 insertions(+), 3 deletions(-) - -diff --git a/vendor/libc-0.2.126/.cargo-checksum.json b/vendor/libc-0.2.126/.cargo-checksum.json -index 26956a434..2db39a0c3 100644 ---- a/vendor/libc-0.2.126/.cargo-checksum.json -+++ b/vendor/libc-0.2.126/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"6a0abcfcbc1d9fb00a356343043a161f5b84b3f780cb0f02df4627d022b14b7f","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"41f9743021d9e5ed74ede55c94057cf6867a322a13b25a5d524b966656a08e38","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"bc8c46531bd1a2429f36aaf2bc137b50e42505b798de83f34eecfa94ad89179b","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"3f13d5f9b29d8969dde507661f1637524e21fe3bd34957fc778868f2f3713c46","src/macros.rs":"d7437c2573c4915768ff96b34710a61ee9f63622b23526cddeaeaf6bfb4751a2","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"d7155927fbd1af6dd984a4c6c1a735a5932af828c96818209487eb6ae72d7d7e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"379302e12d30807a1f973c4e2dd2205179d95343ee6fae05f33c9ed45a342799","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"467b66843ab8c1a54b01ae9e90aaf0295b32f54decbdfb64caca84523b488925","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a7345cc3fb7372572efe06848feb2cc246dfc2c2a0cc9ccf434f4c55041a59fa","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"594a0f9e23c4d7702ba38afdba5a0e866be25d692ec0afd66e04d939aa6b3f04","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"cb1560bf8ffcc7b2726a27b433efac90e726292960626f3064bd2c6b7f861a55","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"816a8ef47df60a752a91967627eeccb9ca776dc718ecc53ae902d8edaee0bce9","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"d5833ff9b94daa81d2470df544453212af17530d78c5a7fb912eac915d00f329","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"6454948ea98be86243229f99d67cdc7ca460e16b2a6445663ff4b5b6907c358d","src/unix/linux_like/android/mod.rs":"1247397a7e1b6269e0d2d6df88c6396bc18eb477e3ff293ff57d66a6b1380d94","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"b71d37106750f57bc2dae4e9bcb473ff098ef48235827e41a1687a39825f0aa4","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c4e20b1c63d7a03a6e22aef2046689ef95cc4651011ade7cb94176fcea1dc252","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"1b939aaf3cdf3efc7d3bd53e83e80235530d3ba0c24bb7611d4730d35d457ec1","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"84ad4a663b5fa2498179be8dca96fef5f0446ec1619215ac674424ee394e307d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"cff23db1e0bac8c30052dfed5e89e65bc207471e4bfb3a6fa0a4df62ed9e413e","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"9b05b1fae6bcb7cb6d909b9973977fde01684175f3e26c27dcb44223cc3933d9","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"2efe98b8166270be1624888953fa07da06f08313f15bf4c7dc2eba63f5a790a5","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"ddd223d4f574b2b92072bbdab091f12d8d89d5e05f41076ddfa6bc6af379698f","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"dd4f7a1d66d8501b4a2c4e75e6e9305ed69f1002ae99e410596a6c636878595a","src/unix/mod.rs":"d1b4ba41f9b9c106f6ba8c661b5808824b774a7a7caac7d8938bf50979ba5195","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"976b07a13e195840b67c166a62318abfa9ffc8d5ebbb0358f199dd213ec98d1b","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"} -\ No newline at end of file -+{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"6a0abcfcbc1d9fb00a356343043a161f5b84b3f780cb0f02df4627d022b14b7f","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"41f9743021d9e5ed74ede55c94057cf6867a322a13b25a5d524b966656a08e38","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"bc8c46531bd1a2429f36aaf2bc137b50e42505b798de83f34eecfa94ad89179b","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"3f13d5f9b29d8969dde507661f1637524e21fe3bd34957fc778868f2f3713c46","src/macros.rs":"d7437c2573c4915768ff96b34710a61ee9f63622b23526cddeaeaf6bfb4751a2","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"d7155927fbd1af6dd984a4c6c1a735a5932af828c96818209487eb6ae72d7d7e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"379302e12d30807a1f973c4e2dd2205179d95343ee6fae05f33c9ed45a342799","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"467b66843ab8c1a54b01ae9e90aaf0295b32f54decbdfb64caca84523b488925","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a7345cc3fb7372572efe06848feb2cc246dfc2c2a0cc9ccf434f4c55041a59fa","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"594a0f9e23c4d7702ba38afdba5a0e866be25d692ec0afd66e04d939aa6b3f04","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"cb1560bf8ffcc7b2726a27b433efac90e726292960626f3064bd2c6b7f861a55","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"816a8ef47df60a752a91967627eeccb9ca776dc718ecc53ae902d8edaee0bce9","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"d5833ff9b94daa81d2470df544453212af17530d78c5a7fb912eac915d00f329","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"6454948ea98be86243229f99d67cdc7ca460e16b2a6445663ff4b5b6907c358d","src/unix/linux_like/android/mod.rs":"1247397a7e1b6269e0d2d6df88c6396bc18eb477e3ff293ff57d66a6b1380d94","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"b71d37106750f57bc2dae4e9bcb473ff098ef48235827e41a1687a39825f0aa4","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c4e20b1c63d7a03a6e22aef2046689ef95cc4651011ade7cb94176fcea1dc252","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"1b939aaf3cdf3efc7d3bd53e83e80235530d3ba0c24bb7611d4730d35d457ec1","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"84ad4a663b5fa2498179be8dca96fef5f0446ec1619215ac674424ee394e307d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"cff23db1e0bac8c30052dfed5e89e65bc207471e4bfb3a6fa0a4df62ed9e413e","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"9b05b1fae6bcb7cb6d909b9973977fde01684175f3e26c27dcb44223cc3933d9","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"2efe98b8166270be1624888953fa07da06f08313f15bf4c7dc2eba63f5a790a5","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"ddd223d4f574b2b92072bbdab091f12d8d89d5e05f41076ddfa6bc6af379698f","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"dd4f7a1d66d8501b4a2c4e75e6e9305ed69f1002ae99e410596a6c636878595a","src/unix/mod.rs":"d1b4ba41f9b9c106f6ba8c661b5808824b774a7a7caac7d8938bf50979ba5195","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"976b07a13e195840b67c166a62318abfa9ffc8d5ebbb0358f199dd213ec98d1b","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"} -diff --git a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -index 7ca870fd0..ba3075edd 100644 ---- a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -+++ b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -@@ -5,3 +5,20 @@ s_no_extra_traits! { - priv_: [f64; 4] - } - } -+ -+s! { -+ #[repr(align(8))] -+ pub struct clone_args { -+ pub flags: ::c_ulonglong, -+ pub pidfd: ::c_ulonglong, -+ pub child_tid: ::c_ulonglong, -+ pub parent_tid: ::c_ulonglong, -+ pub exit_signal: ::c_ulonglong, -+ pub stack: ::c_ulonglong, -+ pub stack_size: ::c_ulonglong, -+ pub tls: ::c_ulonglong, -+ pub set_tid: ::c_ulonglong, -+ pub set_tid_size: ::c_ulonglong, -+ pub cgroup: ::c_ulonglong, -+ } -+} -diff --git a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -index 2ed6a9156..ff520e0c6 100644 ---- a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -+++ b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -@@ -247,6 +247,20 @@ align_const! { - }; - } - -+pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; -+pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; -+pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; -+pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; -+pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; -+pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; -+pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; -+pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; -+pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; -+pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; -+pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; -+pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; -+pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; -+ - pub const SYS_io_setup: ::c_long = 0; - pub const SYS_io_destroy: ::c_long = 1; - pub const SYS_io_submit: ::c_long = 2; -@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; - pub const F_OFD_SETLK: ::c_int = 37; - pub const F_OFD_SETLKW: ::c_int = 38; - -+pub const MADV_SOFT_OFFLINE: ::c_int = 101; -+ - pub const EDEADLK: ::c_int = 35; - pub const EDEADLOCK: ::c_int = 35; - pub const ENAMETOOLONG: ::c_int = 36; -diff --git a/vendor/libc-0.2.127/.cargo-checksum.json b/vendor/libc-0.2.127/.cargo-checksum.json -index 3fdf6bc61..29d5859a3 100644 ---- a/vendor/libc-0.2.127/.cargo-checksum.json -+++ b/vendor/libc-0.2.127/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"e1c4b3839177aabdc73c017ee87ba3dcc8025b2730cb0a2c015473f9db99f3fa","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"94cbaad15021e287a1b9546a697b04c1e560f1204b52204ffaaea5975c5d03b9","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"0c5306ea9d12b5261380d733dc3f7624cf259c45638eac8d9222c7e32e134a65","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"e35db24ba69ee0262854916fa19a306bf6c40388f5593ab32d0907e24b5fc5c6","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"d0e8246063cae113806524a63a47c6c0628cc54a3ef03e938e89964f8b4f08b4","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ec229cc7af2511cb510c078e87e90ee2625090bfe94f40eb35f73d79143533aa","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"1e35b4773384ea143810cdce4b96f47108b37446430da30c96a0d1651656d73d","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8f9613e50c2771b33d7cf817a735d536b389ec57f861b9486d870373c768276e","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"228505fa48292e74b06acbed96196801595a4b822da2126a6d6c7fa773cff8bc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"69cc3638c6f7e2086ada7bacf5ea01ce1b7f5d045fd012c6f46b8635d30ce594","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"962741303dc24a5b9653f2e9b0b4ad9eb42fc54daa0a70ca70a7ce175e75094b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"c69c90606d4362f8de89b8816df0ded724ed64b53bf55d15681fde171b7bb361","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c72a08011c32f82919e930e0d89044d8feb65fd41bf80647436756c290344eb8","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f0db9914315d5a3d51bf5ec04a0ae6584f2e1688b9258ce132b617e67d9bd7a9","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"1ca6821fbb94476500d4352908e713b7c698cb7ff0a49997934126391657c573","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"758e222200a8cbb74b1eb01581da92fea895619da866bc383129d4b9a5366aef","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"c7ebabc4e1bdbbd97e5065faa3a57f41f473570920582d979f9e9d4f77448546","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"c3365480375bc258ffe267e7a299d7b3bb542a908bef8881f503ddc25ba8fc1f","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"aabf4582a7ddf17544ee4bfa6a954f0c6e2bd17e707b7ac5266d5697e0da762a","src/unix/mod.rs":"e13a3a67c25c28dffc53a317ab07b6416b014d10dabab9bc9002157a2362c75f","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"8914a68865af026c1f4fb1d5f02ba0053362ef34b813ad60cc4aa3a88aa4999e","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"} -\ No newline at end of file -+{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"e1c4b3839177aabdc73c017ee87ba3dcc8025b2730cb0a2c015473f9db99f3fa","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"94cbaad15021e287a1b9546a697b04c1e560f1204b52204ffaaea5975c5d03b9","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"0c5306ea9d12b5261380d733dc3f7624cf259c45638eac8d9222c7e32e134a65","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"e35db24ba69ee0262854916fa19a306bf6c40388f5593ab32d0907e24b5fc5c6","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"d0e8246063cae113806524a63a47c6c0628cc54a3ef03e938e89964f8b4f08b4","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ec229cc7af2511cb510c078e87e90ee2625090bfe94f40eb35f73d79143533aa","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"1e35b4773384ea143810cdce4b96f47108b37446430da30c96a0d1651656d73d","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8f9613e50c2771b33d7cf817a735d536b389ec57f861b9486d870373c768276e","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"228505fa48292e74b06acbed96196801595a4b822da2126a6d6c7fa773cff8bc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"69cc3638c6f7e2086ada7bacf5ea01ce1b7f5d045fd012c6f46b8635d30ce594","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"962741303dc24a5b9653f2e9b0b4ad9eb42fc54daa0a70ca70a7ce175e75094b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"c69c90606d4362f8de89b8816df0ded724ed64b53bf55d15681fde171b7bb361","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c72a08011c32f82919e930e0d89044d8feb65fd41bf80647436756c290344eb8","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f0db9914315d5a3d51bf5ec04a0ae6584f2e1688b9258ce132b617e67d9bd7a9","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"1ca6821fbb94476500d4352908e713b7c698cb7ff0a49997934126391657c573","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"758e222200a8cbb74b1eb01581da92fea895619da866bc383129d4b9a5366aef","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"c7ebabc4e1bdbbd97e5065faa3a57f41f473570920582d979f9e9d4f77448546","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"c3365480375bc258ffe267e7a299d7b3bb542a908bef8881f503ddc25ba8fc1f","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"aabf4582a7ddf17544ee4bfa6a954f0c6e2bd17e707b7ac5266d5697e0da762a","src/unix/mod.rs":"e13a3a67c25c28dffc53a317ab07b6416b014d10dabab9bc9002157a2362c75f","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"8914a68865af026c1f4fb1d5f02ba0053362ef34b813ad60cc4aa3a88aa4999e","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"} -diff --git a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -index 7ca870fd0..ba3075edd 100644 ---- a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -+++ b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -@@ -5,3 +5,20 @@ s_no_extra_traits! { - priv_: [f64; 4] - } - } -+ -+s! { -+ #[repr(align(8))] -+ pub struct clone_args { -+ pub flags: ::c_ulonglong, -+ pub pidfd: ::c_ulonglong, -+ pub child_tid: ::c_ulonglong, -+ pub parent_tid: ::c_ulonglong, -+ pub exit_signal: ::c_ulonglong, -+ pub stack: ::c_ulonglong, -+ pub stack_size: ::c_ulonglong, -+ pub tls: ::c_ulonglong, -+ pub set_tid: ::c_ulonglong, -+ pub set_tid_size: ::c_ulonglong, -+ pub cgroup: ::c_ulonglong, -+ } -+} -diff --git a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -index 2ed6a9156..ff520e0c6 100644 ---- a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -+++ b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -@@ -247,6 +247,20 @@ align_const! { - }; - } - -+pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; -+pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; -+pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; -+pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; -+pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; -+pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; -+pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; -+pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; -+pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; -+pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; -+pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; -+pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; -+pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; -+ - pub const SYS_io_setup: ::c_long = 0; - pub const SYS_io_destroy: ::c_long = 1; - pub const SYS_io_submit: ::c_long = 2; -@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; - pub const F_OFD_SETLK: ::c_int = 37; - pub const F_OFD_SETLKW: ::c_int = 38; - -+pub const MADV_SOFT_OFFLINE: ::c_int = 101; -+ - pub const EDEADLK: ::c_int = 35; - pub const EDEADLOCK: ::c_int = 35; - pub const ENAMETOOLONG: ::c_int = 36; -diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json -index 631af7226..824a6e056 100644 ---- a/vendor/libc/.cargo-checksum.json -+++ b/vendor/libc/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"04fa9ce26b0efcfe3dd51e3f1bbb81bb36f5d61982a11947283c7616d390549e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"cf7e0df0e655337d1c0852880817b6b514ef9599e2125232fc79cdf8eddd01ba","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"bb61eec399428faee753b3df509410c51ed2ac51406d40559fcec290bb50e293","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"e4f33050d52d3e5c932da8d10e1f377e1ff609fb178ea986bfc458d31e37dc19","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"23f189f188651762b38f40b4e9aba785625f6f9a52558a4a490510c3b1d08b53","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"57fee9dd251ac615ec7d32d293e0f0b6fa3bf28efbddd6d569765765aafb8b9b","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7df84dd6dee8b73fd4d72dd1638584d788e2a1a85f95746f7c5b330b8dc23655","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"236ef119410d566ef94064bf13d734635eaeecb3635a5d21e8e9f91e7e3152ac","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6a8eb9a1e35eec893de9c76a5be3ce29e4c3ca26db45fbcfa925bdd757f6352d","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a61d41f6fe01c06c6de5db2ed970522601eada133e6bac4ed2d1dfaceb576db2","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"fa260decf53280d4fdf714af60f42d4774f8d6f2da71b0a55a6c2a85e422eb57","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"079b11c99c6ca3cc5942c0e6d854541f8765c5058c2f024b84656697840e198b","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"41b9d0f405cd474385acce06df0649f4eeaab3fe8fb4655f97806fa40bdf84d8","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef4652dfb94e3c58aed5133ece982ad30569d46b6b1054552cd61905fa61690","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e2b46404e44f7d63c26af9dbd79b4e166ef7bced2bc9c6746a26ca86e508e0d4","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c91813ee5e1bc817996c46be86d1f46802e73df2952cab576ea015490929afc5","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"06abaca7fc85e805650ec807c4d06c888ff99e146e1ba2685f20840a86e35a2f","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"1d84f37fdfa4dfab1b758345af75e02485e2a18746830413c2afe5069a1e39ce","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"0514b337aaa6e62be9e01e00702ef996c60319b7050ece155530147c20de9995","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"7d8dfbd26ce958d9da17468b3c9d0b119ce7dbd59b3384551cd4423ce25db44a","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"3d03bd583aaf04f285f95ff8b53c9b5a891d3b64bfcda37a42648ec51c4c51e5","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"494e56628d4408bf66ad30ff71fbd21bc33d9037935c411dff7bf73dd3f1070b","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"1369fb55325914654ba3ad02410b75a40c8c0008feed9704c28520be1ee49641","src/unix/solarish/mod.rs":"52a31038984e68582347f4b28fd64c01e6308ff4293628818bb279605e7b28c6","src/unix/solarish/solaris.rs":"36abcfb46fab6e7151a0c1f555b419e1267b82893f6e84d5d260308ba8eeb0c5","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"} -\ No newline at end of file -+{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"04fa9ce26b0efcfe3dd51e3f1bbb81bb36f5d61982a11947283c7616d390549e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"cf7e0df0e655337d1c0852880817b6b514ef9599e2125232fc79cdf8eddd01ba","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"bb61eec399428faee753b3df509410c51ed2ac51406d40559fcec290bb50e293","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"e4f33050d52d3e5c932da8d10e1f377e1ff609fb178ea986bfc458d31e37dc19","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"23f189f188651762b38f40b4e9aba785625f6f9a52558a4a490510c3b1d08b53","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"57fee9dd251ac615ec7d32d293e0f0b6fa3bf28efbddd6d569765765aafb8b9b","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7df84dd6dee8b73fd4d72dd1638584d788e2a1a85f95746f7c5b330b8dc23655","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"236ef119410d566ef94064bf13d734635eaeecb3635a5d21e8e9f91e7e3152ac","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6a8eb9a1e35eec893de9c76a5be3ce29e4c3ca26db45fbcfa925bdd757f6352d","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a61d41f6fe01c06c6de5db2ed970522601eada133e6bac4ed2d1dfaceb576db2","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"fa260decf53280d4fdf714af60f42d4774f8d6f2da71b0a55a6c2a85e422eb57","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"079b11c99c6ca3cc5942c0e6d854541f8765c5058c2f024b84656697840e198b","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"41b9d0f405cd474385acce06df0649f4eeaab3fe8fb4655f97806fa40bdf84d8","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef4652dfb94e3c58aed5133ece982ad30569d46b6b1054552cd61905fa61690","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e2b46404e44f7d63c26af9dbd79b4e166ef7bced2bc9c6746a26ca86e508e0d4","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c91813ee5e1bc817996c46be86d1f46802e73df2952cab576ea015490929afc5","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"06abaca7fc85e805650ec807c4d06c888ff99e146e1ba2685f20840a86e35a2f","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"1d84f37fdfa4dfab1b758345af75e02485e2a18746830413c2afe5069a1e39ce","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"0514b337aaa6e62be9e01e00702ef996c60319b7050ece155530147c20de9995","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"7d8dfbd26ce958d9da17468b3c9d0b119ce7dbd59b3384551cd4423ce25db44a","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"3d03bd583aaf04f285f95ff8b53c9b5a891d3b64bfcda37a42648ec51c4c51e5","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"494e56628d4408bf66ad30ff71fbd21bc33d9037935c411dff7bf73dd3f1070b","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"1369fb55325914654ba3ad02410b75a40c8c0008feed9704c28520be1ee49641","src/unix/solarish/mod.rs":"52a31038984e68582347f4b28fd64c01e6308ff4293628818bb279605e7b28c6","src/unix/solarish/solaris.rs":"36abcfb46fab6e7151a0c1f555b419e1267b82893f6e84d5d260308ba8eeb0c5","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"} -diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -index 7ca870fd0..ba3075edd 100644 ---- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs -@@ -5,3 +5,20 @@ s_no_extra_traits! { - priv_: [f64; 4] - } - } -+ -+s! { -+ #[repr(align(8))] -+ pub struct clone_args { -+ pub flags: ::c_ulonglong, -+ pub pidfd: ::c_ulonglong, -+ pub child_tid: ::c_ulonglong, -+ pub parent_tid: ::c_ulonglong, -+ pub exit_signal: ::c_ulonglong, -+ pub stack: ::c_ulonglong, -+ pub stack_size: ::c_ulonglong, -+ pub tls: ::c_ulonglong, -+ pub set_tid: ::c_ulonglong, -+ pub set_tid_size: ::c_ulonglong, -+ pub cgroup: ::c_ulonglong, -+ } -+} -diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -index 2ed6a9156..ff520e0c6 100644 ---- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs -@@ -247,6 +247,20 @@ align_const! { - }; - } - -+pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; -+pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; -+pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; -+pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; -+pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; -+pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; -+pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; -+pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; -+pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; -+pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; -+pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; -+pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; -+pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; -+ - pub const SYS_io_setup: ::c_long = 0; - pub const SYS_io_destroy: ::c_long = 1; - pub const SYS_io_submit: ::c_long = 2; -@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; - pub const F_OFD_SETLK: ::c_int = 37; - pub const F_OFD_SETLKW: ::c_int = 38; - -+pub const MADV_SOFT_OFFLINE: ::c_int = 101; -+ - pub const EDEADLK: ::c_int = 35; - pub const EDEADLOCK: ::c_int = 35; - pub const ENAMETOOLONG: ::c_int = 36; --- -2.41.0 - diff --git a/0003-vendor-psm-add-loongarch64-support.patch b/0003-vendor-psm-add-loongarch64-support.patch deleted file mode 100644 index 461f59e..0000000 --- a/0003-vendor-psm-add-loongarch64-support.patch +++ /dev/null @@ -1,105 +0,0 @@ -From d4a6c0659f5008337b85451da2e2ea0a74110f99 Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Thu, 7 Jul 2022 11:53:09 +0800 -Subject: [PATCH 3/6] vendor: psm: add loongarch64 support - ---- - vendor/psm/.cargo-checksum.json | 2 +- - vendor/psm/build.rs | 1 + - vendor/psm/src/arch/loongarch64.s | 64 +++++++++++++++++++++++++++++++ - 3 files changed, 66 insertions(+), 1 deletion(-) - create mode 100644 vendor/psm/src/arch/loongarch64.s - -diff --git a/vendor/psm/.cargo-checksum.json b/vendor/psm/.cargo-checksum.json -index a69778b20..ea3c4f99a 100644 ---- a/vendor/psm/.cargo-checksum.json -+++ b/vendor/psm/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"Cargo.lock":"2928b712f89aee2b62581df1e552b7cb8288d999ba180291b4900b86a05c6d8d","Cargo.toml":"c2c5a0154a80cffc82349cd98f819ea1259c92f195c5878ceefb66e06b14d28c","LICENSE-APACHE":"965a63a81d9a2fbeb5f9096954dabb49690f9dffcdac9825f675b25c807252a2","LICENSE-MIT":"3e3714aa69bd874601741fd7d7ad5298740cece37778e279fc1ab4451c5a11af","README.mkd":"6385ecaced99b0a29a5b40166d34ef9312f322c1b8ad002bef3b08cd6c3e29b2","build.rs":"1d7872546e6924bbb2947edc055ddd01f48683cc80d9d75a846adb65540345f0","examples/info.rs":"8ffb89912304ecbf3d714dcc094f42e86fdd0738625b2e76be2e7d59ab0736cf","examples/on_stack_fibo.rs":"287f0a08b177a97366a5da39e24e33e1f4bbe30a1f2473956721c8a9d93926a4","examples/on_stack_fibo_alloc_each_frame.rs":"e084041bbb81d51b195a4db539a765409272916df29c83a62213a93de4b6fca3","examples/panics.rs":"6791fe0dda9456b3becf989cbc89bc45ae27302e633572a57bbf10a57b830076","examples/replace_stack_1.rs":"374a28881f5e5dbf9db9b9e34929fb7a7e6f3910d782a6718f53ac269807b990","examples/thread.rs":"3cf92882aff96151608584d63535701cc8e5ae953d7ecf706d77371180bff025","src/arch/aarch64_armasm.asm":"1c737338287f3de981fbae97f104ac5e49425ba7fbcb4f7d80120afae47a86d5","src/arch/aarch_aapcs64.s":"459b8cd5a96104893e8f849ac83369101d7204c933841672df162104bebd2375","src/arch/arm_aapcs.s":"4ada635e8528279bd0326654f5203b6bdc94dd68c94fdef5de551384ba1b1747","src/arch/arm_armasm.asm":"e3b514169f19368b0b49374412de38bd9f50576e7b93b64d685a0f84fa8f4c91","src/arch/mips64_eabi.s":"4e6f95f89ba72fc4dd1a9a547920764f66d98251d236941cee4d227010484520","src/arch/mips_eabi.s":"8b7927fd63660eb276e2951f28df6b11920f04be4dc17a16b66ad386da12c4c3","src/arch/powerpc32.s":"0b508a65dec7254ba2e0dc65a2c9e86c21069fe62f5d7c41f5190415a4885912","src/arch/powerpc64.s":"c1602d09d12ba1df48fc96af0f827f8679fc93cee728813527fb1b817a788911","src/arch/powerpc64_openpower.s":"421b11cc7381427d1e2acb4e681c9836ccfea0b79930492f0a99ec4d27495e58","src/arch/psm.h":"2cebda3740aa73b167b8ec18e3d2202ca46e400a081a46329b86051abd1a872a","src/arch/riscv.s":"a81d2af4bcc9c29db304730697e52a89a7376b51d2735185c67be8910d0cdf39","src/arch/riscv64.s":"a51da67ce569e2442ff487b062bb8fdfe7c769f3f05a88de480bd5ab214d9a4f","src/arch/sparc64.s":"6250acbd938aea2e440061663a79fbb2dac0592b3a193f027b6b910e2a8e3af1","src/arch/sparc_sysv.s":"c2da7576e1fbe2234cc8a5cf937f7676e125435295f8c32089bfa0b0f27fde5e","src/arch/wasm32.o":"d7279f419cb7e169cae2af2463507652e0393b801c2f4580244de70d3def58b6","src/arch/wasm32.s":"1ebdc90de48f13e6474ee17c406578fc090ff61e57c1f560ecf6e6b75c7ef10a","src/arch/x86.s":"1919a4af1474895f904ed4281a4a8fcdd0428dab257bff4ea262db83ed63b445","src/arch/x86_64.s":"c80f1a3e22db61fd62b5ef2e1b6663185403bdcbcfbfe7ff0f8e0831ff0cafcf","src/arch/x86_64_msvc.asm":"85683bc65a03371ea7d8d79dcbe487f690cc2460c359817fc63c30d575ad8957","src/arch/x86_64_windows_gnu.s":"44637034e094ec0ad76dbe1232e97271c8155eb93bcb1dd86fe825acd05978a0","src/arch/x86_msvc.asm":"1735d4b19f8e46d0699fc9538baa7ab0885d27531ef7d9960e2027ad8137769b","src/arch/x86_windows_gnu.s":"b94d907a86f230c5c8ca1c708ede173f73c5269496f3959e08e4a92155e160d7","src/arch/zseries_linux.s":"5c3379a76e31bf13abf240efda12596fabce108cf63f60f9d0495e82ab8f1717","src/lib.rs":"18774ee37630bc6c7a36273014f80f6afa3f73bf34f4c49f5795d2eb5df1c195","tests/stack_direction.rs":"77d8f9dee196e99e70d569f59fef82bc2f88a8ec17bfe07ebe2f005fcb815c8b","tests/stack_direction_2.rs":"f9191394de5b6381af6ba8223e7717230059dc335f639238c0ddbc7eb87bfc0e"},"package":"cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"} -\ No newline at end of file -+{"files":{"Cargo.lock":"2928b712f89aee2b62581df1e552b7cb8288d999ba180291b4900b86a05c6d8d","Cargo.toml":"c2c5a0154a80cffc82349cd98f819ea1259c92f195c5878ceefb66e06b14d28c","LICENSE-APACHE":"965a63a81d9a2fbeb5f9096954dabb49690f9dffcdac9825f675b25c807252a2","LICENSE-MIT":"3e3714aa69bd874601741fd7d7ad5298740cece37778e279fc1ab4451c5a11af","README.mkd":"6385ecaced99b0a29a5b40166d34ef9312f322c1b8ad002bef3b08cd6c3e29b2","build.rs":"f742cdd0ea2c92b5f43008488b6dc3c89424f83ca9ef25ca89ab3894d6707764","examples/info.rs":"8ffb89912304ecbf3d714dcc094f42e86fdd0738625b2e76be2e7d59ab0736cf","examples/on_stack_fibo.rs":"287f0a08b177a97366a5da39e24e33e1f4bbe30a1f2473956721c8a9d93926a4","examples/on_stack_fibo_alloc_each_frame.rs":"e084041bbb81d51b195a4db539a765409272916df29c83a62213a93de4b6fca3","examples/panics.rs":"6791fe0dda9456b3becf989cbc89bc45ae27302e633572a57bbf10a57b830076","examples/replace_stack_1.rs":"374a28881f5e5dbf9db9b9e34929fb7a7e6f3910d782a6718f53ac269807b990","examples/thread.rs":"3cf92882aff96151608584d63535701cc8e5ae953d7ecf706d77371180bff025","src/arch/aarch64_armasm.asm":"1c737338287f3de981fbae97f104ac5e49425ba7fbcb4f7d80120afae47a86d5","src/arch/aarch_aapcs64.s":"459b8cd5a96104893e8f849ac83369101d7204c933841672df162104bebd2375","src/arch/arm_aapcs.s":"4ada635e8528279bd0326654f5203b6bdc94dd68c94fdef5de551384ba1b1747","src/arch/arm_armasm.asm":"e3b514169f19368b0b49374412de38bd9f50576e7b93b64d685a0f84fa8f4c91","src/arch/loongarch64.s":"47836a2b0a19d8b7a63fd21674509224ec8059eee1251205ad88c8e0ec7469a3","src/arch/mips64_eabi.s":"4e6f95f89ba72fc4dd1a9a547920764f66d98251d236941cee4d227010484520","src/arch/mips_eabi.s":"8b7927fd63660eb276e2951f28df6b11920f04be4dc17a16b66ad386da12c4c3","src/arch/powerpc32.s":"0b508a65dec7254ba2e0dc65a2c9e86c21069fe62f5d7c41f5190415a4885912","src/arch/powerpc64.s":"c1602d09d12ba1df48fc96af0f827f8679fc93cee728813527fb1b817a788911","src/arch/powerpc64_openpower.s":"421b11cc7381427d1e2acb4e681c9836ccfea0b79930492f0a99ec4d27495e58","src/arch/psm.h":"2cebda3740aa73b167b8ec18e3d2202ca46e400a081a46329b86051abd1a872a","src/arch/riscv.s":"a81d2af4bcc9c29db304730697e52a89a7376b51d2735185c67be8910d0cdf39","src/arch/riscv64.s":"a51da67ce569e2442ff487b062bb8fdfe7c769f3f05a88de480bd5ab214d9a4f","src/arch/sparc64.s":"6250acbd938aea2e440061663a79fbb2dac0592b3a193f027b6b910e2a8e3af1","src/arch/sparc_sysv.s":"c2da7576e1fbe2234cc8a5cf937f7676e125435295f8c32089bfa0b0f27fde5e","src/arch/wasm32.o":"d7279f419cb7e169cae2af2463507652e0393b801c2f4580244de70d3def58b6","src/arch/wasm32.s":"1ebdc90de48f13e6474ee17c406578fc090ff61e57c1f560ecf6e6b75c7ef10a","src/arch/x86.s":"1919a4af1474895f904ed4281a4a8fcdd0428dab257bff4ea262db83ed63b445","src/arch/x86_64.s":"c80f1a3e22db61fd62b5ef2e1b6663185403bdcbcfbfe7ff0f8e0831ff0cafcf","src/arch/x86_64_msvc.asm":"85683bc65a03371ea7d8d79dcbe487f690cc2460c359817fc63c30d575ad8957","src/arch/x86_64_windows_gnu.s":"44637034e094ec0ad76dbe1232e97271c8155eb93bcb1dd86fe825acd05978a0","src/arch/x86_msvc.asm":"1735d4b19f8e46d0699fc9538baa7ab0885d27531ef7d9960e2027ad8137769b","src/arch/x86_windows_gnu.s":"b94d907a86f230c5c8ca1c708ede173f73c5269496f3959e08e4a92155e160d7","src/arch/zseries_linux.s":"5c3379a76e31bf13abf240efda12596fabce108cf63f60f9d0495e82ab8f1717","src/lib.rs":"18774ee37630bc6c7a36273014f80f6afa3f73bf34f4c49f5795d2eb5df1c195","tests/stack_direction.rs":"77d8f9dee196e99e70d569f59fef82bc2f88a8ec17bfe07ebe2f005fcb815c8b","tests/stack_direction_2.rs":"f9191394de5b6381af6ba8223e7717230059dc335f639238c0ddbc7eb87bfc0e"},"package":"cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"} -diff --git a/vendor/psm/build.rs b/vendor/psm/build.rs -index 01a13bf71..9fab27a83 100644 ---- a/vendor/psm/build.rs -+++ b/vendor/psm/build.rs -@@ -51,6 +51,7 @@ fn find_assembly( - ("riscv32", _, _, _) => Some(("src/arch/riscv.s", true)), - ("riscv64", _, _, _) => Some(("src/arch/riscv64.s", true)), - ("wasm32", _, _, _) => Some(("src/arch/wasm32.o", true)), -+ ("loongarch64", _, _, _) => Some(("src/arch/loongarch64.s", true)), - _ => None, - } - } -diff --git a/vendor/psm/src/arch/loongarch64.s b/vendor/psm/src/arch/loongarch64.s -new file mode 100644 -index 000000000..04bcee3a0 ---- /dev/null -+++ b/vendor/psm/src/arch/loongarch64.s -@@ -0,0 +1,64 @@ -+#include "psm.h" -+ -+.text -+.globl rust_psm_stack_direction -+.p2align 2 -+.type rust_psm_stack_direction,@function -+/* extern "C" fn() -> u8 */ -+rust_psm_stack_direction: -+.cfi_startproc -+ addi.w $r4, $r0, STACK_DIRECTION_DESCENDING -+ jr $r1 -+.rust_psm_stack_direction_end: -+.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction -+.cfi_endproc -+ -+ -+.globl rust_psm_stack_pointer -+.p2align 2 -+.type rust_psm_stack_pointer,@function -+/* extern "C" fn() -> *mut u8 */ -+rust_psm_stack_pointer: -+.cfi_startproc -+ move $r4, $r3 -+ jr $r1 -+.rust_psm_stack_pointer_end: -+.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer -+.cfi_endproc -+ -+ -+.globl rust_psm_replace_stack -+.p2align 2 -+.type rust_psm_replace_stack,@function -+/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */ -+rust_psm_replace_stack: -+.cfi_startproc -+ move $r3, $r6 -+ jr $r5 -+.rust_psm_replace_stack_end: -+.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack -+.cfi_endproc -+ -+ -+.globl rust_psm_on_stack -+.p2align 2 -+.type rust_psm_on_stack,@function -+/* extern "C" fn(r4: iusize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */ -+rust_psm_on_stack: -+.cfi_startproc -+ st.d $r3, $r7, -8 -+ st.d $r1, $r7, -16 -+ .cfi_def_cfa 7, 0 -+ .cfi_offset 3, -8 -+ .cfi_offset 1, -16 -+ addi.d $r3, $r7, -16 -+ .cfi_def_cfa 3, -16 -+ jirl $r1, $r6, 0 -+ ld.d $r1, $r3, 0 -+ .cfi_restore 12 -+ ld.d $r3, $r3, 8 -+ .cfi_restore 3 -+ jr $r1 -+.rust_psm_on_stack_end: -+.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack -+.cfi_endproc --- -2.41.0 - diff --git a/0004-vendor-object-add-loongarch64-support.patch b/0004-vendor-object-add-loongarch64-support.patch deleted file mode 100644 index 620cb66..0000000 --- a/0004-vendor-object-add-loongarch64-support.patch +++ /dev/null @@ -1,623 +0,0 @@ -From 5258a72e586e973867e392178f0e3dfd19610d23 Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Sun, 25 Jun 2023 16:22:39 +0800 -Subject: [PATCH 4/6] vendor: object: add loongarch64 support - ---- - vendor/object-0.26.2/.cargo-checksum.json | 2 +- - vendor/object-0.26.2/src/common.rs | 2 + - vendor/object-0.26.2/src/elf.rs | 119 +++++++++ - vendor/object-0.26.2/src/read/elf/file.rs | 1 + - .../object-0.26.2/src/read/elf/relocation.rs | 5 + - vendor/object-0.26.2/src/write/elf.rs | 10 + - vendor/object-0.26.2/tests/round_trip/mod.rs | 1 + - vendor/object/.cargo-checksum.json | 2 +- - vendor/object/src/common.rs | 4 +- - vendor/object/src/elf.rs | 244 +++++++++--------- - vendor/object/src/write/elf/object.rs | 7 +- - 11 files changed, 264 insertions(+), 133 deletions(-) - -diff --git a/vendor/object-0.26.2/.cargo-checksum.json b/vendor/object-0.26.2/.cargo-checksum.json -index 1f76cb1fc..32e0621c8 100644 ---- a/vendor/object-0.26.2/.cargo-checksum.json -+++ b/vendor/object-0.26.2/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"CHANGELOG.md":"52a47c66164f368e5a167f1732525583ec574cd7de8be91fac29d52997b1c632","Cargo.lock":"a1190887088da0ebf768d172d97a9c21519fe4adb72860e4c9d3826307a57ce6","Cargo.toml":"2481b73a96029b6409d582b026d901d04f5ef12c12ccb27f3c997fa567ce18a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"283c8881f81e647191130eea41b94fe877214e492fd35dd02a10c0698aaedcdf","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"49feba2fd34a6fb76e18763348e6ccf5a0c4ccf3779e5bc622df4d8ed14e82bf","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"9a16e67c321a6b35d35ce9d0611281f8f30b2c475cde68479d6a0fdd2b997a5e","src/elf.rs":"78df96810cb379e1dd8b4872ab90d2337855fa4d4d98fb09697d0750154dc40b","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"fccca74e1e79d5d4dbb090a0103d91b5a0b4f71983d5e3ee3b139b13a9c7990d","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"7a1b57131f43ed01472f4924f37657896880b82b127a153795388eb4577a640a","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"696a956935e7f1babb621ff71dec23154ca4bf906a8adfa5c02aac7a50117c69","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"3b15e43d5db9e3af025cda166dd731a5a10293c8d6a6a6f82e7ff4541a4b04a8","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"721e4f96c2de16f85192db0ad53ee34745bcbe8d551ad297d4f44ab13205ec06","src/read/coff/symbol.rs":"01a11c8f77c1b80d354d9437439cf4685b99bf254cc9eeadd19da2a394fc3c57","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"9d5958552ac3f590249c45795d40d8ffce0d41a6e4d9ae2f38f356ad4e46c05e","src/read/elf/hash.rs":"3a08046c78a6fd79bccfd1a0d4cc113da8d0664164576f290885b51d8110acca","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"62b27c79964f7b037f4fb0b952afacd14790751828e82b67ed5890f143e2b2dc","src/read/elf/section.rs":"d692093ad195ccd0e4857c2f9c638543aa38a8179180e68d27a1f0784aa5e09a","src/read/elf/segment.rs":"d3cbb86cc9ca6eca93f9c17f36823dae0bd72ab2761f2b784dadd8f5b5c9dd9f","src/read/elf/symbol.rs":"9582039f44e82a3bbf225db12ddab9a3b3d5f4b0536d4125c18bb693da3c6db7","src/read/elf/version.rs":"c665034c90cb17e7bd1a6ba836966534fb2527698979908a704cf3b716c0dbdc","src/read/macho/dyld_cache.rs":"37330ba249226231b2e6ae7de80d60845c2eb7db854fd588c52fc706e13e49b8","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c524be5be3447afb5aa9c68673f495de05e652687790397f6bf5617b9beea21a","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"c0a615079779bf83bc3a6ae6d816f8d853099591f0b72e8646a624955bc5069e","src/read/mod.rs":"18ccc63d7acfc1af561d413738cafb1882368179257d36d2dc2496e21095bf7c","src/read/pe/file.rs":"f17836ac757dfd198323a2df1289b02dbb3ba85f2ceff0fdb7e565d30d555da3","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"befd3c82fe6d9186b5802945853da9653649779989fd36cd2a835e3264156281","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"16f52497fd18ec893c8f72903e9ea0bde6901e75acdfbc8be6a7305e13bccb8c","src/write/elf.rs":"2d6d3c4b014e9df7dd09e3ecf926a7d8fbac6e3cf3ab768e672b7c8ac1d38485","src/write/macho.rs":"fa058f9e7aa1e9895a3c4575fa527c3d5dbac186d994c9ba48801348a8428f35","src/write/mod.rs":"970620fba6e7b851981cda09929d93667a51d0c0be2c1491fdd8002d530515df","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"3bf18004fd5cd25229e480856f36b3410f23b12c096de4c52ab13e11da75b2e3","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b741ba432fdee2156699743962c64aaf2d1e9629c432e40953ac4d410688ea5a","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"} -\ No newline at end of file -+{"files":{"CHANGELOG.md":"52a47c66164f368e5a167f1732525583ec574cd7de8be91fac29d52997b1c632","Cargo.lock":"a1190887088da0ebf768d172d97a9c21519fe4adb72860e4c9d3826307a57ce6","Cargo.toml":"2481b73a96029b6409d582b026d901d04f5ef12c12ccb27f3c997fa567ce18a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"283c8881f81e647191130eea41b94fe877214e492fd35dd02a10c0698aaedcdf","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"49feba2fd34a6fb76e18763348e6ccf5a0c4ccf3779e5bc622df4d8ed14e82bf","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"fefada6d122499cfbdb3c2d6deb3727f0c516b771a9393f716310564c4139da3","src/elf.rs":"47244eee991c738a1e72777e835c196ce2fbd10d5e20a741271356c402d41540","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"fccca74e1e79d5d4dbb090a0103d91b5a0b4f71983d5e3ee3b139b13a9c7990d","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"7a1b57131f43ed01472f4924f37657896880b82b127a153795388eb4577a640a","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"696a956935e7f1babb621ff71dec23154ca4bf906a8adfa5c02aac7a50117c69","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"3b15e43d5db9e3af025cda166dd731a5a10293c8d6a6a6f82e7ff4541a4b04a8","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"721e4f96c2de16f85192db0ad53ee34745bcbe8d551ad297d4f44ab13205ec06","src/read/coff/symbol.rs":"01a11c8f77c1b80d354d9437439cf4685b99bf254cc9eeadd19da2a394fc3c57","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"46e1aa01bed485c53288df14cc1688fe5e4ed81f259a30f54acbb3498042db72","src/read/elf/hash.rs":"3a08046c78a6fd79bccfd1a0d4cc113da8d0664164576f290885b51d8110acca","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"68c85f2ab03ea14feccdffbb383c6c44a55281b7ca17aa82a487ea8ccc710b70","src/read/elf/section.rs":"d692093ad195ccd0e4857c2f9c638543aa38a8179180e68d27a1f0784aa5e09a","src/read/elf/segment.rs":"d3cbb86cc9ca6eca93f9c17f36823dae0bd72ab2761f2b784dadd8f5b5c9dd9f","src/read/elf/symbol.rs":"9582039f44e82a3bbf225db12ddab9a3b3d5f4b0536d4125c18bb693da3c6db7","src/read/elf/version.rs":"c665034c90cb17e7bd1a6ba836966534fb2527698979908a704cf3b716c0dbdc","src/read/macho/dyld_cache.rs":"37330ba249226231b2e6ae7de80d60845c2eb7db854fd588c52fc706e13e49b8","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c524be5be3447afb5aa9c68673f495de05e652687790397f6bf5617b9beea21a","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"c0a615079779bf83bc3a6ae6d816f8d853099591f0b72e8646a624955bc5069e","src/read/mod.rs":"18ccc63d7acfc1af561d413738cafb1882368179257d36d2dc2496e21095bf7c","src/read/pe/file.rs":"f17836ac757dfd198323a2df1289b02dbb3ba85f2ceff0fdb7e565d30d555da3","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"befd3c82fe6d9186b5802945853da9653649779989fd36cd2a835e3264156281","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"16f52497fd18ec893c8f72903e9ea0bde6901e75acdfbc8be6a7305e13bccb8c","src/write/elf.rs":"34cbd7f14853309f94ac29d3371fac25165dbd72b0d84b6c6cd2cae6eb3fd2c7","src/write/macho.rs":"fa058f9e7aa1e9895a3c4575fa527c3d5dbac186d994c9ba48801348a8428f35","src/write/mod.rs":"970620fba6e7b851981cda09929d93667a51d0c0be2c1491fdd8002d530515df","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"3bf18004fd5cd25229e480856f36b3410f23b12c096de4c52ab13e11da75b2e3","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"8086e07fb15c3306944606b3cdd26cd0db42d1606885fc43dada4aa6e456aa2c","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"} -diff --git a/vendor/object-0.26.2/src/common.rs b/vendor/object-0.26.2/src/common.rs -index c86665c21..0759a9d4e 100644 ---- a/vendor/object-0.26.2/src/common.rs -+++ b/vendor/object-0.26.2/src/common.rs -@@ -23,6 +23,7 @@ pub enum Architecture { - S390x, - Sparc64, - Wasm32, -+ LoongArch64, - } - - impl Architecture { -@@ -50,6 +51,7 @@ impl Architecture { - Architecture::S390x => Some(AddressSize::U64), - Architecture::Sparc64 => Some(AddressSize::U64), - Architecture::Wasm32 => Some(AddressSize::U32), -+ Architecture::LoongArch64 => Some(AddressSize::U64), - } - } - } -diff --git a/vendor/object-0.26.2/src/elf.rs b/vendor/object-0.26.2/src/elf.rs -index 28ac16bbe..5591834f1 100644 ---- a/vendor/object-0.26.2/src/elf.rs -+++ b/vendor/object-0.26.2/src/elf.rs -@@ -564,6 +564,8 @@ pub const EM_BPF: u16 = 247; - pub const EM_CSKY: u16 = 252; - /// Digital Alpha - pub const EM_ALPHA: u16 = 0x9026; -+/// LOONGARCH -+pub const EM_LOONGARCH: u16 = 258; - - // Values for `FileHeader*::e_version` and `Ident::version`. - /// Invalid ELF version. -@@ -6081,6 +6083,123 @@ pub const R_RISCV_SET32: u32 = 56; - #[allow(missing_docs)] - pub const R_RISCV_32_PCREL: u32 = 57; - -+//LOONGARCH values `FileHeader*::e_flags`. -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI: u32 = 0x0003; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LP64: u32 = 0x0003; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LPX32: u32 = 0x0002; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LP32: u32 = 0x0001; -+ -+// LOONGARCH values `Rel*::r_type`. -+/* Loongarch specific dynamic relocations. */ -+#[allow(missing_docs)] -+pub const R_LARCH_NONE: u32 = 0; -+#[allow(missing_docs)] -+pub const R_LARCH_32: u32 = 1; -+#[allow(missing_docs)] -+pub const R_LARCH_64: u32 = 2; -+#[allow(missing_docs)] -+pub const R_LARCH_RELATIVE: u32 = 3; -+#[allow(missing_docs)] -+pub const R_LARCH_COPY: u32 = 4; -+#[allow(missing_docs)] -+pub const R_LARCH_JUMP_SLOT: u32 = 5; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPMOD32: u32 = 6; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPMOD64: u32 = 7; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPREL32: u32 = 8; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPREL64: u32 = 9; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_TPREL32: u32 = 10; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_TPREL64: u32 = 11; -+#[allow(missing_docs)] -+pub const R_LARCH_IRELATIVE: u32 = 12; -+#[allow(missing_docs)] -+pub const R_LARCH_MARK_LA: u32 = 20; -+#[allow(missing_docs)] -+pub const R_LARCH_MARK_PCREL: u32 = 21; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_ASSERT: u32 = 30; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_NOT: u32 = 31; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SUB: u32 = 32; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SL: u32 = 33; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SR: u32 = 34; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_ADD: u32 = 35; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_AND: u32 = 36; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_IF_ELSE: u32 = 37; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_U: u32 = 46; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD8: u32 = 47; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD16: u32 = 48; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD24: u32 = 49; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD32: u32 = 50; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD64: u32 = 51; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB8: u32 = 52; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB16: u32 = 53; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB24: u32 = 54; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB32: u32 = 55; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB64: u32 = 56; -+#[allow(missing_docs)] -+pub const R_LARCH_GNU_VTINHERIT: u32 = 57; -+#[allow(missing_docs)] -+pub const R_LARCH_GNU_VTENTRY: u32 = 58; -+ - // BPF values `Rel*::r_type`. - /// No reloc - pub const R_BPF_NONE: u32 = 0; -diff --git a/vendor/object-0.26.2/src/read/elf/file.rs b/vendor/object-0.26.2/src/read/elf/file.rs -index 91273ca41..00262dafc 100644 ---- a/vendor/object-0.26.2/src/read/elf/file.rs -+++ b/vendor/object-0.26.2/src/read/elf/file.rs -@@ -161,6 +161,7 @@ where - (elf::EM_X86_64, false) => Architecture::X86_64_X32, - (elf::EM_X86_64, true) => Architecture::X86_64, - (elf::EM_HEXAGON, _) => Architecture::Hexagon, -+ (elf::EM_LOONGARCH, true) => Architecture::LoongArch64, - (elf::EM_MIPS, false) => Architecture::Mips, - (elf::EM_MIPS, true) => Architecture::Mips64, - (elf::EM_MSP430, _) => Architecture::Msp430, -diff --git a/vendor/object-0.26.2/src/read/elf/relocation.rs b/vendor/object-0.26.2/src/read/elf/relocation.rs -index d3e24b2e8..790cebc91 100644 ---- a/vendor/object-0.26.2/src/read/elf/relocation.rs -+++ b/vendor/object-0.26.2/src/read/elf/relocation.rs -@@ -301,6 +301,11 @@ fn parse_relocation( - elf::R_HEX_32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, -+ elf::EM_LOONGARCH => match reloc.r_type(endian, false) { -+ elf::R_LARCH_32 => (RelocationKind::Absolute, 32), -+ elf::R_LARCH_64 => (RelocationKind::Absolute, 64), -+ r_type => (RelocationKind::Elf(r_type), 0), -+ }, - elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) { - elf::R_MIPS_16 => (RelocationKind::Absolute, 16), - elf::R_MIPS_32 => (RelocationKind::Absolute, 32), -diff --git a/vendor/object-0.26.2/src/write/elf.rs b/vendor/object-0.26.2/src/write/elf.rs -index 34e0abc85..c90146edb 100644 ---- a/vendor/object-0.26.2/src/write/elf.rs -+++ b/vendor/object-0.26.2/src/write/elf.rs -@@ -88,6 +88,7 @@ impl Object { - Architecture::Riscv32 => true, - Architecture::S390x => true, - Architecture::Sparc64 => true, -+ Architecture::LoongArch64 => true, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", -@@ -371,6 +372,7 @@ impl Object { - Architecture::Riscv64 => elf::EM_RISCV, - Architecture::S390x => elf::EM_S390, - Architecture::Sparc64 => elf::EM_SPARCV9, -+ Architecture::LoongArch64 => elf::EM_LOONGARCH, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", -@@ -682,6 +684,14 @@ impl Object { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, -+ Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) { -+ (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, -+ (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, -+ (RelocationKind::Elf(x), _, _) => x, -+ _ => { -+ return Err(Error(format!("unimplemented relocation {:?}", reloc))); -+ } -+ }, - Architecture::Mips | Architecture::Mips64 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16, -diff --git a/vendor/object-0.26.2/tests/round_trip/mod.rs b/vendor/object-0.26.2/tests/round_trip/mod.rs -index 37050689f..5d97f7ab9 100644 ---- a/vendor/object-0.26.2/tests/round_trip/mod.rs -+++ b/vendor/object-0.26.2/tests/round_trip/mod.rs -@@ -236,6 +236,7 @@ fn elf_any() { - (Architecture::X86_64, Endianness::Little), - (Architecture::X86_64_X32, Endianness::Little), - (Architecture::Hexagon, Endianness::Little), -+ (Architecture::LoongArch64, Endianness::Little), - (Architecture::Mips, Endianness::Little), - (Architecture::Mips64, Endianness::Little), - (Architecture::Msp430, Endianness::Little), -diff --git a/vendor/object/.cargo-checksum.json b/vendor/object/.cargo-checksum.json -index e4a57348b..a85fa9ebb 100644 ---- a/vendor/object/.cargo-checksum.json -+++ b/vendor/object/.cargo-checksum.json -@@ -1 +1 @@ --{"files":{"CHANGELOG.md":"78aa23a55bd06448276854e3c19f984ff45098071dda36b27a0fb2e236630348","Cargo.toml":"4cdcbff917685fee9e3b4212583c2f1ea7a278b6fdb402ff18e314d57095a8b6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"3c5f153cecb269a4dbd5f0907951b1fe40e53054a9625bb75604e3b142ed45e3","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"ec5c87c07743202d1faabcaac7e4f65d7d1186ad47d503c7b9cd30ecce39383e","src/elf.rs":"018c6da138e3ff7f7d78c9346ffab37773e23fb6224ac8c7627defc802cbaacb","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"22f3f5a5834821d144daf3b1993da1a2072ee57692321366da9c281de6d0a0fe","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"f14fe040751bdde66d8a39b53d145817ac131722c6d790f853bbcd764b1466b8","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"3c525fbe89144caf72ae0d55f5625b3be8476dcfa8a9203425f68fb087631c12","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"a2b0e3131c17e3b14def694342b119a215b017ac81c8538097bebe0ea3a6ecdd","src/read/elf/comdat.rs":"9c31a274e7b43bc27f9b82a67207b94eef2d07ef107c8e2ef7a1535fe7329f55","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"192adf7e082e9a702233f5012981b422408e55f0d8460cf39f8faa8fda0d6a5e","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"4ce50bfeaa6ae69c36458139a7699eac6542f448c786b5a102efd187b0fd5ddb","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"f0534940d8697d7bb66bc784dee0a3e2e173c2ff5266d03d7ad92b0b3efa15e1","src/read/elf/symbol.rs":"6d7361ed09d3829f6fed87f26d10746b4b8b1862579f94445683651f047b8b43","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"ee5e429abdaf6de167de2247679e13ce37724a6a0c50b8842302eb98d583bb71","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"e8c308113c48439a00777404fca21d9115203c1135e65b8703d533af761658a2","src/read/pe/data_directory.rs":"9c20dec2b52b26d0a80d2cdf9565c5298ea90e5b5b1001808abf56cdb25a7f8b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"59d2b02d1c1cbac649796b245f4e8c85fdfedf5ca0feab4524cc2004aae82927","src/read/pe/import.rs":"ad1a094a3608be6c17dcc7d8c9eae99f2628055f0550818657cb0b185b4fb35e","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"71f9b8c0aaf0c54a7ee3bd0a2135f72d48da8bda2b4e3550c17aa4cc22e0ac5f","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/write/coff.rs":"43413acdb221a985b7d4c4c326ee4a48c09bc3d7dc99162a16724b99c8abf3c9","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"6101aef4e2c65f0e41fa63c04f229950b173525110b86165aede792159004ec2","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"392e3a81ebb1694cd9e66eeb98f046731348030b0c1f45e4a22df52aad928b94","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"ed1bef4d599ba31ca7083f53cf8605a91e1dd0a3e755df9271d1417649230452","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"} -\ No newline at end of file -+{"files":{"CHANGELOG.md":"78aa23a55bd06448276854e3c19f984ff45098071dda36b27a0fb2e236630348","Cargo.toml":"4cdcbff917685fee9e3b4212583c2f1ea7a278b6fdb402ff18e314d57095a8b6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"3c5f153cecb269a4dbd5f0907951b1fe40e53054a9625bb75604e3b142ed45e3","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"85dfbce1d99eb21feff95062ef39c9082ae4f277cb7f5d8703cc024c9e7060f5","src/elf.rs":"2b81f91e92b13e32e246d357ac6168b0e3d355f82bd8b6d0becaa8b3f97dfd37","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"22f3f5a5834821d144daf3b1993da1a2072ee57692321366da9c281de6d0a0fe","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"f14fe040751bdde66d8a39b53d145817ac131722c6d790f853bbcd764b1466b8","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"3c525fbe89144caf72ae0d55f5625b3be8476dcfa8a9203425f68fb087631c12","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"a2b0e3131c17e3b14def694342b119a215b017ac81c8538097bebe0ea3a6ecdd","src/read/elf/comdat.rs":"9c31a274e7b43bc27f9b82a67207b94eef2d07ef107c8e2ef7a1535fe7329f55","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"192adf7e082e9a702233f5012981b422408e55f0d8460cf39f8faa8fda0d6a5e","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"4ce50bfeaa6ae69c36458139a7699eac6542f448c786b5a102efd187b0fd5ddb","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"f0534940d8697d7bb66bc784dee0a3e2e173c2ff5266d03d7ad92b0b3efa15e1","src/read/elf/symbol.rs":"6d7361ed09d3829f6fed87f26d10746b4b8b1862579f94445683651f047b8b43","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"ee5e429abdaf6de167de2247679e13ce37724a6a0c50b8842302eb98d583bb71","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"e8c308113c48439a00777404fca21d9115203c1135e65b8703d533af761658a2","src/read/pe/data_directory.rs":"9c20dec2b52b26d0a80d2cdf9565c5298ea90e5b5b1001808abf56cdb25a7f8b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"59d2b02d1c1cbac649796b245f4e8c85fdfedf5ca0feab4524cc2004aae82927","src/read/pe/import.rs":"ad1a094a3608be6c17dcc7d8c9eae99f2628055f0550818657cb0b185b4fb35e","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"71f9b8c0aaf0c54a7ee3bd0a2135f72d48da8bda2b4e3550c17aa4cc22e0ac5f","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/write/coff.rs":"43413acdb221a985b7d4c4c326ee4a48c09bc3d7dc99162a16724b99c8abf3c9","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"93f003cdbd2fa87a049b3bcc3840c18cef69f97ac92d29dd157513d05f1fefd8","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"392e3a81ebb1694cd9e66eeb98f046731348030b0c1f45e4a22df52aad928b94","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"ed1bef4d599ba31ca7083f53cf8605a91e1dd0a3e755df9271d1417649230452","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"} -diff --git a/vendor/object/src/common.rs b/vendor/object/src/common.rs -index 20dde991a..39a3fa6fe 100644 ---- a/vendor/object/src/common.rs -+++ b/vendor/object/src/common.rs -@@ -13,7 +13,6 @@ pub enum Architecture { - #[allow(non_camel_case_types)] - X86_64_X32, - Hexagon, -- LoongArch64, - Mips, - Mips64, - Msp430, -@@ -24,6 +23,7 @@ pub enum Architecture { - S390x, - Sparc64, - Wasm32, -+ LoongArch64, - } - - impl Architecture { -@@ -41,7 +41,6 @@ impl Architecture { - Architecture::X86_64 => Some(AddressSize::U64), - Architecture::X86_64_X32 => Some(AddressSize::U32), - Architecture::Hexagon => Some(AddressSize::U32), -- Architecture::LoongArch64 => Some(AddressSize::U64), - Architecture::Mips => Some(AddressSize::U32), - Architecture::Mips64 => Some(AddressSize::U64), - Architecture::Msp430 => Some(AddressSize::U16), -@@ -52,6 +51,7 @@ impl Architecture { - Architecture::S390x => Some(AddressSize::U64), - Architecture::Sparc64 => Some(AddressSize::U64), - Architecture::Wasm32 => Some(AddressSize::U32), -+ Architecture::LoongArch64 => Some(AddressSize::U64), - } - } - } -diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs -index 9f6577269..9c0b91621 100644 ---- a/vendor/object/src/elf.rs -+++ b/vendor/object/src/elf.rs -@@ -574,10 +574,10 @@ pub const EM_RISCV: u16 = 243; - pub const EM_BPF: u16 = 247; - /// C-SKY - pub const EM_CSKY: u16 = 252; --/// Loongson LoongArch --pub const EM_LOONGARCH: u16 = 258; - /// Digital Alpha - pub const EM_ALPHA: u16 = 0x9026; -+/// LOONGARCH -+pub const EM_LOONGARCH: u16 = 258; - - // Values for `FileHeader*::e_version` and `Ident::version`. - /// Invalid ELF version. -@@ -6114,6 +6114,123 @@ pub const R_RISCV_SET32: u32 = 56; - #[allow(missing_docs)] - pub const R_RISCV_32_PCREL: u32 = 57; - -+//LOONGARCH values `FileHeader*::e_flags`. -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI: u32 = 0x0003; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LP64: u32 = 0x0003; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LPX32: u32 = 0x0002; -+#[allow(missing_docs)] -+pub const EF_LARCH_ABI_LP32: u32 = 0x0001; -+ -+// LOONGARCH values `Rel*::r_type`. -+/* Loongarch specific dynamic relocations. */ -+#[allow(missing_docs)] -+pub const R_LARCH_NONE: u32 = 0; -+#[allow(missing_docs)] -+pub const R_LARCH_32: u32 = 1; -+#[allow(missing_docs)] -+pub const R_LARCH_64: u32 = 2; -+#[allow(missing_docs)] -+pub const R_LARCH_RELATIVE: u32 = 3; -+#[allow(missing_docs)] -+pub const R_LARCH_COPY: u32 = 4; -+#[allow(missing_docs)] -+pub const R_LARCH_JUMP_SLOT: u32 = 5; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPMOD32: u32 = 6; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPMOD64: u32 = 7; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPREL32: u32 = 8; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_DTPREL64: u32 = 9; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_TPREL32: u32 = 10; -+#[allow(missing_docs)] -+pub const R_LARCH_TLS_TPREL64: u32 = 11; -+#[allow(missing_docs)] -+pub const R_LARCH_IRELATIVE: u32 = 12; -+#[allow(missing_docs)] -+pub const R_LARCH_MARK_LA: u32 = 20; -+#[allow(missing_docs)] -+pub const R_LARCH_MARK_PCREL: u32 = 21; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_ASSERT: u32 = 30; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_NOT: u32 = 31; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SUB: u32 = 32; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SL: u32 = 33; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_SR: u32 = 34; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_ADD: u32 = 35; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_AND: u32 = 36; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_IF_ELSE: u32 = 37; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; -+#[allow(missing_docs)] -+pub const R_LARCH_SOP_POP_32_U: u32 = 46; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD8: u32 = 47; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD16: u32 = 48; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD24: u32 = 49; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD32: u32 = 50; -+#[allow(missing_docs)] -+pub const R_LARCH_ADD64: u32 = 51; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB8: u32 = 52; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB16: u32 = 53; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB24: u32 = 54; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB32: u32 = 55; -+#[allow(missing_docs)] -+pub const R_LARCH_SUB64: u32 = 56; -+#[allow(missing_docs)] -+pub const R_LARCH_GNU_VTINHERIT: u32 = 57; -+#[allow(missing_docs)] -+pub const R_LARCH_GNU_VTENTRY: u32 = 58; -+ - // BPF values `Rel*::r_type`. - /// No reloc - pub const R_BPF_NONE: u32 = 0; -@@ -6250,129 +6367,6 @@ pub const R_NDS32_TLS_TPOFF: u32 = 102; - #[allow(missing_docs)] - pub const R_NDS32_TLS_DESC: u32 = 119; - --// LoongArch values `FileHeader*::e_flags`. --/// Uses 64-bit GPRs and the stack for parameter passing --pub const EF_LARCH_ABI_LP64S: u32 = 0x1; --/// Uses 64-bit GPRs, 32-bit FPRs and the stack for parameter passing --pub const EF_LARCH_ABI_LP64F: u32 = 0x2; --/// Uses 64-bit GPRs, 64-bit FPRs and the stack for parameter passing --pub const EF_LARCH_ABI_LP64D: u32 = 0x3; --/// Uses 32-bit GPRs and the stack for parameter passing --pub const EF_LARCH_ABI_ILP32S: u32 = 0x5; --/// Uses 32-bit GPRs, 32-bit FPRs and the stack for parameter passing --pub const EF_LARCH_ABI_ILP32F: u32 = 0x6; --/// Uses 32-bit GPRs, 64-bit FPRs and the stack for parameter passing --pub const EF_LARCH_ABI_ILP32D: u32 = 0x7; -- --// LoongArch values `Rel*::r_type`. --/// No reloc --pub const R_LARCH_NONE: u32 = 0; --/// Runtime address resolving --pub const R_LARCH_32: u32 = 1; --/// Runtime address resolving --pub const R_LARCH_64: u32 = 2; --/// Runtime fixup for load-address --pub const R_LARCH_RELATIVE: u32 = 3; --/// Runtime memory copy in executable --pub const R_LARCH_COPY: u32 = 4; --/// Runtime PLT supporting --pub const R_LARCH_JUMP_SLOT: u32 = 5; --/// Runtime relocation for TLS-GD --pub const R_LARCH_TLS_DTPMOD32: u32 = 6; --/// Runtime relocation for TLS-GD --pub const R_LARCH_TLS_DTPMOD64: u32 = 7; --/// Runtime relocation for TLS-GD --pub const R_LARCH_TLS_DTPREL32: u32 = 8; --/// Runtime relocation for TLS-GD --pub const R_LARCH_TLS_DTPREL64: u32 = 9; --/// Runtime relocation for TLE-IE --pub const R_LARCH_TLS_TPREL32: u32 = 10; --/// Runtime relocation for TLE-IE --pub const R_LARCH_TLS_TPREL64: u32 = 11; --/// Runtime local indirect function resolving --pub const R_LARCH_IRELATIVE: u32 = 12; --/// Mark la.abs: load absolute address for static link. --pub const R_LARCH_MARK_LA: u32 = 20; --/// Mark external label branch: access PC relative address for static link. --pub const R_LARCH_MARK_PCREL: u32 = 21; --/// Push PC-relative offset --pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; --/// Push constant or absolute address --pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; --/// Duplicate stack top --pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; --/// Push for access GOT entry --pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; --/// Push for TLS-LE --pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; --/// Push for TLS-IE --pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; --/// Push for TLS-GD --pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; --/// Push for external function calling --pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; --/// Assert stack top --pub const R_LARCH_SOP_ASSERT: u32 = 30; --/// Stack top logical not (unary) --pub const R_LARCH_SOP_NOT: u32 = 31; --/// Stack top subtraction (binary) --pub const R_LARCH_SOP_SUB: u32 = 32; --/// Stack top left shift (binary) --pub const R_LARCH_SOP_SL: u32 = 33; --/// Stack top right shift (binary) --pub const R_LARCH_SOP_SR: u32 = 34; --/// Stack top addition (binary) --pub const R_LARCH_SOP_ADD: u32 = 35; --/// Stack top bitwise and (binary) --pub const R_LARCH_SOP_AND: u32 = 36; --/// Stack top selection (tertiary) --pub const R_LARCH_SOP_IF_ELSE: u32 = 37; --/// Pop stack top to fill 5-bit signed immediate operand --pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; --/// Pop stack top to fill 12-bit unsigned immediate operand --pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; --/// Pop stack top to fill 12-bit signed immediate operand --pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; --/// Pop stack top to fill 16-bit signed immediate operand --pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; --/// Pop stack top to fill 18-bit signed immediate operand with two trailing --/// zeros implied --pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; --/// Pop stack top to fill 20-bit signed immediate operand --pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; --/// Pop stack top to fill 23-bit signed immediate operand with two trailing --/// zeros implied --pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; --/// Pop stack top to fill 28-bit signed immediate operand with two trailing --/// zeros implied --pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; --/// Pop stack top to fill an instruction --pub const R_LARCH_SOP_POP_32_U: u32 = 46; --/// 8-bit in-place addition --pub const R_LARCH_ADD8: u32 = 47; --/// 16-bit in-place addition --pub const R_LARCH_ADD16: u32 = 48; --/// 24-bit in-place addition --pub const R_LARCH_ADD24: u32 = 49; --/// 32-bit in-place addition --pub const R_LARCH_ADD32: u32 = 50; --/// 64-bit in-place addition --pub const R_LARCH_ADD64: u32 = 51; --/// 8-bit in-place subtraction --pub const R_LARCH_SUB8: u32 = 52; --/// 16-bit in-place subtraction --pub const R_LARCH_SUB16: u32 = 53; --/// 24-bit in-place subtraction --pub const R_LARCH_SUB24: u32 = 54; --/// 32-bit in-place subtraction --pub const R_LARCH_SUB32: u32 = 55; --/// 64-bit in-place subtraction --pub const R_LARCH_SUB64: u32 = 56; --/// GNU C++ vtable hierarchy --pub const R_LARCH_GNU_VTINHERIT: u32 = 57; --/// GNU C++ vtable member usage --pub const R_LARCH_GNU_VTENTRY: u32 = 58; -- - unsafe_impl_endian_pod!( - FileHeader32, - FileHeader64, -diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs -index 8c1fa4717..7541e8ebf 100644 ---- a/vendor/object/src/write/elf/object.rs -+++ b/vendor/object/src/write/elf/object.rs -@@ -74,7 +74,6 @@ impl<'a> Object<'a> { - Architecture::X86_64 => true, - Architecture::X86_64_X32 => true, - Architecture::Hexagon => true, -- Architecture::LoongArch64 => true, - Architecture::Mips => false, - Architecture::Mips64 => true, - Architecture::Msp430 => true, -@@ -84,6 +83,7 @@ impl<'a> Object<'a> { - Architecture::Riscv32 => true, - Architecture::S390x => true, - Architecture::Sparc64 => true, -+ Architecture::LoongArch64 => true, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", -@@ -271,7 +271,6 @@ impl<'a> Object<'a> { - Architecture::X86_64 => elf::EM_X86_64, - Architecture::X86_64_X32 => elf::EM_X86_64, - Architecture::Hexagon => elf::EM_HEXAGON, -- Architecture::LoongArch64 => elf::EM_LOONGARCH, - Architecture::Mips => elf::EM_MIPS, - Architecture::Mips64 => elf::EM_MIPS, - Architecture::Msp430 => elf::EM_MSP430, -@@ -281,6 +280,7 @@ impl<'a> Object<'a> { - Architecture::Riscv64 => elf::EM_RISCV, - Architecture::S390x => elf::EM_S390, - Architecture::Sparc64 => elf::EM_SPARCV9, -+ Architecture::LoongArch64 => elf::EM_LOONGARCH, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", -@@ -524,8 +524,7 @@ impl<'a> Object<'a> { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, -- Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) -- { -+ Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, - (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, - (RelocationKind::Elf(x), _, _) => x, --- -2.41.0 - diff --git a/0005-llvm-update-loongarch64-support.patch b/0005-llvm-update-loongarch64-support.patch deleted file mode 100644 index 10258a2..0000000 --- a/0005-llvm-update-loongarch64-support.patch +++ /dev/null @@ -1,70995 +0,0 @@ -From fdea5c854378f7722ec6443de42999ba83f9c086 Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Sun, 25 Jun 2023 16:27:22 +0800 -Subject: [PATCH 5/6] llvm: update loongarch64 support - ---- - .../readability/SimplifyBooleanExprCheck.cpp | 4 +- - .../clang-tools-extra/clangd/CodeComplete.cpp | 5 +- - .../clang-tools-extra/clangd/Headers.cpp | 26 +- - .../clang-tools-extra/clangd/Headers.h | 6 + - .../clang-tools-extra/clangd/InlayHints.cpp | 59 +- - .../clang-tools-extra/clangd/TidyProvider.cpp | 10 +- - .../clangd/index/CanonicalIncludes.cpp | 16 +- - .../clangd/test/lit.site.cfg.py.in | 1 + - .../clangd/unittests/CodeCompleteTests.cpp | 17 + - .../clangd/unittests/HeadersTests.cpp | 14 + - .../clangd/unittests/InlayHintTests.cpp | 9 + - ...y-bool-expr-chained-conditional-return.cpp | 11 + - src/llvm-project/clang/CMakeLists.txt | 1 + - src/llvm-project/clang/docs/ReleaseNotes.rst | 6 + - .../clang/lib/Basic/CMakeLists.txt | 4 + - src/llvm-project/clang/lib/CodeGen/CGStmt.cpp | 15 + - .../clang/lib/CodeGen/TargetInfo.cpp | 8 +- - .../clang/lib/Driver/ToolChains/Gnu.cpp | 40 +- - src/llvm-project/clang/lib/Sema/SemaInit.cpp | 8 +- - .../clang/lib/Sema/SemaLookup.cpp | 8 +- - src/llvm-project/clang/lib/Sema/SemaType.cpp | 3 + - .../lib/StaticAnalyzer/Core/ExprEngine.cpp | 6 + - .../clang/lib/Tooling/Syntax/Tokens.cpp | 222 +- - .../test/Analysis/template-param-objects.cpp | 33 + - .../clang/test/CodeGen/arm-vaarg.c | 23 + - .../test/CodeGen/attr-btf_type_tag-func-ptr.c | 15 + - .../test/CodeGen/debug-info-enum-case-val.c | 30 + - .../clang/test/Sema/gnu-builtins.c | 13 + - .../SemaCXX/specialization-diagnose-crash.cpp | 24 + - .../clang/unittests/Driver/ToolChainTest.cpp | 92 - - .../unittests/Tooling/Syntax/TokensTest.cpp | 56 + - .../cmake/Modules/FindLibEdit.cmake | 1 + - .../cmake/Modules/CompilerRTDarwinUtils.cmake | 2 +- - .../compiler-rt/cmake/config-ix.cmake | 2 +- - .../compiler-rt/lib/builtins/CMakeLists.txt | 2 +- - .../lib/sanitizer_common/sanitizer_common.h | 2 +- - .../sanitizer_common_interceptors.inc | 2 +- - .../sanitizer_common/sanitizer_stack_store.h | 2 +- - .../TestCases/Linux/sem_init_glibc.cpp | 43 +- - .../function.objects/func.blocks.arc.pass.mm | 89 + - .../vector.bool/ctor_exceptions.pass.cpp | 141 + - .../vector/vector.cons/exceptions.pass.cpp | 229 + - src/llvm-project/libunwind/CMakeLists.txt | 2 +- - src/llvm-project/libunwind/README_RUST_SGX.md | 22 - - .../libunwind/cmake/config-ix.cmake | 2 +- - .../libunwind/docs/BuildingLibunwind.rst | 5 - - .../libunwind/src/AddressSpace.hpp | 27 - - src/llvm-project/libunwind/src/CMakeLists.txt | 47 +- - src/llvm-project/libunwind/src/RWMutex.hpp | 2 +- - .../libunwind/src/UnwindRustSgx.c | 125 - - .../libunwind/src/UnwindRustSgx.h | 94 - - src/llvm-project/libunwind/src/config.h | 4 - - src/llvm-project/lld/CMakeLists.txt | 13 - - src/llvm-project/lld/COFF/CMakeLists.txt | 1 + - src/llvm-project/lld/Common/CMakeLists.txt | 9 +- - src/llvm-project/lld/ELF/Arch/RISCV.cpp | 6 +- - src/llvm-project/lld/ELF/Driver.cpp | 9 +- - src/llvm-project/lld/ELF/InputFiles.cpp | 6 +- - src/llvm-project/lld/ELF/InputSection.cpp | 11 +- - .../lld/ELF/SyntheticSections.cpp | 10 +- - .../lld/MachO/UnwindInfoSection.cpp | 35 +- - .../lld/MachO/UnwindInfoSection.h | 2 +- - src/llvm-project/lld/MachO/Writer.cpp | 2 +- - .../lld/test/ELF/comdat-binding2.s | 42 + - .../lld/test/ELF/lto-plugin-ignore.s | 2 + - .../test/MachO/eh-frame-personality-dedup.s | 43 + - src/llvm-project/lld/test/wasm/export-all.s | 7 +- - .../lld/test/wasm/mutable-global-exports.s | 7 +- - src/llvm-project/lld/wasm/Driver.cpp | 1 + - src/llvm-project/lld/wasm/Symbols.cpp | 1 + - src/llvm-project/lld/wasm/Symbols.h | 11 +- - src/llvm-project/lld/wasm/Writer.cpp | 16 +- - src/llvm-project/lldb/bindings/CMakeLists.txt | 2 - - .../lldb/bindings/interfaces.swig | 3 - - .../lldb/bindings/python/python-typemaps.swig | 2 +- - .../lldb/include/lldb/API/SBType.h | 2 + - .../lldb/include/lldb/Symbol/CompilerType.h | 24 +- - .../lldb/include/lldb/Symbol/TypeSystem.h | 14 +- - src/llvm-project/lldb/source/API/SBType.cpp | 12 +- - .../source/Plugins/Process/Linux/Perf.cpp | 31 +- - .../TypeSystem/Clang/TypeSystemClang.cpp | 81 +- - .../TypeSystem/Clang/TypeSystemClang.h | 19 +- - .../lldb/source/Symbol/CompilerType.cpp | 18 +- - .../lldb/source/Symbol/TypeSystem.cpp | 12 +- - .../TestTemplatePackArgs.py | 38 + - .../class-template-parameter-pack/main.cpp | 8 +- - .../tools/debugserver/source/CMakeLists.txt | 2 +- - .../unittests/Symbol/TestTypeSystemClang.cpp | 30 +- - src/llvm-project/llvm/CMakeLists.txt | 5 +- - src/llvm-project/llvm/cmake/config-ix.cmake | 4 +- - src/llvm-project/llvm/cmake/config.guess | 3 + - .../llvm/cmake/modules/AddLLVM.cmake | 1 + - .../llvm/cmake/modules/CheckAtomic.cmake | 13 + - .../llvm/cmake/modules/FindFFI.cmake | 2 +- - .../llvm/cmake/modules/FindTerminfo.cmake | 2 +- - .../llvm/cmake/modules/FindZ3.cmake | 3 +- - .../llvm/cmake/modules/Findzstd.cmake | 49 + - .../cmake/modules/HandleLLVMOptions.cmake | 2 +- - .../llvm/cmake/modules/LLVMConfig.cmake.in | 1 - - src/llvm-project/llvm/docs/ReleaseNotes.rst | 14 + - .../llvm/include/llvm/ADT/Triple.h | 11 + - .../llvm/include/llvm/BinaryFormat/ELF.h | 23 +- - .../llvm/include/llvm/IR/CMakeLists.txt | 1 + - .../llvm/include/llvm/IR/InlineAsm.h | 1 + - .../llvm/include/llvm/IR/Intrinsics.td | 1 + - .../include/llvm/IR/IntrinsicsLoongArch.td | 3657 +++++++ - .../llvm/lib/Analysis/ScalarEvolution.cpp | 7 +- - .../llvm/lib/Analysis/VectorUtils.cpp | 7 +- - .../llvm/lib/CodeGen/PrologEpilogInserter.cpp | 8 +- - .../llvm/lib/CodeGen/RegAllocFast.cpp | 3 + - .../lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 3 + - .../SelectionDAG/SelectionDAGBuilder.cpp | 1 + - .../CodeGen/TargetLoweringObjectFileImpl.cpp | 10 + - .../llvm/lib/CodeGen/TypePromotion.cpp | 4 +- - .../lib/DebugInfo/DWARF/DWARFVerifier.cpp | 6 +- - src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp | 2 +- - src/llvm-project/llvm/lib/IR/Function.cpp | 1 + - .../llvm/lib/MC/MCObjectFileInfo.cpp | 6 + - .../llvm/lib/Object/RelocationResolver.cpp | 26 + - .../llvm/lib/ObjectYAML/ELFYAML.cpp | 8 - - .../llvm/lib/Support/CMakeLists.txt | 21 +- - src/llvm-project/llvm/lib/Support/Triple.cpp | 1 + - .../lib/Support/UnicodeNameToCodepoint.cpp | 8 +- - .../llvm/lib/Support/Unix/Path.inc | 2 +- - .../llvm/lib/Support/Unix/Signals.inc | 4 - - .../llvm/lib/Support/Windows/Threading.inc | 6 - - .../llvm/lib/Support/X86TargetParser.cpp | 10 +- - .../Target/AArch64/AArch64ISelLowering.cpp | 67 +- - .../lib/Target/AArch64/AArch64ISelLowering.h | 2 +- - .../llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 + - .../lib/Target/ARM/ARMTargetTransformInfo.cpp | 2 +- - .../Target/LoongArch/AsmParser/CMakeLists.txt | 4 +- - .../AsmParser/LoongArchAsmParser.cpp | 2529 ++++- - .../llvm/lib/Target/LoongArch/CMakeLists.txt | 13 +- - .../LoongArch/Disassembler/CMakeLists.txt | 4 +- - .../Disassembler/LoongArchDisassembler.cpp | 921 +- - .../llvm/lib/Target/LoongArch/LoongArch.h | 37 +- - .../llvm/lib/Target/LoongArch/LoongArch.td | 166 +- - .../Target/LoongArch/LoongArch32InstrInfo.td | 717 ++ - .../Target/LoongArch/LoongArchAsmPrinter.cpp | 614 +- - .../Target/LoongArch/LoongArchAsmPrinter.h | 115 +- - .../lib/Target/LoongArch/LoongArchCCState.cpp | 165 + - .../lib/Target/LoongArch/LoongArchCCState.h | 165 + - .../Target/LoongArch/LoongArchCallingConv.td | 309 +- - .../LoongArch/LoongArchExpandPseudo.cpp | 2471 +++++ - .../LoongArch/LoongArchFloat32InstrInfo.td | 229 - - .../LoongArch/LoongArchFloat64InstrInfo.td | 242 - - .../LoongArch/LoongArchFloatInstrFormats.td | 241 - - .../LoongArch/LoongArchFrameLowering.cpp | 610 +- - .../Target/LoongArch/LoongArchFrameLowering.h | 61 +- - .../LoongArch/LoongArchISelDAGToDAG.cpp | 946 +- - .../Target/LoongArch/LoongArchISelDAGToDAG.h | 143 +- - .../LoongArch/LoongArchISelLowering.cpp | 8809 +++++++++++++++-- - .../Target/LoongArch/LoongArchISelLowering.h | 632 +- - .../Target/LoongArch/LoongArchInstrFormats.td | 842 +- - .../Target/LoongArch/LoongArchInstrInfo.cpp | 1067 +- - .../lib/Target/LoongArch/LoongArchInstrInfo.h | 220 +- - .../Target/LoongArch/LoongArchInstrInfo.td | 2646 +++-- - .../Target/LoongArch/LoongArchInstrInfoF.td | 630 ++ - .../LoongArch/LoongArchLASXInstrFormats.td | 448 + - .../LoongArch/LoongArchLASXInstrInfo.td | 5673 +++++++++++ - .../LoongArch/LoongArchLSXInstrFormats.td | 449 + - .../Target/LoongArch/LoongArchLSXInstrInfo.td | 5906 +++++++++++ - .../Target/LoongArch/LoongArchMCInstLower.cpp | 357 +- - .../Target/LoongArch/LoongArchMCInstLower.h | 55 + - .../LoongArch/LoongArchMachineFunction.cpp | 58 + - .../LoongArch/LoongArchMachineFunction.h | 103 + - .../LoongArch/LoongArchMachineFunctionInfo.h | 57 - - .../LoongArch/LoongArchModuleISelDAGToDAG.cpp | 53 + - .../LoongArch/LoongArchRegisterInfo.cpp | 376 +- - .../Target/LoongArch/LoongArchRegisterInfo.h | 62 +- - .../Target/LoongArch/LoongArchRegisterInfo.td | 484 +- - .../Target/LoongArch/LoongArchSubtarget.cpp | 99 +- - .../lib/Target/LoongArch/LoongArchSubtarget.h | 146 +- - .../LoongArch/LoongArchTargetMachine.cpp | 170 +- - .../Target/LoongArch/LoongArchTargetMachine.h | 34 +- - .../LoongArch/LoongArchTargetObjectFile.cpp | 26 + - .../LoongArch/LoongArchTargetObjectFile.h | 24 + - .../LoongArch/LoongArchTargetStreamer.h | 130 + - .../LoongArchTargetTransformInfo.cpp | 325 + - .../LoongArch/LoongArchTargetTransformInfo.h | 91 + - .../LoongArch/MCTargetDesc/CMakeLists.txt | 11 +- - .../MCTargetDesc/LoongArchABIInfo.cpp | 106 + - .../LoongArch/MCTargetDesc/LoongArchABIInfo.h | 76 + - .../LoongArchAnalyzeImmediate.cpp | 64 + - ...chMatInt.h => LoongArchAnalyzeImmediate.h} | 15 +- - .../MCTargetDesc/LoongArchAsmBackend.cpp | 202 +- - .../MCTargetDesc/LoongArchAsmBackend.h | 78 +- - .../MCTargetDesc/LoongArchBaseInfo.cpp | 40 - - .../MCTargetDesc/LoongArchBaseInfo.h | 134 +- - .../MCTargetDesc/LoongArchELFObjectWriter.cpp | 176 +- - .../MCTargetDesc/LoongArchELFStreamer.cpp | 138 + - .../MCTargetDesc/LoongArchELFStreamer.h | 53 + - .../MCTargetDesc/LoongArchFixupKinds.h | 90 + - .../MCTargetDesc/LoongArchInstPrinter.cpp | 237 +- - .../MCTargetDesc/LoongArchInstPrinter.h | 110 +- - .../MCTargetDesc/LoongArchMCAsmInfo.cpp | 33 +- - .../MCTargetDesc/LoongArchMCAsmInfo.h | 9 +- - .../MCTargetDesc/LoongArchMCCodeEmitter.cpp | 1480 ++- - .../MCTargetDesc/LoongArchMCCodeEmitter.h | 146 + - .../MCTargetDesc/LoongArchMCExpr.cpp | 158 + - .../LoongArch/MCTargetDesc/LoongArchMCExpr.h | 97 + - .../MCTargetDesc/LoongArchMCTargetDesc.cpp | 144 +- - .../MCTargetDesc/LoongArchMCTargetDesc.h | 28 +- - .../MCTargetDesc/LoongArchMatInt.cpp | 51 - - .../MCTargetDesc/LoongArchTargetStreamer.cpp | 330 + - .../LoongArch/TargetInfo/CMakeLists.txt | 1 - - .../TargetInfo/LoongArchTargetInfo.cpp | 18 +- - .../TargetInfo/LoongArchTargetInfo.h | 4 +- - .../llvm/lib/Target/Sparc/SparcCallingConv.td | 10 +- - .../lib/Target/Sparc/SparcISelLowering.cpp | 61 +- - .../llvm/lib/Target/Sparc/SparcISelLowering.h | 5 + - src/llvm-project/llvm/lib/Target/X86/X86.td | 1 - - .../llvm/lib/Transforms/IPO/GlobalOpt.cpp | 2 +- - .../InstCombine/InstCombineCalls.cpp | 4 + - .../ControlHeightReduction.cpp | 1 + - .../llvm/lib/Transforms/Scalar/SROA.cpp | 19 +- - .../lib/Transforms/Utils/LoopVersioning.cpp | 4 +- - .../llvm/lib/Transforms/Utils/VNCoercion.cpp | 4 +- - .../Transforms/Vectorize/LoopVectorize.cpp | 4 +- - .../llvm/lib/Transforms/Vectorize/VPlan.cpp | 2 +- - .../llvm/lib/Transforms/Vectorize/VPlan.h | 2 +- - .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 5 +- - src/llvm-project/llvm/test/CMakeLists.txt | 1 + - .../llvm/test/CodeGen/LoongArch/1ri.mir | 96 - - .../llvm/test/CodeGen/LoongArch/2r.mir | 230 - - .../llvm/test/CodeGen/LoongArch/2ri.mir | 432 - - .../llvm/test/CodeGen/LoongArch/3r.mir | 995 -- - .../llvm/test/CodeGen/LoongArch/3ri.mir | 69 - - .../llvm/test/CodeGen/LoongArch/align.ll | 8 + - .../CodeGen/LoongArch/atomic-operand-imm0.ll | 17 + - .../test/CodeGen/LoongArch/atomic_16_8.ll | 809 ++ - .../test/CodeGen/LoongArch/atomic_64_32.ll | 327 + - .../llvm/test/CodeGen/LoongArch/bss.ll | 5 + - .../LoongArch/builtins-loongarch-base.ll | 752 ++ - .../llvm/test/CodeGen/LoongArch/const-mult.ll | 245 + - .../CodeGen/LoongArch/disable-tail-calls.ll | 94 + - .../llvm/test/CodeGen/LoongArch/divrem.ll | 68 + - .../llvm/test/CodeGen/LoongArch/dup-tail.ll | 45 + - .../test/CodeGen/LoongArch/eliminateFI.ll | 106 + - .../CodeGen/LoongArch/emergency-spill-slot.ll | 103 + - .../llvm/test/CodeGen/LoongArch/fcopysign.ll | 17 + - .../llvm/test/CodeGen/LoongArch/frame-info.ll | 132 + - .../llvm/test/CodeGen/LoongArch/fsel.ll | 47 + - .../llvm/test/CodeGen/LoongArch/immediate.ll | 2542 +++++ - .../CodeGen/LoongArch/inlineasm/extra-code.ll | 8 + - .../inlineasm/floating-point-in-gpr.ll | 31 + - .../non-native-value-type-registers-error.ll | 8 + - .../non-native-value-type-registers.ll | 42 + - .../test/CodeGen/LoongArch/inlineasm/preld.ll | 8 + - .../test/CodeGen/LoongArch/jirl-verify.ll | 34 + - .../test/CodeGen/LoongArch/lasx/VExtend.ll | 54 + - .../CodeGen/LoongArch/lasx/imm_vector_lasx.ll | 176 + - .../test/CodeGen/LoongArch/lasx/inline-asm.ll | 55 + - .../CodeGen/LoongArch/lasx/insert-lasx.ll | 38 + - .../CodeGen/LoongArch/lasx/intrinsic-lasx.ll | 70 + - .../test/CodeGen/LoongArch/lasx/lasxvclr.ll | 46 + - .../test/CodeGen/LoongArch/lasx/logic-lasx.ll | 130 + - .../test/CodeGen/LoongArch/lasx/set-lasx.ll | 38 + - .../LoongArch/lasx/shuffle_v4i64_1032.ll | 19 + - .../test/CodeGen/LoongArch/lasx/vext2xv.ll | 65 + - .../test/CodeGen/LoongArch/lasx/xvadda.ll | 62 + - .../test/CodeGen/LoongArch/lasx/xvaddsub.ll | 98 + - .../test/CodeGen/LoongArch/lasx/xvhadd.ll | 21 + - .../test/CodeGen/LoongArch/lasx/xvilvh.ll | 32 + - .../test/CodeGen/LoongArch/lasx/xvilvl.ll | 32 + - .../llvm/test/CodeGen/LoongArch/ldptr.ll | 70 + - .../llvm/test/CodeGen/LoongArch/lit.local.cfg | 12 +- - .../llvm/test/CodeGen/LoongArch/logic-op.ll | 171 + - .../llvm/test/CodeGen/LoongArch/lshr.ll | 12 + - .../CodeGen/LoongArch/lsx/imm_vector_lsx.ll | 176 + - .../test/CodeGen/LoongArch/lsx/inline-asm.ll | 34 + - .../CodeGen/LoongArch/lsx/intrinsic-lsx.ll | 92 + - .../test/CodeGen/LoongArch/lsx/logic-lsx.ll | 132 + - .../test/CodeGen/LoongArch/lsx/lsxvclr.ll | 50 + - .../test/CodeGen/LoongArch/lsx/set-lsx.ll | 38 + - .../llvm/test/CodeGen/LoongArch/lsx/vadda.ll | 62 + - .../llvm/test/CodeGen/LoongArch/lu12i.ll | 7 + - .../llvm/test/CodeGen/LoongArch/mcpu_load.ll | 72 + - .../llvm/test/CodeGen/LoongArch/misc.mir | 200 - - .../test/CodeGen/LoongArch/named-register.ll | 29 + - .../llvm/test/CodeGen/LoongArch/nomerge.ll | 35 + - .../llvm/test/CodeGen/LoongArch/noti32.ll | 143 + - .../LoongArch/peephole-load-store-addi.ll | 100 + - .../llvm/test/CodeGen/LoongArch/signext.ll | 37 + - .../llvm/test/CodeGen/LoongArch/stptr.ll | 52 + - .../llvm/test/CodeGen/LoongArch/tailcall-R.ll | 62 + - .../test/CodeGen/LoongArch/tailcall-check.ll | 155 + - .../test/CodeGen/LoongArch/tailcall-mem.ll | 35 + - .../llvm/test/CodeGen/LoongArch/tailcall.ll | 13 + - .../test/CodeGen/LoongArch/thread-pointer.ll | 9 + - .../llvm/test/CodeGen/LoongArch/trunc.ll | 108 + - .../test/CodeGen/LoongArch/unalignment.ll | 72 + - .../PowerPC/regalloc-fast-debug-spill.ll | 250 + - .../llvm/test/CodeGen/SPARC/bigreturn.ll | 254 + - .../CodeGen/X86/zero-call-used-regs-i386.ll | 112 + - .../llvm/test/MC/LoongArch/aligned-nops.s | 25 + - .../llvm/test/MC/LoongArch/atomic-error.s | 7 + - .../llvm/test/MC/LoongArch/atomic.s | 12 + - .../llvm/test/MC/LoongArch/fixups-expr.s | 40 + - .../llvm/test/MC/LoongArch/invalid.s | 50 + - .../llvm/test/MC/LoongArch/lit.local.cfg | 1 + - .../llvm/test/MC/LoongArch/macro-la.s | 168 + - .../llvm/test/MC/LoongArch/macro-li.s | 773 ++ - .../llvm/test/MC/LoongArch/valid_12imm.s | 33 + - .../llvm/test/MC/LoongArch/valid_4operands.s | 53 + - .../llvm/test/MC/LoongArch/valid_bigimm.s | 33 + - .../llvm/test/MC/LoongArch/valid_branch.s | 155 + - .../llvm/test/MC/LoongArch/valid_float.s | 297 + - .../llvm/test/MC/LoongArch/valid_integer.s | 369 + - .../llvm/test/MC/LoongArch/valid_memory.s | 405 + - .../llvm/test/MC/LoongArch/valid_priv.s | 125 + - .../test/Support/unix03-sigpipe-exit.test | 26 - - .../AtomicExpand/LoongArch/lit.local.cfg | 5 - - .../Transforms/GlobalOpt/inalloca-varargs.ll | 38 + - .../test/Transforms/InstCombine/cast-byval.ll | 31 + - .../versioning-scev-invalidation.ll | 125 + - ...interleave-allocsize-not-equal-typesize.ll | 141 + - .../phi-speculate-different-load-types.ll | 41 + - .../loongarch_function_name.ll.expected | 6 +- - ...arch_generated_funcs.ll.generated.expected | 148 - - ...ch_generated_funcs.ll.nogenerated.expected | 147 - - .../loongarch_generated_funcs.test | 17 - - .../llvm-readobj/ELF/loongarch-eflags.test | 64 - - .../tools/obj2yaml/ELF/loongarch-eflags.yaml | 29 - - .../llvm/tools/dsymutil/CMakeLists.txt | 4 +- - .../llvm/tools/llvm-config/CMakeLists.txt | 8 +- - .../llvm/tools/llvm-readobj/ELFDumper.cpp | 15 - - .../clang-tidy/misc/BUILD.gn | 2 +- - .../llvm/utils/gn/secondary/llvm/version.gni | 2 +- - .../llvm/utils/lit/lit/__init__.py | 2 +- - .../llvm/utils/lit/lit/llvm/config.py | 2 +- - 332 files changed, 57210 insertions(+), 7989 deletions(-) - create mode 100644 src/llvm-project/clang/test/Analysis/template-param-objects.cpp - create mode 100644 src/llvm-project/clang/test/CodeGen/arm-vaarg.c - create mode 100644 src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c - create mode 100644 src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c - create mode 100644 src/llvm-project/clang/test/Sema/gnu-builtins.c - create mode 100644 src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp - create mode 100644 src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm - create mode 100644 src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp - create mode 100644 src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp - delete mode 100644 src/llvm-project/libunwind/README_RUST_SGX.md - delete mode 100644 src/llvm-project/libunwind/src/UnwindRustSgx.c - delete mode 100644 src/llvm-project/libunwind/src/UnwindRustSgx.h - create mode 100644 src/llvm-project/lld/test/ELF/comdat-binding2.s - create mode 100644 src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s - create mode 100644 src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py - create mode 100644 src/llvm-project/llvm/cmake/modules/Findzstd.cmake - create mode 100644 src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp - rename src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/{LoongArchMatInt.h => LoongArchAnalyzeImmediate.h} (62%) - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h - delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp - create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll - delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll - create mode 100644 src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/atomic.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/invalid.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/macro-la.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/macro-li.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_float.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s - create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s - delete mode 100644 src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test - delete mode 100644 src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg - create mode 100644 src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll - create mode 100644 src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll - create mode 100644 src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll - create mode 100644 src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll - create mode 100644 src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll - delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected - delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected - delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test - delete mode 100644 src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test - delete mode 100644 src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml - -diff --git a/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp -index 8ae990a92..afb4a1044 100644 ---- a/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp -+++ b/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp -@@ -472,8 +472,8 @@ public: - checkSingleStatement(If->getThen(), parseReturnLiteralBool); - if (ThenReturnBool && - ThenReturnBool.Bool != TrailingReturnBool.Bool) { -- if (Check->ChainedConditionalReturn || -- (!PrevIf && If->getElse() == nullptr)) { -+ if ((Check->ChainedConditionalReturn || !PrevIf) && -+ If->getElse() == nullptr) { - Check->replaceCompoundReturnWithCondition( - Context, cast(*Second), TrailingReturnBool.Bool, - If, ThenReturnBool.Item); -diff --git a/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp b/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp -index edbb1722a..55982f412 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp -@@ -486,6 +486,9 @@ private: - // we need to complete 'forward<$1>($0)'. - return "($0)"; - -+ if (Snippet->empty()) -+ return ""; -+ - bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function || - Completion.Kind == CompletionItemKind::Method || - Completion.Kind == CompletionItemKind::Constructor || -@@ -524,8 +527,6 @@ private: - return *Snippet; - - // Replace argument snippets with a simplified pattern. -- if (Snippet->empty()) -- return ""; - if (MayHaveArgList) { - // Functions snippets can be of 2 types: - // - containing only function arguments, e.g. -diff --git a/src/llvm-project/clang-tools-extra/clangd/Headers.cpp b/src/llvm-project/clang-tools-extra/clangd/Headers.cpp -index cb7abac3e..af22a446b 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/Headers.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/Headers.cpp -@@ -22,9 +22,17 @@ - namespace clang { - namespace clangd { - --const char IWYUPragmaKeep[] = "// IWYU pragma: keep"; --const char IWYUPragmaExport[] = "// IWYU pragma: export"; --const char IWYUPragmaBeginExports[] = "// IWYU pragma: begin_exports"; -+llvm::Optional parseIWYUPragma(const char *Text) { -+ // This gets called for every comment seen in the preamble, so it's quite hot. -+ constexpr llvm::StringLiteral IWYUPragma = "// IWYU pragma: "; -+ if (strncmp(Text, IWYUPragma.data(), IWYUPragma.size())) -+ return llvm::None; -+ Text += IWYUPragma.size(); -+ const char *End = Text; -+ while (*End != 0 && *End != '\n') -+ ++End; -+ return StringRef(Text, End - Text); -+} - - class IncludeStructure::RecordHeaders : public PPCallbacks, - public CommentHandler { -@@ -129,10 +137,10 @@ public: - } - - bool HandleComment(Preprocessor &PP, SourceRange Range) override { -- bool Err = false; -- llvm::StringRef Text = SM.getCharacterData(Range.getBegin(), &Err); -- if (Err) -+ auto Pragma = parseIWYUPragma(SM.getCharacterData(Range.getBegin())); -+ if (!Pragma) - return false; -+ - if (inMainFile()) { - // Given: - // -@@ -150,8 +158,7 @@ public: - // will know that the next inclusion is behind the IWYU pragma. - // FIXME: Support "IWYU pragma: begin_exports" and "IWYU pragma: - // end_exports". -- if (!Text.startswith(IWYUPragmaExport) && -- !Text.startswith(IWYUPragmaKeep)) -+ if (!Pragma->startswith("export") && !Pragma->startswith("keep")) - return false; - unsigned Offset = SM.getFileOffset(Range.getBegin()); - LastPragmaKeepInMainFileLine = -@@ -161,8 +168,7 @@ public: - // does not support them properly yet, so they will be not marked as - // unused. - // FIXME: Once IncludeCleaner supports export pragmas, remove this. -- if (!Text.startswith(IWYUPragmaExport) && -- !Text.startswith(IWYUPragmaBeginExports)) -+ if (!Pragma->startswith("export") && !Pragma->startswith("begin_exports")) - return false; - Out->HasIWYUExport.insert( - *Out->getID(SM.getFileEntryForID(SM.getFileID(Range.getBegin())))); -diff --git a/src/llvm-project/clang-tools-extra/clangd/Headers.h b/src/llvm-project/clang-tools-extra/clangd/Headers.h -index ff3f06316..ba72ad397 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/Headers.h -+++ b/src/llvm-project/clang-tools-extra/clangd/Headers.h -@@ -35,6 +35,12 @@ namespace clangd { - /// Returns true if \p Include is literal include like "path" or . - bool isLiteralInclude(llvm::StringRef Include); - -+/// If Text begins an Include-What-You-Use directive, returns it. -+/// Given "// IWYU pragma: keep", returns "keep". -+/// Input is a null-terminated char* as provided by SM.getCharacterData(). -+/// (This should not be StringRef as we do *not* want to scan for its length). -+llvm::Optional parseIWYUPragma(const char *Text); -+ - /// Represents a header file to be #include'd. - struct HeaderFile { - std::string File; -diff --git a/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp b/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp -index 7be05fbc3..16c6b1cec 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp -@@ -10,6 +10,7 @@ - #include "Config.h" - #include "HeuristicResolver.h" - #include "ParsedAST.h" -+#include "SourceCode.h" - #include "clang/AST/Decl.h" - #include "clang/AST/DeclarationName.h" - #include "clang/AST/ExprCXX.h" -@@ -192,8 +193,8 @@ class InlayHintVisitor : public RecursiveASTVisitor { - public: - InlayHintVisitor(std::vector &Results, ParsedAST &AST, - const Config &Cfg, llvm::Optional RestrictRange) -- : Results(Results), AST(AST.getASTContext()), Cfg(Cfg), -- RestrictRange(std::move(RestrictRange)), -+ : Results(Results), AST(AST.getASTContext()), Tokens(AST.getTokens()), -+ Cfg(Cfg), RestrictRange(std::move(RestrictRange)), - MainFileID(AST.getSourceManager().getMainFileID()), - Resolver(AST.getHeuristicResolver()), - TypeHintPolicy(this->AST.getPrintingPolicy()), -@@ -227,8 +228,7 @@ public: - return true; - } - -- processCall(E->getParenOrBraceRange().getBegin(), E->getConstructor(), -- {E->getArgs(), E->getNumArgs()}); -+ processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()}); - return true; - } - -@@ -254,7 +254,7 @@ public: - if (!Callee) - return true; - -- processCall(E->getRParenLoc(), Callee, {E->getArgs(), E->getNumArgs()}); -+ processCall(Callee, {E->getArgs(), E->getNumArgs()}); - return true; - } - -@@ -278,11 +278,11 @@ public: - return true; - } - -- void addReturnTypeHint(FunctionDecl *D, SourceLocation Loc) { -+ void addReturnTypeHint(FunctionDecl *D, SourceRange Range) { - auto *AT = D->getReturnType()->getContainedAutoType(); - if (!AT || AT->getDeducedType().isNull()) - return; -- addTypeHint(Loc, D->getReturnType(), /*Prefix=*/"-> "); -+ addTypeHint(Range, D->getReturnType(), /*Prefix=*/"-> "); - } - - bool VisitVarDecl(VarDecl *D) { -@@ -375,21 +375,11 @@ public: - private: - using NameVec = SmallVector; - -- // The purpose of Anchor is to deal with macros. It should be the call's -- // opening or closing parenthesis or brace. (Always using the opening would -- // make more sense but CallExpr only exposes the closing.) We heuristically -- // assume that if this location does not come from a macro definition, then -- // the entire argument list likely appears in the main file and can be hinted. -- void processCall(SourceLocation Anchor, const FunctionDecl *Callee, -+ void processCall(const FunctionDecl *Callee, - llvm::ArrayRef Args) { - if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee) - return; - -- // If the anchor location comes from a macro defintion, there's nowhere to -- // put hints. -- if (!AST.getSourceManager().getTopMacroCallerLoc(Anchor).isFileID()) -- return; -- - // The parameter name of a move or copy constructor is not very interesting. - if (auto *Ctor = dyn_cast(Callee)) - if (Ctor->isCopyOrMoveConstructor()) -@@ -637,25 +627,33 @@ private: - #undef CHECK_KIND - } - -- auto FileRange = -- toHalfOpenFileRange(AST.getSourceManager(), AST.getLangOpts(), R); -- if (!FileRange) -+ auto LSPRange = getHintRange(R); -+ if (!LSPRange) - return; -- Range LSPRange{ -- sourceLocToPosition(AST.getSourceManager(), FileRange->getBegin()), -- sourceLocToPosition(AST.getSourceManager(), FileRange->getEnd())}; -- Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end; -+ Position LSPPos = Side == HintSide::Left ? LSPRange->start : LSPRange->end; - if (RestrictRange && - (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end))) - return; -- // The hint may be in a file other than the main file (for example, a header -- // file that was included after the preamble), do not show in that case. -- if (!AST.getSourceManager().isWrittenInMainFile(FileRange->getBegin())) -- return; - bool PadLeft = Prefix.consume_front(" "); - bool PadRight = Suffix.consume_back(" "); - Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, -- PadLeft, PadRight, LSPRange}); -+ PadLeft, PadRight, *LSPRange}); -+ } -+ -+ // Get the range of the main file that *exactly* corresponds to R. -+ llvm::Optional getHintRange(SourceRange R) { -+ const auto &SM = AST.getSourceManager(); -+ auto Spelled = Tokens.spelledForExpanded(Tokens.expandedTokens(R)); -+ // TokenBuffer will return null if e.g. R corresponds to only part of a -+ // macro expansion. -+ if (!Spelled || Spelled->empty()) -+ return llvm::None; -+ // Hint must be within the main file, not e.g. a non-preamble include. -+ if (SM.getFileID(Spelled->front().location()) != SM.getMainFileID() || -+ SM.getFileID(Spelled->back().location()) != SM.getMainFileID()) -+ return llvm::None; -+ return Range{sourceLocToPosition(SM, Spelled->front().location()), -+ sourceLocToPosition(SM, Spelled->back().endLocation())}; - } - - void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) { -@@ -680,6 +678,7 @@ private: - - std::vector &Results; - ASTContext &AST; -+ const syntax::TokenBuffer &Tokens; - const Config &Cfg; - llvm::Optional RestrictRange; - FileID MainFileID; -diff --git a/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp b/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp -index 32a4d6a30..a0a37e86b 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp -@@ -212,8 +212,14 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { - // code, which is often the case when clangd - // tries to build an AST. - "-bugprone-use-after-move", -- // Alias for bugprone-use-after-moe. -- "-hicpp-invalid-access-moved"); -+ // Alias for bugprone-use-after-move. -+ "-hicpp-invalid-access-moved", -+ -+ // ----- Performance problems ----- -+ -+ // This check runs expensive analysis for each variable. -+ // It has been observed to increase reparse time by 10x. -+ "-misc-const-correctness"); - - size_t Size = BadChecks.size(); - for (const std::string &Str : ExtraBadChecks) { -diff --git a/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp b/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp -index 145d98d57..bbc80e7e0 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp -@@ -17,8 +17,6 @@ - namespace clang { - namespace clangd { - namespace { --const char IWYUPragma[] = "// IWYU pragma: private, include "; -- - const std::pair IncludeMappings[] = { - {"include/__stddef_max_align_t.h", ""}, - {"include/__wmmintrin_aes.h", ""}, -@@ -712,17 +710,17 @@ collectIWYUHeaderMaps(CanonicalIncludes *Includes) { - PragmaCommentHandler(CanonicalIncludes *Includes) : Includes(Includes) {} - - bool HandleComment(Preprocessor &PP, SourceRange Range) override { -- llvm::StringRef Text = -- Lexer::getSourceText(CharSourceRange::getCharRange(Range), -- PP.getSourceManager(), PP.getLangOpts()); -- if (!Text.consume_front(IWYUPragma)) -+ auto Pragma = parseIWYUPragma( -+ PP.getSourceManager().getCharacterData(Range.getBegin())); -+ if (!Pragma || !Pragma->consume_front("private, include ")) - return false; - auto &SM = PP.getSourceManager(); - // We always insert using the spelling from the pragma. - if (auto *FE = SM.getFileEntryForID(SM.getFileID(Range.getBegin()))) -- Includes->addMapping( -- FE->getLastRef(), -- isLiteralInclude(Text) ? Text.str() : ("\"" + Text + "\"").str()); -+ Includes->addMapping(FE->getLastRef(), -+ isLiteralInclude(*Pragma) -+ ? Pragma->str() -+ : ("\"" + *Pragma + "\"").str()); - return false; - } - -diff --git a/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in b/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in -index 20caa72af..1fe7c8d0f 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in -+++ b/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in -@@ -10,6 +10,7 @@ config.python_executable = "@Python3_EXECUTABLE@" - config.clang_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@") - config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") - config.llvm_libs_dir = lit_config.substitute("@LLVM_LIBS_DIR@") -+config.llvm_shlib_dir = "@SHLIBDIR@" - - config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.." - config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.." -diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp -index 5050ab203..079a4ec70 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp -@@ -1014,6 +1014,23 @@ TEST(CodeCompleteTest, NoColonColonAtTheEnd) { - EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::")))); - } - -+TEST(CompletionTests, EmptySnippetDoesNotCrash) { -+ // See https://github.com/clangd/clangd/issues/1216 -+ auto Results = completions(R"cpp( -+ int main() { -+ auto w = [&](auto &&f) { return f(f); }; -+ auto f = w([&](auto &&f) { -+ return [&](auto &&n) { -+ if (n == 0) { -+ return 1; -+ } -+ return n * ^(f)(n - 1); -+ }; -+ })(10); -+ } -+ )cpp"); -+} -+ - TEST(CompletionTest, BacktrackCrashes) { - // Sema calls code completion callbacks twice in these cases. - auto Results = completions(R"cpp( -diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp -index 32e4aea15..324d4b58a 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp -@@ -9,6 +9,7 @@ - #include "Headers.h" - - #include "Compiler.h" -+#include "Matchers.h" - #include "TestFS.h" - #include "TestTU.h" - #include "clang/Basic/TokenKinds.h" -@@ -30,6 +31,7 @@ namespace { - using ::testing::AllOf; - using ::testing::Contains; - using ::testing::ElementsAre; -+using ::testing::Eq; - using ::testing::IsEmpty; - using ::testing::Not; - using ::testing::UnorderedElementsAre; -@@ -445,6 +447,18 @@ TEST_F(HeadersTest, HasIWYUPragmas) { - EXPECT_FALSE(Includes.hasIWYUExport(getID("none.h", Includes))); - } - -+TEST(Headers, ParseIWYUPragma) { -+ EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), HasValue(Eq("keep"))); -+ EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep\netc"), -+ HasValue(Eq("keep"))); -+ EXPECT_EQ(parseIWYUPragma("/* IWYU pragma: keep"), llvm::None) -+ << "Only // comments supported!"; -+ EXPECT_EQ(parseIWYUPragma("// IWYU pragma: keep"), llvm::None) -+ << "Sensitive to whitespace"; -+ EXPECT_EQ(parseIWYUPragma("// IWYU pragma:keep"), llvm::None) -+ << "Sensitive to whitespace"; -+} -+ - } // namespace - } // namespace clangd - } // namespace clang -diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp -index a429c0899..7127f6cc5 100644 ---- a/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp -+++ b/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp -@@ -820,6 +820,15 @@ TEST(ParameterHints, Macros) { - } - )cpp", - ExpectedHint{"param: ", "param"}); -+ -+ // If the macro expands to multiple arguments, don't hint it. -+ assertParameterHints(R"cpp( -+ void foo(double x, double y); -+ #define CONSTANTS 3.14, 2.72 -+ void bar() { -+ foo(CONSTANTS); -+ } -+ )cpp"); - } - - TEST(ParameterHints, ConstructorParens) { -diff --git a/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp b/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp -index 7e97e9f71..ff50528c2 100644 ---- a/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp -+++ b/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp -@@ -92,3 +92,14 @@ bool complex_chained_if_return_return_negated(int i) { - // CHECK-FIXES: {{^}} }{{$}} - // CHECK-FIXES: {{^ return i <= 10;$}} - // CHECK-FIXES: {{^}$}} -+ -+ -+bool PR57819(int x) { -+ // False positive introduced in clang-tidy-15 -+ // Expect no warning here. -+ if (x > 0) -+ return false; -+ else { -+ } -+ return true; -+} -diff --git a/src/llvm-project/clang/CMakeLists.txt b/src/llvm-project/clang/CMakeLists.txt -index 13d76e7fd..e3bc4b468 100644 ---- a/src/llvm-project/clang/CMakeLists.txt -+++ b/src/llvm-project/clang/CMakeLists.txt -@@ -117,6 +117,7 @@ if(CLANG_BUILT_STANDALONE) - include(TableGen) - include(HandleLLVMOptions) - include(VersionFromVCS) -+ include(CheckAtomic) - include(GetErrcMessages) - include(LLVMDistributionSupport) - -diff --git a/src/llvm-project/clang/docs/ReleaseNotes.rst b/src/llvm-project/clang/docs/ReleaseNotes.rst -index a17b033f5..13cca2ebb 100644 ---- a/src/llvm-project/clang/docs/ReleaseNotes.rst -+++ b/src/llvm-project/clang/docs/ReleaseNotes.rst -@@ -225,6 +225,12 @@ Bug Fixes - - Fix a crash when generating code coverage information for an - ``if consteval`` statement. This fixes - `Issue 57377 `_. -+- Fix a crash when a ``btf_type_tag`` attribute is applied to the pointee of -+ a function pointer. -+- Clang 14 predeclared some builtin POSIX library functions in ``gnu2x`` mode, -+ and Clang 15 accidentally stopped predeclaring those functions in that -+ language mode. Clang 16 now predeclares those functions again. This fixes -+ `Issue 56607 `_. - - Improvements to Clang's diagnostics - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -diff --git a/src/llvm-project/clang/lib/Basic/CMakeLists.txt b/src/llvm-project/clang/lib/Basic/CMakeLists.txt -index 3e052c0cf..c38c9fddb 100644 ---- a/src/llvm-project/clang/lib/Basic/CMakeLists.txt -+++ b/src/llvm-project/clang/lib/Basic/CMakeLists.txt -@@ -110,3 +110,7 @@ add_clang_library(clangBasic - omp_gen - ) - -+target_link_libraries(clangBasic -+ PRIVATE -+ ${LLVM_ATOMIC_LIB} -+) -diff --git a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp -index 481438de0..9935fcc0d 100644 ---- a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp -+++ b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp -@@ -1509,6 +1509,21 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S, - - llvm::ConstantInt *CaseVal = - Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); -+ -+ // Emit debuginfo for the case value if it is an enum value. -+ const ConstantExpr *CE; -+ if (auto ICE = dyn_cast(S.getLHS())) -+ CE = dyn_cast(ICE->getSubExpr()); -+ else -+ CE = dyn_cast(S.getLHS()); -+ if (CE) { -+ if (auto DE = dyn_cast(CE->getSubExpr())) -+ if (CGDebugInfo *Dbg = getDebugInfo()) -+ if (CGM.getCodeGenOpts().hasReducedDebugInfo()) -+ Dbg->EmitGlobalVariable(DE->getDecl(), -+ APValue(llvm::APSInt(CaseVal->getValue()))); -+ } -+ - if (SwitchLikelihood) - SwitchLikelihood->push_back(Stmt::getLikelihood(Attrs)); - -diff --git a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp -index 36e10e4df..44743fa02 100644 ---- a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp -+++ b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp -@@ -7047,10 +7047,10 @@ Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, - - // Empty records are ignored for parameter passing purposes. - if (isEmptyRecord(getContext(), Ty, true)) { -- Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr), -- getVAListElementType(CGF), SlotSize); -- Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); -- return Addr; -+ VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy); -+ auto *Load = CGF.Builder.CreateLoad(VAListAddr); -+ Address Addr = Address(Load, CGF.Int8Ty, SlotSize); -+ return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); - } - - CharUnits TySize = getContext().getTypeSizeInChars(Ty); -diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp -index f203cae1d..665cdc313 100644 ---- a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp -+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp -@@ -2139,31 +2139,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( - // and gcc-toolsets. - if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux && - D.getVFS().exists("/opt/rh")) { -- // Find the directory in /opt/rh/ starting with gcc-toolset-* or -- // devtoolset-* with the highest version number and add that -- // one to our prefixes. -- std::string ChosenToolsetDir; -- unsigned ChosenToolsetVersion = 0; -- std::error_code EC; -- for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC), -- LE; -- !EC && LI != LE; LI = LI.increment(EC)) { -- StringRef ToolsetDir = llvm::sys::path::filename(LI->path()); -- unsigned ToolsetVersion; -- if ((!ToolsetDir.startswith("gcc-toolset-") && -- !ToolsetDir.startswith("devtoolset-")) || -- ToolsetDir.substr(ToolsetDir.rfind('-') + 1) -- .getAsInteger(10, ToolsetVersion)) -- continue; -- -- if (ToolsetVersion > ChosenToolsetVersion) { -- ChosenToolsetVersion = ToolsetVersion; -- ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str(); -- } -- } -- -- if (ChosenToolsetVersion > 0) -- Prefixes.push_back(ChosenToolsetDir + "/root/usr"); -+ // TODO: We may want to remove this, since the functionality -+ // can be achieved using config files. -+ Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr"); -+ Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr"); -+ Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-12/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-11/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-10/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-9/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-8/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-7/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); -+ Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); - } - - // Fall back to /usr which is used by most non-Solaris systems. -diff --git a/src/llvm-project/clang/lib/Sema/SemaInit.cpp b/src/llvm-project/clang/lib/Sema/SemaInit.cpp -index d3b454843..bf7ca718a 100644 ---- a/src/llvm-project/clang/lib/Sema/SemaInit.cpp -+++ b/src/llvm-project/clang/lib/Sema/SemaInit.cpp -@@ -695,10 +695,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, - // member of reference type uninitialized, the program is - // ill-formed. - SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) -- << Field->getType() -- << ILE->getSyntacticForm()->getSourceRange(); -- SemaRef.Diag(Field->getLocation(), -- diag::note_uninit_reference_member); -+ << Field->getType() -+ << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm()) -+ ->getSourceRange(); -+ SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); - } - hadError = true; - return; -diff --git a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp -index 68158ec97..5d0d87fd2 100644 ---- a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp -+++ b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp -@@ -939,11 +939,9 @@ bool Sema::LookupBuiltin(LookupResult &R) { - - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) { -- // In C++, C2x, and OpenCL (spec v1.2 s6.9.f), we don't have any -- // predefined library functions like 'malloc'. Instead, we'll just -- // error. -- if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL || -- getLangOpts().C2x) && -+ // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined -+ // library functions like 'malloc'. Instead, we'll just error. -+ if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL) && - Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return false; - -diff --git a/src/llvm-project/clang/lib/Sema/SemaType.cpp b/src/llvm-project/clang/lib/Sema/SemaType.cpp -index 3ab5d26a9..edcac4d2e 100644 ---- a/src/llvm-project/clang/lib/Sema/SemaType.cpp -+++ b/src/llvm-project/clang/lib/Sema/SemaType.cpp -@@ -6443,6 +6443,9 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - } - -+ while (BTFTagAttributedTypeLoc TL = CurrTL.getAs()) -+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); -+ - while (DependentAddressSpaceTypeLoc TL = - CurrTL.getAs()) { - fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); -diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp -index 19149d079..ab65612bc 100644 ---- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp -+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp -@@ -2839,6 +2839,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, - return; - } - -+ if (const auto *TPO = dyn_cast(D)) { -+ // FIXME: We should meaningfully implement this. -+ (void)TPO; -+ return; -+ } -+ - llvm_unreachable("Support for this Decl not implemented."); - } - -diff --git a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp -index e2014f965..1fa73c667 100644 ---- a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp -+++ b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp -@@ -55,45 +55,140 @@ getTokensCovering(llvm::ArrayRef Toks, SourceRange R, - return {Begin, End}; - } - --// Finds the smallest expansion range that contains expanded tokens First and --// Last, e.g.: -+// Finds the range within FID corresponding to expanded tokens [First, Last]. -+// Prev precedes First and Next follows Last, these must *not* be included. -+// If no range satisfies the criteria, returns an invalid range. -+// - // #define ID(x) x - // ID(ID(ID(a1) a2)) - // ~~ -> a1 - // ~~ -> a2 - // ~~~~~~~~~ -> a1 a2 --SourceRange findCommonRangeForMacroArgs(const syntax::Token &First, -- const syntax::Token &Last, -- const SourceManager &SM) { -- SourceRange Res; -- auto FirstLoc = First.location(), LastLoc = Last.location(); -- // Keep traversing up the spelling chain as longs as tokens are part of the -- // same expansion. -- while (!FirstLoc.isFileID() && !LastLoc.isFileID()) { -- auto ExpInfoFirst = SM.getSLocEntry(SM.getFileID(FirstLoc)).getExpansion(); -- auto ExpInfoLast = SM.getSLocEntry(SM.getFileID(LastLoc)).getExpansion(); -- // Stop if expansions have diverged. -- if (ExpInfoFirst.getExpansionLocStart() != -- ExpInfoLast.getExpansionLocStart()) -+SourceRange spelledForExpandedSlow(SourceLocation First, SourceLocation Last, -+ SourceLocation Prev, SourceLocation Next, -+ FileID TargetFile, -+ const SourceManager &SM) { -+ // There are two main parts to this algorithm: -+ // - identifying which spelled range covers the expanded tokens -+ // - validating that this range doesn't cover any extra tokens (First/Last) -+ // -+ // We do these in order. However as we transform the expanded range into the -+ // spelled one, we adjust First/Last so the validation remains simple. -+ -+ assert(SM.getSLocEntry(TargetFile).isFile()); -+ // In most cases, to select First and Last we must return their expansion -+ // range, i.e. the whole of any macros they are included in. -+ // -+ // When First and Last are part of the *same macro arg* of a macro written -+ // in TargetFile, we that slice of the arg, i.e. their spelling range. -+ // -+ // Unwrap such macro calls. If the target file has A(B(C)), the -+ // SourceLocation stack of a token inside C shows us the expansion of A first, -+ // then B, then any macros inside C's body, then C itself. -+ // (This is the reverse of the order the PP applies the expansions in). -+ while (First.isMacroID() && Last.isMacroID()) { -+ auto DecFirst = SM.getDecomposedLoc(First); -+ auto DecLast = SM.getDecomposedLoc(Last); -+ auto &ExpFirst = SM.getSLocEntry(DecFirst.first).getExpansion(); -+ auto &ExpLast = SM.getSLocEntry(DecLast.first).getExpansion(); -+ -+ if (!ExpFirst.isMacroArgExpansion() || !ExpLast.isMacroArgExpansion()) -+ break; -+ // Locations are in the same macro arg if they expand to the same place. -+ // (They may still have different FileIDs - an arg can have >1 chunks!) -+ if (ExpFirst.getExpansionLocStart() != ExpLast.getExpansionLocStart()) - break; -- // Do not continue into macro bodies. -- if (!ExpInfoFirst.isMacroArgExpansion() || -- !ExpInfoLast.isMacroArgExpansion()) -+ // Careful, given: -+ // #define HIDE ID(ID(a)) -+ // ID(ID(HIDE)) -+ // The token `a` is wrapped in 4 arg-expansions, we only want to unwrap 2. -+ // We distinguish them by whether the macro expands into the target file. -+ // Fortunately, the target file ones will always appear first. -+ auto &ExpMacro = -+ SM.getSLocEntry(SM.getFileID(ExpFirst.getExpansionLocStart())) -+ .getExpansion(); -+ if (ExpMacro.getExpansionLocStart().isMacroID()) - break; -- FirstLoc = SM.getImmediateSpellingLoc(FirstLoc); -- LastLoc = SM.getImmediateSpellingLoc(LastLoc); -- // Update the result afterwards, as we want the tokens that triggered the -- // expansion. -- Res = {FirstLoc, LastLoc}; -+ // Replace each endpoint with its spelling inside the macro arg. -+ // (This is getImmediateSpellingLoc without repeating lookups). -+ First = ExpFirst.getSpellingLoc().getLocWithOffset(DecFirst.second); -+ Last = ExpLast.getSpellingLoc().getLocWithOffset(DecLast.second); -+ -+ // Now: how do we adjust the previous/next bounds? Three cases: -+ // A) If they are also part of the same macro arg, we translate them too. -+ // This will ensure that we don't select any macros nested within the -+ // macro arg that cover extra tokens. Critical case: -+ // #define ID(X) X -+ // ID(prev target) // selecting 'target' succeeds -+ // #define LARGE ID(prev target) -+ // LARGE // selecting 'target' fails. -+ // B) They are not in the macro at all, then their expansion range is a -+ // sibling to it, and we can safely substitute that. -+ // #define PREV prev -+ // #define ID(X) X -+ // PREV ID(target) // selecting 'target' succeeds. -+ // #define LARGE PREV ID(target) -+ // LARGE // selecting 'target' fails. -+ // C) They are in a different arg of this macro, or the macro body. -+ // Now selecting the whole macro arg is fine, but the whole macro is not. -+ // Model this by setting using the edge of the macro call as the bound. -+ // #define ID2(X, Y) X Y -+ // ID2(prev, target) // selecting 'target' succeeds -+ // #define LARGE ID2(prev, target) -+ // LARGE // selecting 'target' fails -+ auto AdjustBound = [&](SourceLocation &Bound) { -+ if (Bound.isInvalid() || !Bound.isMacroID()) // Non-macro must be case B. -+ return; -+ auto DecBound = SM.getDecomposedLoc(Bound); -+ auto &ExpBound = SM.getSLocEntry(DecBound.first).getExpansion(); -+ if (ExpBound.isMacroArgExpansion() && -+ ExpBound.getExpansionLocStart() == ExpFirst.getExpansionLocStart()) { -+ // Case A: translate to (spelling) loc within the macro arg. -+ Bound = ExpBound.getSpellingLoc().getLocWithOffset(DecBound.second); -+ return; -+ } -+ while (Bound.isMacroID()) { -+ SourceRange Exp = SM.getImmediateExpansionRange(Bound).getAsRange(); -+ if (Exp.getBegin() == ExpMacro.getExpansionLocStart()) { -+ // Case B: bounds become the macro call itself. -+ Bound = (&Bound == &Prev) ? Exp.getBegin() : Exp.getEnd(); -+ return; -+ } -+ // Either case C, or expansion location will later find case B. -+ // We choose the upper bound for Prev and the lower one for Next: -+ // ID(prev) target ID(next) -+ // ^ ^ -+ // new-prev new-next -+ Bound = (&Bound == &Prev) ? Exp.getEnd() : Exp.getBegin(); -+ } -+ }; -+ AdjustBound(Prev); -+ AdjustBound(Next); - } -- // Normally mapping back to expansion location here only changes FileID, as -- // we've already found some tokens expanded from the same macro argument, and -- // they should map to a consecutive subset of spelled tokens. Unfortunately -- // SourceManager::isBeforeInTranslationUnit discriminates sourcelocations -- // based on their FileID in addition to offsets. So even though we are -- // referring to same tokens, SourceManager might tell us that one is before -- // the other if they've got different FileIDs. -- return SM.getExpansionRange(CharSourceRange(Res, true)).getAsRange(); -+ -+ // In all remaining cases we need the full containing macros. -+ // If this overlaps Prev or Next, then no range is possible. -+ SourceRange Candidate = -+ SM.getExpansionRange(SourceRange(First, Last)).getAsRange(); -+ auto DecFirst = SM.getDecomposedExpansionLoc(Candidate.getBegin()); -+ auto DecLast = SM.getDecomposedLoc(Candidate.getEnd()); -+ // Can end up in the wrong file due to bad input or token-pasting shenanigans. -+ if (Candidate.isInvalid() || DecFirst.first != TargetFile || DecLast.first != TargetFile) -+ return SourceRange(); -+ // Check bounds, which may still be inside macros. -+ if (Prev.isValid()) { -+ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Prev).getBegin()); -+ if (Dec.first != DecFirst.first || Dec.second >= DecFirst.second) -+ return SourceRange(); -+ } -+ if (Next.isValid()) { -+ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Next).getEnd()); -+ if (Dec.first != DecLast.first || Dec.second <= DecLast.second) -+ return SourceRange(); -+ } -+ // Now we know that Candidate is a file range that covers [First, Last] -+ // without encroaching on {Prev, Next}. Ship it! -+ return Candidate; - } - - } // namespace -@@ -363,51 +458,50 @@ TokenBuffer::spelledForExpanded(llvm::ArrayRef Expanded) const { - // of the range, bail out in that case. - if (Expanded.empty()) - return llvm::None; -- -- const syntax::Token *BeginSpelled; -- const Mapping *BeginMapping; -- std::tie(BeginSpelled, BeginMapping) = -- spelledForExpandedToken(&Expanded.front()); -- -- const syntax::Token *LastSpelled; -- const Mapping *LastMapping; -- std::tie(LastSpelled, LastMapping) = -- spelledForExpandedToken(&Expanded.back()); -- -- FileID FID = SourceMgr->getFileID(BeginSpelled->location()); -+ const syntax::Token *First = &Expanded.front(); -+ const syntax::Token *Last = &Expanded.back(); -+ const syntax::Token *FirstSpelled, *LastSpelled; -+ const TokenBuffer::Mapping *FirstMapping, *LastMapping; -+ std::tie(FirstSpelled, FirstMapping) = spelledForExpandedToken(First); -+ std::tie(LastSpelled, LastMapping) = spelledForExpandedToken(Last); -+ -+ FileID FID = SourceMgr->getFileID(FirstSpelled->location()); - // FIXME: Handle multi-file changes by trying to map onto a common root. - if (FID != SourceMgr->getFileID(LastSpelled->location())) - return llvm::None; - - const MarkedFile &File = Files.find(FID)->second; - -- // If both tokens are coming from a macro argument expansion, try and map to -- // smallest part of the macro argument. BeginMapping && LastMapping check is -- // only for performance, they are a prerequisite for Expanded.front() and -- // Expanded.back() being part of a macro arg expansion. -- if (BeginMapping && LastMapping && -- SourceMgr->isMacroArgExpansion(Expanded.front().location()) && -- SourceMgr->isMacroArgExpansion(Expanded.back().location())) { -- auto CommonRange = findCommonRangeForMacroArgs(Expanded.front(), -- Expanded.back(), *SourceMgr); -- // It might be the case that tokens are arguments of different macro calls, -- // in that case we should continue with the logic below instead of returning -- // an empty range. -- if (CommonRange.isValid()) -- return getTokensCovering(File.SpelledTokens, CommonRange, *SourceMgr); -+ // If the range is within one macro argument, the result may be only part of a -+ // Mapping. We must use the general (SourceManager-based) algorithm. -+ if (FirstMapping && FirstMapping == LastMapping && -+ SourceMgr->isMacroArgExpansion(First->location()) && -+ SourceMgr->isMacroArgExpansion(Last->location())) { -+ // We use excluded Prev/Next token for bounds checking. -+ SourceLocation Prev = (First == &ExpandedTokens.front()) -+ ? SourceLocation() -+ : (First - 1)->location(); -+ SourceLocation Next = (Last == &ExpandedTokens.back()) -+ ? SourceLocation() -+ : (Last + 1)->location(); -+ SourceRange Range = spelledForExpandedSlow( -+ First->location(), Last->location(), Prev, Next, FID, *SourceMgr); -+ if (Range.isInvalid()) -+ return llvm::None; -+ return getTokensCovering(File.SpelledTokens, Range, *SourceMgr); - } - -+ // Otherwise, use the fast version based on Mappings. - // Do not allow changes that doesn't cover full expansion. -- unsigned BeginExpanded = Expanded.begin() - ExpandedTokens.data(); -- unsigned EndExpanded = Expanded.end() - ExpandedTokens.data(); -- if (BeginMapping && BeginExpanded != BeginMapping->BeginExpanded) -+ unsigned FirstExpanded = Expanded.begin() - ExpandedTokens.data(); -+ unsigned LastExpanded = Expanded.end() - ExpandedTokens.data(); -+ if (FirstMapping && FirstExpanded != FirstMapping->BeginExpanded) - return llvm::None; -- if (LastMapping && LastMapping->EndExpanded != EndExpanded) -+ if (LastMapping && LastMapping->EndExpanded != LastExpanded) - return llvm::None; -- // All is good, return the result. - return llvm::makeArrayRef( -- BeginMapping ? File.SpelledTokens.data() + BeginMapping->BeginSpelled -- : BeginSpelled, -+ FirstMapping ? File.SpelledTokens.data() + FirstMapping->BeginSpelled -+ : FirstSpelled, - LastMapping ? File.SpelledTokens.data() + LastMapping->EndSpelled - : LastSpelled + 1); - } -diff --git a/src/llvm-project/clang/test/Analysis/template-param-objects.cpp b/src/llvm-project/clang/test/Analysis/template-param-objects.cpp -new file mode 100644 -index 000000000..dde95fa62 ---- /dev/null -+++ b/src/llvm-project/clang/test/Analysis/template-param-objects.cpp -@@ -0,0 +1,33 @@ -+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection \ -+// RUN: -analyzer-config eagerly-assume=false -std=c++20 -verify %s -+ -+template void clang_analyzer_dump(T); -+void clang_analyzer_eval(bool); -+ -+struct Box { -+ int value; -+}; -+bool operator ==(Box lhs, Box rhs) { -+ return lhs.value == rhs.value; -+} -+template void dumps() { -+ clang_analyzer_dump(V); // expected-warning {{lazyCompoundVal}} -+ clang_analyzer_dump(&V); // expected-warning {{Unknown}} -+ clang_analyzer_dump(V.value); // expected-warning {{Unknown}} FIXME: It should be '6 S32b'. -+ clang_analyzer_dump(&V.value); // expected-warning {{Unknown}} -+} -+template void dumps(); -+ -+// [temp.param].7.3.2: -+// "All such template parameters in the program of the same type with the -+// same value denote the same template parameter object." -+template void stable_addresses() { -+ clang_analyzer_eval(&A1 == &A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. -+ clang_analyzer_eval(&B1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. -+ clang_analyzer_eval(&A1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. -+ -+ clang_analyzer_eval(A1 == A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. -+ clang_analyzer_eval(B1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. -+ clang_analyzer_eval(A1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. -+} -+template void stable_addresses(); -diff --git a/src/llvm-project/clang/test/CodeGen/arm-vaarg.c b/src/llvm-project/clang/test/CodeGen/arm-vaarg.c -new file mode 100644 -index 000000000..4dab397a2 ---- /dev/null -+++ b/src/llvm-project/clang/test/CodeGen/arm-vaarg.c -@@ -0,0 +1,23 @@ -+// RUN: %clang -Xclang -no-opaque-pointers -mfloat-abi=soft -target arm-linux-gnu -emit-llvm -S -o - %s | FileCheck %s -+ -+struct Empty {}; -+ -+struct Empty emptyvar; -+ -+void take_args(int a, ...) { -+// CHECK: [[ALLOCA_VA_LIST:%[a-zA-Z0-9._]+]] = alloca %struct.__va_list, align 4 -+// CHECK: call void @llvm.va_start -+// CHECK-NEXT: [[AP_ADDR:%[a-zA-Z0-9._]+]] = bitcast %struct.__va_list* [[ALLOCA_VA_LIST]] to i8** -+// CHECK-NEXT: [[LOAD_AP:%[a-zA-Z0-9._]+]] = load i8*, i8** [[AP_ADDR]], align 4 -+// CHECK-NEXT: [[EMPTY_PTR:%[a-zA-Z0-9._]+]] = bitcast i8* [[LOAD_AP]] to %struct.Empty* -+ -+ // It's conceivable that EMPTY_PTR may not actually be a valid pointer -+ // (e.g. it's at the very bottom of the stack and the next page is -+ // invalid). This doesn't matter provided it's never loaded (there's no -+ // well-defined way to tell), but it becomes a problem if we do try to use it. -+// CHECK-NOT: load %struct.Empty, %struct.Empty* [[EMPTY_PTR]] -+ __builtin_va_list l; -+ __builtin_va_start(l, a); -+ emptyvar = __builtin_va_arg(l, struct Empty); -+ __builtin_va_end(l); -+} -diff --git a/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c -new file mode 100644 -index 000000000..29ca5f58e ---- /dev/null -+++ b/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c -@@ -0,0 +1,15 @@ -+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s -+ -+struct t { -+ int (__attribute__((btf_type_tag("rcu"))) *f)(); -+ int a; -+}; -+int foo(struct t *arg) { -+ return arg->a; -+} -+ -+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f" -+// CHECK-SAME: baseType: ![[L18:[0-9]+]] -+// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]]) -+// CHECK: ![[L21]] = !{![[L22:[0-9]+]]} -+// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"} -diff --git a/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c b/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c -new file mode 100644 -index 000000000..f39de0d73 ---- /dev/null -+++ b/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c -@@ -0,0 +1,30 @@ -+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s -+ -+enum { A = 1 }; -+int func1(int a) { -+ switch(a) { -+ case A: return 10; -+ default: break; -+ } -+ return 0; -+} -+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type -+// CHECK-SAME: elements: [[TEST1_ENUMS:![0-9]*]] -+// CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]} -+// CHECK: [[TEST1_E]] = !DIEnumerator(name: "A", value: 1) -+ -+// Test ImplicitCast of switch case enum value -+enum { B = 2 }; -+typedef unsigned long long __t1; -+typedef __t1 __t2; -+int func2(__t2 a) { -+ switch(a) { -+ case B: return 10; -+ default: break; -+ } -+ return 0; -+} -+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type -+// CHECK-SAME: elements: [[TEST2_ENUMS:![0-9]*]] -+// CHECK: [[TEST2_ENUMS]] = !{[[TEST2_E:![0-9]*]]} -+// CHECK: [[TEST2_E]] = !DIEnumerator(name: "B", value: 2) -diff --git a/src/llvm-project/clang/test/Sema/gnu-builtins.c b/src/llvm-project/clang/test/Sema/gnu-builtins.c -new file mode 100644 -index 000000000..c4da8b393 ---- /dev/null -+++ b/src/llvm-project/clang/test/Sema/gnu-builtins.c -@@ -0,0 +1,13 @@ -+// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu17 %s -+// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu2x %s -+// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c17 %s -+// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c2x %s -+ -+// std-no-diagnostics -+ -+// 'index' is a builtin library function, but only in GNU mode. So this should -+// give an error in GNU modes but be okay in non-GNU mode. -+// FIXME: the error is correct, but these notes are pretty awful. -+int index; // gnu-error {{redefinition of 'index' as different kind of symbol}} \ -+ gnu-note {{unguarded header; consider using #ifdef guards or #pragma once}} \ -+ gnu-note {{previous definition is here}} -diff --git a/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp b/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp -new file mode 100644 -index 000000000..5fd387cab ---- /dev/null -+++ b/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp -@@ -0,0 +1,24 @@ -+// RUN: %clang_cc1 -fsyntax-only %s --std=c++17 -verify -+// This is a reduction of GH57370 and GH58028, originally appearing -+// in libstdc++'s variant code. -+ -+struct V1 {}; -+struct V2 : V1 { -+ int &a; -+}; -+ -+template using void_t = void; -+ -+template struct X { T x; }; -+ -+template struct Variant { -+ Variant() = delete; // expected-note {{deleted here}} -+}; -+ -+template -+struct Variant{T1()})>> {}; -+ -+void f() { -+ Variant(); -+ Variant(); // expected-error {{call to deleted constructor}} -+} -diff --git a/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp b/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp -index 64bc61652..c434dfcb3 100644 ---- a/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp -+++ b/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp -@@ -18,7 +18,6 @@ - #include "clang/Driver/Driver.h" - #include "llvm/ADT/ArrayRef.h" - #include "llvm/MC/TargetRegistry.h" --#include "llvm/Support/Host.h" - #include "llvm/Support/TargetSelect.h" - #include "llvm/Support/VirtualFileSystem.h" - #include "llvm/Support/raw_ostream.h" -@@ -570,95 +569,4 @@ TEST(DxcModeTest, ValidatorVersionValidation) { - Diags.Clear(); - DiagConsumer->clear(); - } -- --TEST(ToolChainTest, Toolsets) { -- // Ignore this test on Windows hosts. -- llvm::Triple Host(llvm::sys::getProcessTriple()); -- if (Host.isOSWindows()) -- GTEST_SKIP(); -- -- IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); -- IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); -- -- // Check (newer) GCC toolset installation. -- { -- IntrusiveRefCntPtr InMemoryFileSystem( -- new llvm::vfs::InMemoryFileSystem); -- -- // These should be ignored. -- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- -- // File needed for GCC installation detection. -- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-12/root/usr/lib/gcc/" -- "x86_64-redhat-linux/11/crtbegin.o", -- 0, llvm::MemoryBuffer::getMemBuffer("\n")); -- -- DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); -- Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, -- "clang LLVM compiler", InMemoryFileSystem); -- std::unique_ptr C( -- TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); -- ASSERT_TRUE(C); -- std::string S; -- { -- llvm::raw_string_ostream OS(S); -- C->getDefaultToolChain().printVerboseInfo(OS); -- } -- EXPECT_EQ("Found candidate GCC installation: " -- "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" -- "Selected GCC installation: " -- "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" -- "Candidate multilib: .;@m64\n" -- "Selected multilib: .;@m64\n", -- S); -- } -- -- // And older devtoolset. -- { -- IntrusiveRefCntPtr InMemoryFileSystem( -- new llvm::vfs::InMemoryFileSystem); -- -- // These should be ignored. -- InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0, -- llvm::MemoryBuffer::getMemBuffer("\n")); -- -- // File needed for GCC installation detection. -- InMemoryFileSystem->addFile("/opt/rh/devtoolset-12/root/usr/lib/gcc/" -- "x86_64-redhat-linux/11/crtbegin.o", -- 0, llvm::MemoryBuffer::getMemBuffer("\n")); -- -- DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); -- Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, -- "clang LLVM compiler", InMemoryFileSystem); -- std::unique_ptr C( -- TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); -- ASSERT_TRUE(C); -- std::string S; -- { -- llvm::raw_string_ostream OS(S); -- C->getDefaultToolChain().printVerboseInfo(OS); -- } -- EXPECT_EQ("Found candidate GCC installation: " -- "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" -- "Selected GCC installation: " -- "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" -- "Candidate multilib: .;@m64\n" -- "Selected multilib: .;@m64\n", -- S); -- } --} -- - } // end anonymous namespace. -diff --git a/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp b/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp -index 77f719ce2..85fc837fb 100644 ---- a/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp -+++ b/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp -@@ -743,6 +743,62 @@ TEST_F(TokenBufferTest, SpelledByExpanded) { - ValueIs(SameRange(findSpelled("ID2 ( a4 , a5 a6 a7 )")))); - // Should fail, spans multiple invocations. - EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("a1 a2 a3 a4")), llvm::None); -+ -+ // https://github.com/clangd/clangd/issues/1289 -+ recordTokens(R"cpp( -+ #define FOO(X) foo(X) -+ #define INDIRECT FOO(y) -+ INDIRECT // expands to foo(y) -+ )cpp"); -+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("y")), llvm::None); -+ -+ recordTokens(R"cpp( -+ #define FOO(X) a X b -+ FOO(y) -+ )cpp"); -+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("y")), -+ ValueIs(SameRange(findSpelled("y")))); -+ -+ recordTokens(R"cpp( -+ #define ID(X) X -+ #define BAR ID(1) -+ BAR -+ )cpp"); -+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("1")), -+ ValueIs(SameRange(findSpelled(") BAR").drop_front()))); -+ -+ // Critical cases for mapping of Prev/Next in spelledForExpandedSlow. -+ recordTokens(R"cpp( -+ #define ID(X) X -+ ID(prev ID(good)) -+ #define LARGE ID(prev ID(bad)) -+ LARGE -+ )cpp"); -+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), -+ ValueIs(SameRange(findSpelled("good")))); -+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); -+ -+ recordTokens(R"cpp( -+ #define PREV prev -+ #define ID(X) X -+ PREV ID(good) -+ #define LARGE PREV ID(bad) -+ LARGE -+ )cpp"); -+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), -+ ValueIs(SameRange(findSpelled("good")))); -+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); -+ -+ recordTokens(R"cpp( -+ #define ID(X) X -+ #define ID2(X, Y) X Y -+ ID2(prev, ID(good)) -+ #define LARGE ID2(prev, bad) -+ LARGE -+ )cpp"); -+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), -+ ValueIs(SameRange(findSpelled("good")))); -+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); - } - - TEST_F(TokenBufferTest, ExpandedTokensForRange) { -diff --git a/src/llvm-project/cmake/Modules/FindLibEdit.cmake b/src/llvm-project/cmake/Modules/FindLibEdit.cmake -index 7e62d4d83..de8f5a2e7 100644 ---- a/src/llvm-project/cmake/Modules/FindLibEdit.cmake -+++ b/src/llvm-project/cmake/Modules/FindLibEdit.cmake -@@ -21,6 +21,7 @@ find_library(LibEdit_LIBRARIES NAMES edit HINTS ${PC_LIBEDIT_LIBRARY_DIRS}) - - include(CheckIncludeFile) - if(LibEdit_INCLUDE_DIRS AND EXISTS "${LibEdit_INCLUDE_DIRS}/histedit.h") -+ include(CMakePushCheckState) - cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_INCLUDES ${LibEdit_INCLUDE_DIRS}) - list(APPEND CMAKE_REQUIRED_LIBRARIES ${LibEdit_LIBRARIES}) -diff --git a/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake -index 2c9983c6a..640c7e712 100644 ---- a/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake -+++ b/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake -@@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs) - if(NOT TEST_COMPILE_ONLY) - message(STATUS "Finding valid architectures for ${os}...") - set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) -- file(WRITE ${SIMPLE_C} "#include \nint main() { printf(__FILE__); return 0; }\n") -+ file(WRITE ${SIMPLE_C} "#include \nint main(void) { printf(__FILE__); return 0; }\n") - - set(os_linker_flags) - foreach(flag ${DARWIN_${os}_LINK_FLAGS}) -diff --git a/src/llvm-project/compiler-rt/cmake/config-ix.cmake b/src/llvm-project/compiler-rt/cmake/config-ix.cmake -index cd45176cf..9077e8f9f 100644 ---- a/src/llvm-project/compiler-rt/cmake/config-ix.cmake -+++ b/src/llvm-project/compiler-rt/cmake/config-ix.cmake -@@ -209,7 +209,7 @@ set(COMPILER_RT_SUPPORTED_ARCH) - # runtime libraries supported by our current compilers cross-compiling - # abilities. - set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) --file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() { printf(\"hello, world\"); }\n") -+file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") - - # Detect whether the current target platform is 32-bit or 64-bit, and setup - # the correct commandline flags needed to attempt to target 32-bit and 64-bit. -diff --git a/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt b/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt -index ec668e294..df02682ae 100644 ---- a/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt -+++ b/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt -@@ -745,7 +745,7 @@ else () - SOURCE "#if !(__ARM_FP & 0x8) - #error No double-precision support! - #endif -- int main() { return 0; }") -+ int main(void) { return 0; }") - if(NOT COMPILER_RT_HAS_${arch}_VFP_DP) - list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_DP_SOURCES}) - endif() -diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h -index fc5aeccf2..08c6062ba 100644 ---- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h -+++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h -@@ -443,7 +443,7 @@ inline uptr RoundUpToPowerOfTwo(uptr size) { - return 1ULL << (up + 1); - } - --inline uptr RoundUpTo(uptr size, uptr boundary) { -+inline constexpr uptr RoundUpTo(uptr size, uptr boundary) { - RAW_CHECK(IsPowerOfTwo(boundary)); - return (size + boundary - 1) & ~(boundary - 1); - } -diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc -index 9af296b18..b29665a63 100644 ---- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc -+++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc -@@ -6703,7 +6703,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) { - COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value); - // Workaround a bug in glibc's "old" semaphore implementation by - // zero-initializing the sem_t contents. This has to be done here because -- // interceptors bind to the lowest symbols version by default, hitting the -+ // interceptors bind to the lowest version before glibc 2.36, hitting the - // buggy code path while the non-sanitized build of the same code works fine. - REAL(memset)(s, 0, sizeof(*s)); - int res = REAL(sem_init)(s, pshared, value); -diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h -index ddb96d2cc..4f1a8caac 100644 ---- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h -+++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h -@@ -61,7 +61,7 @@ class StackStore { - return frame_idx % kBlockSizeFrames; - } - -- static uptr IdToOffset(Id id) { -+ static constexpr uptr IdToOffset(Id id) { - CHECK_NE(id, 0); - return id - 1; // Avoid zero as id. - } -diff --git a/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp b/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp -index d623ccabb..234c5019f 100644 ---- a/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp -+++ b/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp -@@ -1,39 +1,36 @@ - // RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t - // This test depends on the glibc layout of struct sem_t and checks that we - // don't leave sem_t::private uninitialized. --// UNSUPPORTED: android, lsan-x86, ubsan, target-is-mips64, target-is-mips64el -+// UNSUPPORTED: android, lsan-x86, ubsan - #include - #include - #include - #include - #include - --// On powerpc64be semval_t must be 64 bits even with "old" versions of glibc. --#if __PPC64__ && __BIG_ENDIAN__ --typedef uint64_t semval_t; -- --// This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. --#elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ -- defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ -- defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) --typedef uint64_t semval_t; --#else -+// musl and glibc's __HAVE_64B_ATOMICS==0 ports (e.g. arm, i386) use 32-bit sem -+// values. 64-bit glibc ports defining sem_init@GLIBC_2.0 (mips64) use 32-bit as -+// well, if the sem_init interceptor picks the oldest versioned symbol -+// (glibc<2.36, see https://sourceware.org/PR14932). -+#if !defined(__GLIBC__) || defined(__ILP32__) || \ -+ !__GLIBC_PREREQ(2, 36) && defined(__mips64__) - typedef unsigned semval_t; -+#else -+typedef uint64_t semval_t; - #endif - --// glibc 2.21 has introduced some changes in the way the semaphore value is --// handled for 32-bit platforms, but since these changes are not ABI-breaking --// they are not versioned. On newer platforms such as ARM, there is only one --// version of the symbol, so it's enough to check the glibc version. However, --// for old platforms such as i386, glibc contains two or even three versions of --// the sem_init symbol, and the sanitizers always pick the oldest one. --// Therefore, it is not enough to rely on the __GLIBC_PREREQ macro - we should --// instead check the platform as well to make sure we only expect the new --// behavior on platforms where the older symbols do not exist. --#if defined(__arm__) && __GLIBC_PREREQ(2, 21) --#define GET_SEM_VALUE(V) ((V) >> 1) -+// glibc __HAVE_64B_ATOMICS==0 ports define a sem_init which shifts the value by -+// 1 (https://sourceware.org/PR12674 glibc 2.21). The version is picked if -+// either glibc>=2.36 or sem_init@GLIBC_2.0 is absent (arm and newer ports). -+// -+// The __GLIBC_PREREQ check is brittle in that it requires matched -+// __GLIBC_PREREQ values for build time and run time. -+#if defined(__GLIBC__) && defined(__ILP32__) && \ -+ (__GLIBC_PREREQ(2, 36) || (__GLIBC_PREREQ(2, 21) && !defined(__i386__) && \ -+ !defined(__mips__) && !defined(__powerpc__))) -+# define GET_SEM_VALUE(V) ((V) >> 1) - #else --#define GET_SEM_VALUE(V) (V) -+# define GET_SEM_VALUE(V) (V) - #endif - - void my_sem_init(bool priv, int value, semval_t *a, unsigned char *b) { -diff --git a/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm b/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm -new file mode 100644 -index 000000000..186fe22e6 ---- /dev/null -+++ b/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm -@@ -0,0 +1,89 @@ -+//===----------------------------------------------------------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+// std::function support for "blocks" when ARC is enabled -+ -+// UNSUPPORTED: c++03 -+ -+// This test requires the Blocks runtime, which is (only?) available on Darwin -+// out-of-the-box. -+// REQUIRES: has-fblocks && darwin -+ -+// ADDITIONAL_COMPILE_FLAGS: -fblocks -fobjc-arc -+ -+#include -+ -+#include -+#include -+#include -+ -+struct Foo { -+ Foo() = default; -+ Foo(std::size_t (^bl)()) : f(bl) {} -+ -+ std::function f; -+}; -+ -+Foo Factory(std::size_t (^bl)()) { -+ Foo result(bl); -+ return result; -+} -+ -+Foo Factory2() { -+ auto hello = std::string("Hello world"); -+ return Factory(^() { -+ return hello.size(); -+ }); -+} -+ -+Foo AssignmentFactory(std::size_t (^bl)()) { -+ Foo result; -+ result.f = bl; -+ return result; -+} -+ -+Foo AssignmentFactory2() { -+ auto hello = std::string("Hello world"); -+ return AssignmentFactory(^() { -+ return hello.size(); -+ }); -+} -+ -+int main(int, char **) { -+ // Case 1, works -+ { -+ auto hello = std::string("Hello world"); -+ auto f = AssignmentFactory(^() { -+ return hello.size(); -+ }); -+ assert(f.f() == 11); -+ } -+ -+ // Case 2, works -+ { -+ auto f = AssignmentFactory2(); -+ assert(f.f() == 11); -+ } -+ -+ // Case 3, works -+ { -+ auto hello = std::string("Hello world"); -+ auto f = Factory(^() { -+ return hello.size(); -+ }); -+ assert(f.f() == 11); -+ } -+ -+ // Case 4, used to crash under ARC -+ { -+ auto f = Factory2(); -+ assert(f.f() == 11); -+ } -+ -+ return 0; -+} -diff --git a/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp b/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp -new file mode 100644 -index 000000000..592d733de ---- /dev/null -+++ b/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp -@@ -0,0 +1,141 @@ -+//===----------------------------------------------------------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+// UNSUPPORTED: no-exceptions -+ -+// (bug report: https://llvm.org/PR58392) -+// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception -+ -+#include -+#include -+ -+#include "count_new.h" -+#include "test_iterators.h" -+ -+template -+struct Allocator { -+ using value_type = T; -+ using is_always_equal = std::false_type; -+ -+ template -+ Allocator(const Allocator&) {} -+ -+ Allocator(bool should_throw = true) { -+ if (should_throw) -+ throw 0; -+ } -+ -+ T* allocate(int n) { return std::allocator().allocate(n); } -+ void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } -+ -+ friend bool operator==(const Allocator&, const Allocator&) { return false; } -+}; -+ -+template -+struct Iterator { -+ using iterator_category = IterCat; -+ using difference_type = std::ptrdiff_t; -+ using value_type = bool; -+ using reference = bool&; -+ using pointer = bool*; -+ -+ int i_; -+ bool b_ = true; -+ Iterator(int i = 0) : i_(i) {} -+ bool& operator*() { -+ if (i_ == 1) -+ throw 1; -+ return b_; -+ } -+ -+ friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } -+ -+ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } -+ -+ Iterator& operator++() { -+ ++i_; -+ return *this; -+ } -+ -+ Iterator operator++(int) { -+ auto tmp = *this; -+ ++i_; -+ return tmp; -+ } -+}; -+ -+void check_new_delete_called() { -+ assert(globalMemCounter.new_called == globalMemCounter.delete_called); -+ assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); -+ assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); -+ assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); -+} -+ -+int main(int, char**) { -+ using AllocVec = std::vector >; -+ -+#if TEST_STD_VER >= 14 -+ try { // Throw in vector(size_type, const allocator_type&) from allocator -+ Allocator alloc(false); -+ AllocVec get_alloc(0, alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+#endif // TEST_STD_VER >= 14 -+ -+ try { // Throw in vector(InputIterator, InputIterator) from input iterator -+ std::vector vec((Iterator()), Iterator(2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator) from forward iterator -+ std::vector vec((Iterator()), Iterator(2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator) from allocator -+ int a[] = {1, 2}; -+ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator -+ std::allocator alloc; -+ std::vector vec(Iterator(), Iterator(2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator -+ std::allocator alloc; -+ std::vector vec(Iterator(), Iterator(2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator -+ bool a[] = {true, false}; -+ Allocator alloc(false); -+ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator -+ bool a[] = {true, false}; -+ Allocator alloc(false); -+ AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ return 0; -+} -diff --git a/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp b/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp -new file mode 100644 -index 000000000..26ad7b4fd ---- /dev/null -+++ b/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp -@@ -0,0 +1,229 @@ -+//===----------------------------------------------------------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+// UNSUPPORTED: no-exceptions -+ -+// (bug report: https://llvm.org/PR58392) -+// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception -+ -+#include -+#include -+ -+#include "count_new.h" -+#include "test_iterators.h" -+ -+template -+struct Allocator { -+ using value_type = T; -+ using is_always_equal = std::false_type; -+ -+ Allocator(bool should_throw = true) { -+ if (should_throw) -+ throw 0; -+ } -+ -+ T* allocate(int n) { return std::allocator().allocate(n); } -+ void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } -+ -+ friend bool operator==(const Allocator&, const Allocator&) { return false; } -+}; -+ -+struct ThrowingT { -+ int* throw_after_n_ = nullptr; -+ ThrowingT() { throw 0; } -+ -+ ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) { -+ if (throw_after_n == 0) -+ throw 0; -+ --throw_after_n; -+ } -+ -+ ThrowingT(const ThrowingT&) { -+ if (throw_after_n_ == nullptr || *throw_after_n_ == 0) -+ throw 1; -+ --*throw_after_n_; -+ } -+ -+ ThrowingT& operator=(const ThrowingT&) { -+ if (throw_after_n_ == nullptr || *throw_after_n_ == 0) -+ throw 1; -+ --*throw_after_n_; -+ return *this; -+ } -+}; -+ -+template -+struct Iterator { -+ using iterator_category = IterCat; -+ using difference_type = std::ptrdiff_t; -+ using value_type = int; -+ using reference = int&; -+ using pointer = int*; -+ -+ int i_; -+ Iterator(int i = 0) : i_(i) {} -+ int& operator*() { -+ if (i_ == 1) -+ throw 1; -+ return i_; -+ } -+ -+ friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } -+ -+ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } -+ -+ Iterator& operator++() { -+ ++i_; -+ return *this; -+ } -+ -+ Iterator operator++(int) { -+ auto tmp = *this; -+ ++i_; -+ return tmp; -+ } -+}; -+ -+void check_new_delete_called() { -+ assert(globalMemCounter.new_called == globalMemCounter.delete_called); -+ assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); -+ assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); -+ assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); -+} -+ -+int main(int, char**) { -+ using AllocVec = std::vector >; -+ try { // vector() -+ AllocVec vec; -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(size_type) from type -+ std::vector get_alloc(1); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+#if TEST_STD_VER >= 14 -+ try { // Throw in vector(size_type, value_type) from type -+ int throw_after = 1; -+ ThrowingT v(throw_after); -+ std::vector get_alloc(1, v); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(size_type, const allocator_type&) from allocator -+ Allocator alloc(false); -+ AllocVec get_alloc(0, alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(size_type, const allocator_type&) from the type -+ std::vector vec(1, std::allocator()); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+#endif // TEST_STD_VER >= 14 -+ -+ try { // Throw in vector(InputIterator, InputIterator) from input iterator -+ std::vector vec((Iterator()), Iterator(2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator) from forward iterator -+ std::vector vec((Iterator()), Iterator(2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator) from allocator -+ int a[] = {1, 2}; -+ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator -+ std::allocator alloc; -+ std::vector vec(Iterator(), Iterator(2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator -+ std::allocator alloc; -+ std::vector vec(Iterator(), Iterator(2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator -+ int a[] = {1, 2}; -+ Allocator alloc(false); -+ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator -+ int a[] = {1, 2}; -+ Allocator alloc(false); -+ AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(const vector&) from type -+ std::vector vec; -+ int throw_after = 0; -+ vec.emplace_back(throw_after); -+ auto vec2 = vec; -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(const vector&, const allocator_type&) from type -+ std::vector vec; -+ int throw_after = 1; -+ vec.emplace_back(throw_after); -+ std::vector vec2(vec, std::allocator()); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(vector&&, const allocator_type&) from type -+ std::vector > vec(Allocator(false)); -+ int throw_after = 1; -+ vec.emplace_back(throw_after); -+ std::vector > vec2(std::move(vec), Allocator(false)); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+#if TEST_STD_VER >= 11 -+ try { // Throw in vector(initializer_list) from type -+ int throw_after = 1; -+ std::vector vec({ThrowingT(throw_after)}); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+ -+ try { // Throw in vector(initializer_list, const allocator_type&) constructor from type -+ int throw_after = 1; -+ std::vector vec({ThrowingT(throw_after)}, std::allocator()); -+ } catch (int) { -+ } -+ check_new_delete_called(); -+#endif // TEST_STD_VER >= 11 -+ -+ return 0; -+} -diff --git a/src/llvm-project/libunwind/CMakeLists.txt b/src/llvm-project/libunwind/CMakeLists.txt -index acf3d6dd4..5a06805f0 100644 ---- a/src/llvm-project/libunwind/CMakeLists.txt -+++ b/src/llvm-project/libunwind/CMakeLists.txt -@@ -264,7 +264,7 @@ if (LIBUNWIND_ENABLE_ASSERTIONS) - - # On Release builds cmake automatically defines NDEBUG, so we - # explicitly undefine it: -- if ((NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") AND (NOT RUST_SGX)) -+ if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") - add_compile_flags(-UNDEBUG) - endif() - else() -diff --git a/src/llvm-project/libunwind/README_RUST_SGX.md b/src/llvm-project/libunwind/README_RUST_SGX.md -deleted file mode 100644 -index c5d6eb477..000000000 ---- a/src/llvm-project/libunwind/README_RUST_SGX.md -+++ /dev/null -@@ -1,22 +0,0 @@ --# Libunwind customizations for linking with x86_64-fortanix-unknown-sgx Rust target. -- --## Description --### Initial Fork --Initial Fork has been made from 5.0 release of llvm (commit: 6a075b6de4) --### Detailed Description --#### Header files that we do not include for this target --1. pthread.h --#### Library that we do not link to for this target. --1. pthread (Locks used by libunwind is provided by rust stdlib for this target) -- --## Building unwind for rust-sgx target --### Generate Make files: --* `cd where you want to build libunwind` --* `mkdir build` --* `cd build` --* `cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" -DLLVM_ENABLE_WARNINGS=1 -DLIBUNWIND_ENABLE_PEDANTIC=0 -DLLVM_PATH= ` --* `"DEBUG"` could be used instead of `"RELEASE"` to enable debug logs of libunwind. -- --### Build: --* `make unwind_static` --* `build/lib/` will have the built library. -diff --git a/src/llvm-project/libunwind/cmake/config-ix.cmake b/src/llvm-project/libunwind/cmake/config-ix.cmake -index c9b65b3ce..1b027cf37 100644 ---- a/src/llvm-project/libunwind/cmake/config-ix.cmake -+++ b/src/llvm-project/libunwind/cmake/config-ix.cmake -@@ -85,7 +85,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas") - check_c_source_compiles(" - #pragma comment(lib, \"c\") --int main() { return 0; } -+int main(void) { return 0; } - " C_SUPPORTS_COMMENT_LIB_PRAGMA) - cmake_pop_check_state() - endif() -diff --git a/src/llvm-project/libunwind/docs/BuildingLibunwind.rst b/src/llvm-project/libunwind/docs/BuildingLibunwind.rst -index abd432c93..79166b476 100644 ---- a/src/llvm-project/libunwind/docs/BuildingLibunwind.rst -+++ b/src/llvm-project/libunwind/docs/BuildingLibunwind.rst -@@ -148,8 +148,3 @@ libunwind specific options - - Path where built libunwind libraries should be installed. If a relative path, - relative to ``CMAKE_INSTALL_PREFIX``. -- --.. option:: LIBUNWIND_ENABLE_RUST_SGX:BOOL -- -- **Default**: ``OFF`` -- -diff --git a/src/llvm-project/libunwind/src/AddressSpace.hpp b/src/llvm-project/libunwind/src/AddressSpace.hpp -index e9a1f3f7f..36c9f5a9e 100644 ---- a/src/llvm-project/libunwind/src/AddressSpace.hpp -+++ b/src/llvm-project/libunwind/src/AddressSpace.hpp -@@ -90,7 +90,6 @@ char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, - // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; - // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - --#if !defined(RUST_SGX) - extern char __eh_frame_start; - extern char __eh_frame_end; - -@@ -99,15 +98,6 @@ extern char __eh_frame_hdr_start; - extern char __eh_frame_hdr_end; - #endif - --#elif defined(RUST_SGX) --extern "C" char IMAGE_BASE; --extern "C" uint64_t EH_FRM_HDR_OFFSET; --extern "C" uint64_t EH_FRM_HDR_LEN; --extern "C" uint64_t EH_FRM_OFFSET; --extern "C" uint64_t EH_FRM_LEN; --#endif -- -- - #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) - - // When statically linked on bare-metal, the symbols for the EH table are looked -@@ -515,10 +505,6 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, - #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - - --#if defined(RUST_SGX) --extern "C" char IMAGE_BASE; --#endif -- - inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - UnwindInfoSections &info) { - #ifdef __APPLE__ -@@ -536,8 +522,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) - info.dso_base = 0; - // Bare metal is statically linked, so no need to ask the dynamic loader -- --#if !defined(RUST_SGX) - info.dwarf_section_length = (size_t)(&__eh_frame_end - &__eh_frame_start); - info.dwarf_section = (uintptr_t)(&__eh_frame_start); - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", -@@ -548,17 +532,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", - (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); - #endif -- --#elif defined(RUST_SGX) -- info.dwarf_section = (uintptr_t)EH_FRM_OFFSET + (uintptr_t)(&IMAGE_BASE); -- info.dwarf_section_length = (uintptr_t)EH_FRM_LEN; --#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) -- info.dwarf_index_section = (uintptr_t)EH_FRM_HDR_OFFSET + (uintptr_t)(&IMAGE_BASE); -- info.dwarf_index_section_length = (uintptr_t)EH_FRM_HDR_LEN; --#endif -- --#endif -- - if (info.dwarf_section_length) - return true; - #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) -diff --git a/src/llvm-project/libunwind/src/CMakeLists.txt b/src/llvm-project/libunwind/src/CMakeLists.txt -index 76d4094dc..61df2737b 100644 ---- a/src/llvm-project/libunwind/src/CMakeLists.txt -+++ b/src/llvm-project/libunwind/src/CMakeLists.txt -@@ -1,9 +1,5 @@ - # Get sources - --enable_language(C CXX ASM) -- --set(CMAKE_POSITION_INDEPENDENT_CODE ON) -- - set(LIBUNWIND_CXX_SOURCES - libunwind.cpp - Unwind-EHABI.cpp -@@ -26,6 +22,9 @@ set(LIBUNWIND_C_SOURCES - UnwindLevel1-gcc-ext.c - Unwind-sjlj.c - ) -+set_source_files_properties(${LIBUNWIND_C_SOURCES} -+ PROPERTIES -+ COMPILE_FLAGS "-std=c99") - - set(LIBUNWIND_ASM_SOURCES - UnwindRegistersRestore.S -@@ -74,44 +73,6 @@ if (MSVC_IDE) - source_group("Header Files" FILES ${LIBUNWIND_HEADERS}) - endif() - --if (RUST_SGX) -- # Compile Flags -- add_definitions(-DRUST_SGX) -- add_definitions(-D__NO_STRING_INLINES) -- add_definitions(-D__NO_MATH_INLINES) -- add_definitions(-D_LIBUNWIND_IS_BAREMETAL) -- # Can't use add_definitions because CMake will reorder these arguments -- list(APPEND LIBUNWIND_COMPILE_FLAGS -U_FORTIFY_SOURCE) -- list(APPEND LIBUNWIND_COMPILE_FLAGS -D_FORTIFY_SOURCE=0) -- -- list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-stack-protector) -- list(APPEND LIBUNWIND_COMPILE_FLAGS -ffreestanding) -- list(APPEND LIBUNWIND_COMPILE_FLAGS -fexceptions) -- # Avoid too new relocation types being emitted, which might prevent linking -- # on older platforms. -- # -- # See https://github.com/rust-lang/rust/issues/34978 -- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") -- list(APPEND LIBUNWIND_COMPILE_FLAGS -Wa,-mrelax-relocations=no) -- else() -- list(APPEND LIBUNWIND_COMPILE_FLAGS) -- endif() -- -- # Sources -- list(APPEND LIBUNWIND_HEADERS UnwindRustSgx.h) -- list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgx.c) --endif() -- -- --set_source_files_properties(${LIBUNWIND_C_SOURCES} -- PROPERTIES -- COMPILE_FLAGS "-std=c99") -- --# See add_asm_sources() in compiler-rt for explanation of this workaround. --if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR (MINGW AND CMAKE_VERSION VERSION_LESS 3.17)) -- set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C) --endif() -- - set(LIBUNWIND_SOURCES - ${LIBUNWIND_CXX_SOURCES} - ${LIBUNWIND_C_SOURCES} -@@ -126,7 +87,7 @@ else() - add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc) - endif() - add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl) --if (LIBUNWIND_ENABLE_THREADS AND (NOT RUST_SGX)) -+if (LIBUNWIND_ENABLE_THREADS) - add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread) - add_compile_flags_if(LIBUNWIND_WEAK_PTHREAD_LIB -DLIBUNWIND_USE_WEAK_PTHREAD=1) - endif() -diff --git a/src/llvm-project/libunwind/src/RWMutex.hpp b/src/llvm-project/libunwind/src/RWMutex.hpp -index 65bd849aa..344d35641 100644 ---- a/src/llvm-project/libunwind/src/RWMutex.hpp -+++ b/src/llvm-project/libunwind/src/RWMutex.hpp -@@ -15,7 +15,7 @@ - - #if defined(_WIN32) - #include --#elif !defined(_LIBUNWIND_HAS_NO_THREADS) && !defined(RUST_SGX) -+#elif !defined(_LIBUNWIND_HAS_NO_THREADS) - #include - #if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB) - #pragma comment(lib, "pthread") -diff --git a/src/llvm-project/libunwind/src/UnwindRustSgx.c b/src/llvm-project/libunwind/src/UnwindRustSgx.c -deleted file mode 100644 -index 9be7c1b54..000000000 ---- a/src/llvm-project/libunwind/src/UnwindRustSgx.c -+++ /dev/null -@@ -1,125 +0,0 @@ --//===--------------------- UnwindRustSgx.c ----------------------------------===// --// --//// The LLVM Compiler Infrastructure --//// --//// This file is dual licensed under the MIT and the University of Illinois Open --//// Source Licenses. See LICENSE.TXT for details. --//// --//// --////===----------------------------------------------------------------------===// -- --#define _GNU_SOURCE --#include -- --#include --#include --#include --#include --#include "UnwindRustSgx.h" -- --#define max_log 256 -- --__attribute__((weak)) struct _IO_FILE *stderr = (struct _IO_FILE *)-1; -- --static int vwrite_err(const char *format, va_list ap) --{ -- int len = 0; --#ifndef NDEBUG -- char s[max_log]; -- s[0]='\0'; -- len = vsnprintf(s, max_log, format, ap); -- __rust_print_err((uint8_t *)s, len); --#endif -- return len; --} -- --static int write_err(const char *format, ...) --{ -- int ret; -- va_list args; -- va_start(args, format); -- ret = vwrite_err(format, args); -- va_end(args); -- -- -- return ret; --} -- --__attribute__((weak)) int fprintf (FILE *__restrict __stream, -- const char *__restrict __format, ...) --{ -- -- int ret; -- if (__stream != stderr) { -- write_err("Rust SGX Unwind supports only writing to stderr\n"); -- return -1; -- } else { -- va_list args; -- ret = 0; -- va_start(args, __format); -- ret += vwrite_err(__format, args); -- va_end(args); -- } -- -- return ret; --} -- --__attribute__((weak)) int fflush (FILE *__stream) --{ -- // We do not need to do anything here. -- return 0; --} -- --__attribute__((weak)) void __assert_fail(const char * assertion, -- const char * file, -- unsigned int line, -- const char * function) --{ -- write_err("%s:%d %s %s\n", file, line, function, assertion); -- abort(); --} -- --// We do not report stack over flow detected. --// Calling write_err uses more stack due to the way we have implemented it. --// With possible enabling of stack probes, we should not --// get into __stack_chk_fail() at all. --__attribute__((weak)) void __stack_chk_fail() { -- abort(); --} -- --/* -- * Below are defined for all executibles compiled for -- * x86_64-fortanix-unknown-sgx rust target. -- * Ref: rust/src/libstd/sys/sgx/abi/entry.S -- */ -- --struct libwu_rs_alloc_meta { -- size_t alloc_size; -- // Should we put a signatre guard before ptr for oob access? -- unsigned char ptr[0]; --}; -- --#define META_FROM_PTR(__PTR) (struct libwu_rs_alloc_meta *) \ -- ((unsigned char *)__PTR - offsetof(struct libwu_rs_alloc_meta, ptr)) -- --void *libuw_malloc(size_t size) --{ -- struct libwu_rs_alloc_meta *meta; -- size_t alloc_size = size + sizeof(struct libwu_rs_alloc_meta); -- meta = (void *)__rust_c_alloc(alloc_size, sizeof(size_t)); -- if (!meta) { -- return NULL; -- } -- meta->alloc_size = alloc_size; -- return (void *)meta->ptr; --} -- --void libuw_free(void *p) --{ -- struct libwu_rs_alloc_meta *meta; -- if (!p) { -- return; -- } -- meta = META_FROM_PTR(p); -- __rust_c_dealloc((unsigned char *)meta, meta->alloc_size, sizeof(size_t)); --} -diff --git a/src/llvm-project/libunwind/src/UnwindRustSgx.h b/src/llvm-project/libunwind/src/UnwindRustSgx.h -deleted file mode 100644 -index 3c54b1676..000000000 ---- a/src/llvm-project/libunwind/src/UnwindRustSgx.h -+++ /dev/null -@@ -1,94 +0,0 @@ --//===--------------------- UnwindRustSgx.h ----------------------------------===// --// --//// The LLVM Compiler Infrastructure --//// --//// This file is dual licensed under the MIT and the University of Illinois Open --//// Source Licenses. See LICENSE.TXT for details. --//// --//// --////===----------------------------------------------------------------------===// -- --#if !defined(UNWIND_RUST_SGX_H) --#define UNWIND_RUST_SGX_H -- --#ifdef RUST_SGX -- --#undef _GNU_SOURCE --#define _GNU_SOURCE --#include --#include --#include --#include -- --// We have to use RWLock from rust repo, it is defined in: --// src/libstd/sys/sgx/rwlock.rs. --// rwlock.rs has compile time check to ensure sizeof(RWLock) = 144. --typedef struct { -- unsigned char opaque[144]; --} RWLock; -- --// The below is obtained by printing initialized bytes --// for RWLock in rust repo: src/libstd/sys/sgx/rwlock.rs. --#define RWLOCK_INIT { { \ -- /* 0x00 */ 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x60 */ 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- /* 0x80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ -- } } -- --// These are the functions exposed by SGX-Rust. --// The rust changes are available at: --#ifdef __cplusplus --extern "C" { --#endif -- int __rust_rwlock_rdlock(RWLock *rwlock); -- int __rust_rwlock_wrlock(RWLock *rwlock); -- int __rust_rwlock_unlock(RWLock *rwlock); -- unsigned char *__rust_c_alloc(size_t, size_t); -- void __rust_c_dealloc(unsigned char *, size_t, size_t); -- __attribute__((noreturn)) void __rust_abort(void); -- unsigned char *__rust_encl_address(size_t); -- --#ifndef NDEBUG -- void __rust_print_err(uint8_t *m, int s); --#endif -- --#ifdef __cplusplus --} --#endif -- --#define abort __rust_abort -- --#undef pthread_rwlock_t --#undef pthread_rwlock_rdlock --#undef pthread_rwlock_wrlock --#undef pthread_rwlock_unlock --#undef PTHREAD_RWLOCK_INITIALIZER -- --#define pthread_rwlock_t RWLock --#define pthread_rwlock_rdlock __rust_rwlock_rdlock --#define pthread_rwlock_wrlock __rust_rwlock_wrlock --#define pthread_rwlock_unlock __rust_rwlock_unlock --#define PTHREAD_RWLOCK_INITIALIZER RWLOCK_INIT -- --#define malloc libuw_malloc --#define free libuw_free -- --#ifdef __cplusplus --extern "C" { --#endif -- --void *libuw_malloc(size_t size); --void libuw_free(void *p); -- --#ifdef __cplusplus --} --#endif -- --#endif --#endif -diff --git a/src/llvm-project/libunwind/src/config.h b/src/llvm-project/libunwind/src/config.h -index 3f997ec3c..cc41b817a 100644 ---- a/src/llvm-project/libunwind/src/config.h -+++ b/src/llvm-project/libunwind/src/config.h -@@ -20,10 +20,6 @@ - - #include <__libunwind_config.h> - --#ifdef RUST_SGX --#include "UnwindRustSgx.h" --#endif -- - // Platform specific configuration defines. - #ifdef __APPLE__ - #if defined(FOR_DYLD) -diff --git a/src/llvm-project/lld/CMakeLists.txt b/src/llvm-project/lld/CMakeLists.txt -index 02b90ece9..dcc649629 100644 ---- a/src/llvm-project/lld/CMakeLists.txt -+++ b/src/llvm-project/lld/CMakeLists.txt -@@ -246,19 +246,6 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) - ) - endif() - --if (MSVC) -- FOREACH(flag -- CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO -- CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT -- CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO -- CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT) -- if (MSVC) -- STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}") -- SET("${flag}" "${${flag}}") -- endif (MSVC) -- ENDFOREACH() --endif() -- - add_subdirectory(Common) - add_subdirectory(tools/lld) - -diff --git a/src/llvm-project/lld/COFF/CMakeLists.txt b/src/llvm-project/lld/COFF/CMakeLists.txt -index d289bd591..55aec2685 100644 ---- a/src/llvm-project/lld/COFF/CMakeLists.txt -+++ b/src/llvm-project/lld/COFF/CMakeLists.txt -@@ -44,6 +44,7 @@ add_lld_library(lldCOFF - LINK_LIBS - lldCommon - ${LLVM_PTHREAD_LIB} -+ ${LLVM_ATOMIC_LIB} - - DEPENDS - COFFOptionsTableGen -diff --git a/src/llvm-project/lld/Common/CMakeLists.txt b/src/llvm-project/lld/Common/CMakeLists.txt -index 1ae7da1f5..9c23ed395 100644 ---- a/src/llvm-project/lld/Common/CMakeLists.txt -+++ b/src/llvm-project/lld/Common/CMakeLists.txt -@@ -1,9 +1,3 @@ --set(LLD_SYSTEM_LIBS ${LLVM_PTHREAD_LIB}) -- --if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) -- list(APPEND LLD_SYSTEM_LIBS atomic) --endif() -- - find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc) - find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc) - -@@ -54,7 +48,8 @@ add_lld_library(lldCommon - Target - - LINK_LIBS -- ${LLD_SYSTEM_LIBS} -+ ${LLVM_PTHREAD_LIB} -+ ${LLVM_ATOMIC_LIB} - - DEPENDS - intrinsics_gen -diff --git a/src/llvm-project/lld/ELF/Arch/RISCV.cpp b/src/llvm-project/lld/ELF/Arch/RISCV.cpp -index 34f8f1ae0..56a516f9c 100644 ---- a/src/llvm-project/lld/ELF/Arch/RISCV.cpp -+++ b/src/llvm-project/lld/ELF/Arch/RISCV.cpp -@@ -618,9 +618,9 @@ static bool relax(InputSection &sec) { - valueDelta[sa[0].d] = delta; - delta = aux.relocDeltas[it.index()]; - } -- for (const SymbolAnchor &saElem : sa) -- if (!saElem.end) -- valueDelta[saElem.d] = delta; -+ for (const SymbolAnchor &sa : sa) -+ if (!sa.end) -+ valueDelta[sa.d] = delta; - sa = makeArrayRef(aux.anchors); - delta = 0; - -diff --git a/src/llvm-project/lld/ELF/Driver.cpp b/src/llvm-project/lld/ELF/Driver.cpp -index 296fb4220..58d863776 100644 ---- a/src/llvm-project/lld/ELF/Driver.cpp -+++ b/src/llvm-project/lld/ELF/Driver.cpp -@@ -1330,12 +1330,15 @@ static void readConfigs(opt::InputArgList &args) { - parseClangOption(std::string("-") + arg->getValue(), arg->getSpelling()); - - // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or -- // relative path. Just ignore. If not ended with "lto-wrapper", consider it an -+ // relative path. Just ignore. If not ended with "lto-wrapper" (or -+ // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an - // unsupported LLVMgold.so option and error. -- for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) -- if (!StringRef(arg->getValue()).endswith("lto-wrapper")) -+ for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) { -+ StringRef v(arg->getValue()); -+ if (!v.endswith("lto-wrapper") && !v.endswith("lto-wrapper.exe")) - error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() + - "'"); -+ } - - config->passPlugins = args::getStrings(args, OPT_load_pass_plugins); - -diff --git a/src/llvm-project/lld/ELF/InputFiles.cpp b/src/llvm-project/lld/ELF/InputFiles.cpp -index d8bf9ebf7..473809b05 100644 ---- a/src/llvm-project/lld/ELF/InputFiles.cpp -+++ b/src/llvm-project/lld/ELF/InputFiles.cpp -@@ -185,14 +185,14 @@ template static void doParseFile(InputFile *file) { - - // .so file - if (auto *f = dyn_cast(file)) { -- f->template parse(); -+ f->parse(); - return; - } - - // LLVM bitcode file - if (auto *f = dyn_cast(file)) { - ctx->bitcodeFiles.push_back(f); -- f->template parse(); -+ f->parse(); - return; - } - -@@ -1157,7 +1157,7 @@ template void ObjFile::postParse() { - continue; - } - -- if (binding == STB_WEAK) -+ if (sym.binding == STB_WEAK || binding == STB_WEAK) - continue; - std::lock_guard lock(mu); - ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); -diff --git a/src/llvm-project/lld/ELF/InputSection.cpp b/src/llvm-project/lld/ELF/InputSection.cpp -index b71fef583..8fe36eca6 100644 ---- a/src/llvm-project/lld/ELF/InputSection.cpp -+++ b/src/llvm-project/lld/ELF/InputSection.cpp -@@ -130,7 +130,7 @@ template RelsOrRelas InputSectionBase::relsOrRelas() const { - return {}; - RelsOrRelas ret; - typename ELFT::Shdr shdr = -- cast(file)->template getELFShdrs()[relSecIdx]; -+ cast(file)->getELFShdrs()[relSecIdx]; - if (shdr.sh_type == SHT_REL) { - ret.rels = makeArrayRef(reinterpret_cast( - file->mb.getBufferStart() + shdr.sh_offset), -@@ -413,7 +413,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { - // individual "gp" values used by each input object file. - // As a workaround we add the "gp" value to the relocation - // addend and save it back to the file. -- addend += sec->template getFile()->mipsGp0; -+ addend += sec->getFile()->mipsGp0; - } - - if (RelTy::IsRela) -@@ -963,9 +963,9 @@ void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { - // locations with tombstone values. - const RelsOrRelas rels = sec->template relsOrRelas(); - if (rels.areRelocsRel()) -- sec->template relocateNonAlloc(buf, rels.rels); -+ sec->relocateNonAlloc(buf, rels.rels); - else -- sec->template relocateNonAlloc(buf, rels.relas); -+ sec->relocateNonAlloc(buf, rels.relas); - } - - void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { -@@ -1172,8 +1172,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf, - // conservative. - if (Defined *d = dyn_cast(rel.sym)) - if (InputSection *isec = cast_or_null(d->section)) -- if (!isec || !isec->template getFile() || -- isec->template getFile()->splitStack) -+ if (!isec || !isec->getFile() || isec->getFile()->splitStack) - continue; - - if (enclosingPrologueAttempted(rel.offset, prologues)) -diff --git a/src/llvm-project/lld/ELF/SyntheticSections.cpp b/src/llvm-project/lld/ELF/SyntheticSections.cpp -index 9a21fdec6..b359c2e7b 100644 ---- a/src/llvm-project/lld/ELF/SyntheticSections.cpp -+++ b/src/llvm-project/lld/ELF/SyntheticSections.cpp -@@ -197,7 +197,7 @@ std::unique_ptr> MipsOptionsSection::create() { - auto *opt = reinterpret_cast(d.data()); - if (opt->kind == ODK_REGINFO) { - reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; -- sec->template getFile()->mipsGp0 = opt->getRegInfo().ri_gp_value; -+ sec->getFile()->mipsGp0 = opt->getRegInfo().ri_gp_value; - break; - } - -@@ -249,7 +249,7 @@ std::unique_ptr> MipsReginfoSection::create() { - - auto *r = reinterpret_cast(sec->rawData.data()); - reginfo.ri_gprmask |= r->ri_gprmask; -- sec->template getFile()->mipsGp0 = r->ri_gp_value; -+ sec->getFile()->mipsGp0 = r->ri_gp_value; - }; - - return std::make_unique>(reginfo); -@@ -1662,8 +1662,8 @@ void RelocationBaseSection::partitionRels() { - if (!combreloc) - return; - const RelType relativeRel = target->relativeRel; -- numRelativeRelocs = llvm::partition( -- relocs, [=](const DynamicReloc &r) { return r.type == relativeRel; }) - -+ numRelativeRelocs = -+ llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }) - - relocs.begin(); - } - -@@ -3360,7 +3360,7 @@ template void elf::splitSections() { - if (auto *s = dyn_cast(sec)) - s->splitIntoPieces(); - else if (auto *eh = dyn_cast(sec)) -- eh->template split(); -+ eh->split(); - } - }); - } -diff --git a/src/llvm-project/lld/MachO/UnwindInfoSection.cpp b/src/llvm-project/lld/MachO/UnwindInfoSection.cpp -index ca6cbdfbb..8f267251b 100644 ---- a/src/llvm-project/lld/MachO/UnwindInfoSection.cpp -+++ b/src/llvm-project/lld/MachO/UnwindInfoSection.cpp -@@ -158,7 +158,7 @@ class UnwindInfoSectionImpl final : public UnwindInfoSection { - public: - UnwindInfoSectionImpl() : cuOffsets(target->wordSize) {} - uint64_t getSize() const override { return unwindInfoSize; } -- void prepareRelocations() override; -+ void prepare() override; - void finalize() override; - void writeTo(uint8_t *buf) const override; - -@@ -166,6 +166,7 @@ private: - void prepareRelocations(ConcatInputSection *); - void relocateCompactUnwind(std::vector &); - void encodePersonalities(); -+ Symbol *canonicalizePersonality(Symbol *); - - uint64_t unwindInfoSize = 0; - std::vector symbolsVec; -@@ -218,14 +219,24 @@ void UnwindInfoSection::addSymbol(const Defined *d) { - } - } - --void UnwindInfoSectionImpl::prepareRelocations() { -+void UnwindInfoSectionImpl::prepare() { - // This iteration needs to be deterministic, since prepareRelocations may add - // entries to the GOT. Hence the use of a MapVector for - // UnwindInfoSection::symbols. - for (const Defined *d : make_second_range(symbols)) -- if (d->unwindEntry && -- d->unwindEntry->getName() == section_names::compactUnwind) -- prepareRelocations(d->unwindEntry); -+ if (d->unwindEntry) { -+ if (d->unwindEntry->getName() == section_names::compactUnwind) { -+ prepareRelocations(d->unwindEntry); -+ } else { -+ // We don't have to add entries to the GOT here because FDEs have -+ // explicit GOT relocations, so Writer::scanRelocations() will add those -+ // GOT entries. However, we still need to canonicalize the personality -+ // pointers (like prepareRelocations() does for CU entries) in order -+ // to avoid overflowing the 3-personality limit. -+ FDE &fde = cast(d->getFile())->fdes[d->unwindEntry]; -+ fde.personality = canonicalizePersonality(fde.personality); -+ } -+ } - } - - // Compact unwind relocations have different semantics, so we handle them in a -@@ -279,6 +290,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { - continue; - } - -+ // Similar to canonicalizePersonality(), but we also register a GOT entry. - if (auto *defined = dyn_cast(s)) { - // Check if we have created a synthetic symbol at the same address. - Symbol *&personality = -@@ -291,6 +303,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { - } - continue; - } -+ - assert(isa(s)); - in.got->addEntry(s); - continue; -@@ -320,6 +333,18 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { - } - } - -+Symbol *UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) { -+ if (auto *defined = dyn_cast_or_null(personality)) { -+ // Check if we have created a synthetic symbol at the same address. -+ Symbol *&synth = personalityTable[{defined->isec, defined->value}]; -+ if (synth == nullptr) -+ synth = defined; -+ else if (synth != defined) -+ return synth; -+ } -+ return personality; -+} -+ - // We need to apply the relocations to the pre-link compact unwind section - // before converting it to post-link form. There should only be absolute - // relocations here: since we are not emitting the pre-link CU section, there -diff --git a/src/llvm-project/lld/MachO/UnwindInfoSection.h b/src/llvm-project/lld/MachO/UnwindInfoSection.h -index c6b334731..f2bc3213a 100644 ---- a/src/llvm-project/lld/MachO/UnwindInfoSection.h -+++ b/src/llvm-project/lld/MachO/UnwindInfoSection.h -@@ -24,7 +24,7 @@ public: - // section entirely. - bool isNeeded() const override { return !allEntriesAreOmitted; } - void addSymbol(const Defined *); -- virtual void prepareRelocations() = 0; -+ virtual void prepare() = 0; - - protected: - UnwindInfoSection(); -diff --git a/src/llvm-project/lld/MachO/Writer.cpp b/src/llvm-project/lld/MachO/Writer.cpp -index 3c44a60f4..ce9672dd0 100644 ---- a/src/llvm-project/lld/MachO/Writer.cpp -+++ b/src/llvm-project/lld/MachO/Writer.cpp -@@ -675,7 +675,7 @@ void Writer::scanRelocations() { - } - } - -- in.unwindInfo->prepareRelocations(); -+ in.unwindInfo->prepare(); - } - - void Writer::scanSymbols() { -diff --git a/src/llvm-project/lld/test/ELF/comdat-binding2.s b/src/llvm-project/lld/test/ELF/comdat-binding2.s -new file mode 100644 -index 000000000..3ffd72528 ---- /dev/null -+++ b/src/llvm-project/lld/test/ELF/comdat-binding2.s -@@ -0,0 +1,42 @@ -+# REQUIRES: x86 -+## Test we don't report duplicate definition errors when mixing Clang STB_WEAK -+## and GCC STB_GNU_UNIQUE symbols. -+ -+# RUN: rm -rf %t && split-file %s %t && cd %t -+# RUN: llvm-mc -filetype=obj -triple=x86_64 weak.s -o weak.o -+# RUN: llvm-mc -filetype=obj -triple=x86_64 unique.s -o unique.o -+# RUN: ld.lld weak.o unique.o -o weak -+# RUN: llvm-readelf -s weak | FileCheck %s --check-prefix=WEAK -+# RUN: ld.lld unique.o weak.o -o unique -+# RUN: llvm-readelf -s unique | FileCheck %s --check-prefix=UNIQUE -+ -+# WEAK: OBJECT WEAK DEFAULT [[#]] _ZN1BIiE1aE -+# UNIQUE: OBJECT UNIQUE DEFAULT [[#]] _ZN1BIiE1aE -+ -+#--- weak.s -+## Clang -+ .type _ZN1BIiE1aE,@object -+ .section .bss._ZN1BIiE1aE,"aGwR",@nobits,_ZN1BIiE1aE,comdat -+ .weak _ZN1BIiE1aE -+_ZN1BIiE1aE: -+ .zero 4 -+ -+ .type _ZGVN1BIiE1aE,@object -+ .section .bss._ZGVN1BIiE1aE,"aGw",@nobits,_ZN1BIiE1aE,comdat -+ .weak _ZGVN1BIiE1aE -+_ZGVN1BIiE1aE: -+ .quad 0 -+ -+#--- unique.s -+## GCC -fgnu-unique. Note the different group signature for the second group. -+ .weak _ZN1BIiE1aE -+ .section .bss._ZN1BIiE1aE,"awG",@nobits,_ZN1BIiE1aE,comdat -+ .type _ZN1BIiE1aE, @gnu_unique_object -+_ZN1BIiE1aE: -+ .zero 4 -+ -+ .weak _ZGVN1BIiE1aE -+ .section .bss._ZGVN1BIiE1aE,"awG",@nobits,_ZGVN1BIiE1aE,comdat -+ .type _ZGVN1BIiE1aE, @gnu_unique_object -+_ZGVN1BIiE1aE: -+ .zero 8 -diff --git a/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s b/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s -index 2935bad14..dd39139b6 100644 ---- a/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s -+++ b/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s -@@ -8,7 +8,9 @@ - # RUN: ld.lld %t.o -o /dev/null \ - # RUN: -plugin path/to/liblto_plugin.so \ - # RUN: -plugin-opt=/path/to/lto-wrapper \ -+# RUN: -plugin-opt=/path/to/lto-wrapper.exe \ - # RUN: -plugin-opt=relative/path/to/lto-wrapper \ -+# RUN: -plugin-opt=relative/path/to/lto-wrapper.exe \ - # RUN: -plugin-opt=-fresolution=zed \ - # RUN: -plugin-opt=-pass-through=-lgcc \ - # RUN: -plugin-opt=-pass-through=-lgcc_eh \ -diff --git a/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s b/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s -new file mode 100644 -index 000000000..b14ddb234 ---- /dev/null -+++ b/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s -@@ -0,0 +1,43 @@ -+# REQUIRES: x86 -+# RUN: rm -rf %t; split-file %s %t -+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/eh-frame.s -o %t/eh-frame.o -+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/cu.s -o %t/cu.o -+# RUN: %lld -dylib %t/cu.o %t/eh-frame.o -o %t/out -+ -+## Sanity check: we want our input to contain a section (and not symbol) -+## relocation for the personality reference. -+# RUN: llvm-readobj --relocations %t/cu.o | FileCheck %s --check-prefix=SECT-RELOC -+# SECT-RELOC: Section __compact_unwind { -+# SECT-RELOC-NEXT: __text -+# SECT-RELOC-NEXT: __text -+# SECT-RELOC-NEXT: } -+ -+## Verify that the personality referenced via a symbol reloc in eh-frame.s gets -+## dedup'ed with the personality referenced via a section reloc in cu.s. -+# RUN: llvm-objdump --macho --unwind-info %t/out | FileCheck %s -+# CHECK: Personality functions: (count = 1) -+ -+#--- eh-frame.s -+_fun: -+ .cfi_startproc -+ .cfi_personality 155, _my_personality -+ ## cfi_escape cannot be encoded in compact unwind -+ .cfi_escape 0 -+ ret -+ .cfi_endproc -+ -+.subsections_via_symbols -+ -+#--- cu.s -+.globl _my_personality -+_fun: -+ .cfi_startproc -+ .cfi_personality 155, _my_personality -+ .cfi_def_cfa_offset 16 -+ ret -+ .cfi_endproc -+ -+_my_personality: -+ nop -+ -+.subsections_via_symbols -diff --git a/src/llvm-project/lld/test/wasm/export-all.s b/src/llvm-project/lld/test/wasm/export-all.s -index 009da9f6a..5af835ce4 100644 ---- a/src/llvm-project/lld/test/wasm/export-all.s -+++ b/src/llvm-project/lld/test/wasm/export-all.s -@@ -40,9 +40,12 @@ foo: - # CHECK-NEXT: - Name: __heap_base - # CHECK-NEXT: Kind: GLOBAL - # CHECK-NEXT: Index: 4 --# CHECK-NEXT: - Name: __memory_base -+# CHECK-NEXT: - Name: __heap_end - # CHECK-NEXT: Kind: GLOBAL - # CHECK-NEXT: Index: 5 --# CHECK-NEXT: - Name: __table_base -+# CHECK-NEXT: - Name: __memory_base - # CHECK-NEXT: Kind: GLOBAL - # CHECK-NEXT: Index: 6 -+# CHECK-NEXT: - Name: __table_base -+# CHECK-NEXT: Kind: GLOBAL -+# CHECK-NEXT: Index: 7 -diff --git a/src/llvm-project/lld/test/wasm/mutable-global-exports.s b/src/llvm-project/lld/test/wasm/mutable-global-exports.s -index e2e45ff93..98009610a 100644 ---- a/src/llvm-project/lld/test/wasm/mutable-global-exports.s -+++ b/src/llvm-project/lld/test/wasm/mutable-global-exports.s -@@ -79,10 +79,13 @@ _start: - # CHECK-ALL-NEXT: - Name: __heap_base - # CHECK-ALL-NEXT: Kind: GLOBAL - # CHECK-ALL-NEXT: Index: 5 --# CHECK-ALL-NEXT: - Name: __memory_base -+# CHECK-ALL-NEXT: - Name: __heap_end - # CHECK-ALL-NEXT: Kind: GLOBAL - # CHECK-ALL-NEXT: Index: 6 --# CHECK-ALL-NEXT: - Name: __table_base -+# CHECK-ALL-NEXT: - Name: __memory_base - # CHECK-ALL-NEXT: Kind: GLOBAL - # CHECK-ALL-NEXT: Index: 7 -+# CHECK-ALL-NEXT: - Name: __table_base -+# CHECK-ALL-NEXT: Kind: GLOBAL -+# CHECK-ALL-NEXT: Index: 8 - # CHECK-ALL-NEXT: - Type: CODE -diff --git a/src/llvm-project/lld/wasm/Driver.cpp b/src/llvm-project/lld/wasm/Driver.cpp -index 0a0f0c8a0..4afbfe241 100644 ---- a/src/llvm-project/lld/wasm/Driver.cpp -+++ b/src/llvm-project/lld/wasm/Driver.cpp -@@ -681,6 +681,7 @@ static void createOptionalSymbols() { - if (!config->isPic) { - WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); - WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); -+ WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end"); - WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); - WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); - if (config->is64.value_or(false)) -diff --git a/src/llvm-project/lld/wasm/Symbols.cpp b/src/llvm-project/lld/wasm/Symbols.cpp -index e0670cea6..a79c5bec3 100644 ---- a/src/llvm-project/lld/wasm/Symbols.cpp -+++ b/src/llvm-project/lld/wasm/Symbols.cpp -@@ -83,6 +83,7 @@ DefinedData *WasmSym::dsoHandle; - DefinedData *WasmSym::dataEnd; - DefinedData *WasmSym::globalBase; - DefinedData *WasmSym::heapBase; -+DefinedData *WasmSym::heapEnd; - DefinedData *WasmSym::initMemoryFlag; - GlobalSymbol *WasmSym::stackPointer; - GlobalSymbol *WasmSym::tlsBase; -diff --git a/src/llvm-project/lld/wasm/Symbols.h b/src/llvm-project/lld/wasm/Symbols.h -index c17b720a9..32e75a69c 100644 ---- a/src/llvm-project/lld/wasm/Symbols.h -+++ b/src/llvm-project/lld/wasm/Symbols.h -@@ -538,11 +538,14 @@ struct WasmSym { - // Symbol marking the end of the data and bss. - static DefinedData *dataEnd; - -- // __heap_base -- // Symbol marking the end of the data, bss and explicit stack. Any linear -- // memory following this address is not used by the linked code and can -- // therefore be used as a backing store for brk()/malloc() implementations. -+ // __heap_base/__heap_end -+ // Symbols marking the beginning and end of the "heap". It starts at the end -+ // of the data, bss and explicit stack, and extends to the end of the linear -+ // memory allocated by wasm-ld. This region of memory is not used by the -+ // linked code, so it may be used as a backing store for `sbrk` or `malloc` -+ // implementations. - static DefinedData *heapBase; -+ static DefinedData *heapEnd; - - // __wasm_init_memory_flag - // Symbol whose contents are nonzero iff memory has already been initialized. -diff --git a/src/llvm-project/lld/wasm/Writer.cpp b/src/llvm-project/lld/wasm/Writer.cpp -index f98c95526..f6bbaa02b 100644 ---- a/src/llvm-project/lld/wasm/Writer.cpp -+++ b/src/llvm-project/lld/wasm/Writer.cpp -@@ -340,10 +340,20 @@ void Writer::layoutMemory() { - Twine(maxMemorySetting)); - memoryPtr = config->initialMemory; - } -- out.memorySec->numMemoryPages = -- alignTo(memoryPtr, WasmPageSize) / WasmPageSize; -+ -+ memoryPtr = alignTo(memoryPtr, WasmPageSize); -+ -+ out.memorySec->numMemoryPages = memoryPtr / WasmPageSize; - log("mem: total pages = " + Twine(out.memorySec->numMemoryPages)); - -+ if (WasmSym::heapEnd) { -+ // Set `__heap_end` to follow the end of the statically allocated linear -+ // memory. The fact that this comes last means that a malloc/brk -+ // implementation can grow the heap at runtime. -+ log("mem: heap end = " + Twine(memoryPtr)); -+ WasmSym::heapEnd->setVA(memoryPtr); -+ } -+ - if (config->maxMemory != 0) { - if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize)) - error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); -@@ -363,7 +373,7 @@ void Writer::layoutMemory() { - if (config->isPic) - max = maxMemorySetting; - else -- max = alignTo(memoryPtr, WasmPageSize); -+ max = memoryPtr; - } - out.memorySec->maxMemoryPages = max / WasmPageSize; - log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); -diff --git a/src/llvm-project/lldb/bindings/CMakeLists.txt b/src/llvm-project/lldb/bindings/CMakeLists.txt -index c8aa0bcf9..9eed2f1e6 100644 ---- a/src/llvm-project/lldb/bindings/CMakeLists.txt -+++ b/src/llvm-project/lldb/bindings/CMakeLists.txt -@@ -26,8 +26,6 @@ set(SWIG_COMMON_FLAGS - -features autodoc - -I${LLDB_SOURCE_DIR}/include - -I${CMAKE_CURRENT_SOURCE_DIR} -- -D__STDC_LIMIT_MACROS -- -D__STDC_CONSTANT_MACROS - ${DARWIN_EXTRAS} - ) - -diff --git a/src/llvm-project/lldb/bindings/interfaces.swig b/src/llvm-project/lldb/bindings/interfaces.swig -index c9a6d0f06..021c7683d 100644 ---- a/src/llvm-project/lldb/bindings/interfaces.swig -+++ b/src/llvm-project/lldb/bindings/interfaces.swig -@@ -1,8 +1,5 @@ - /* Various liblldb typedefs that SWIG needs to know about. */ - #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ --/* The ISO C99 standard specifies that in C++ implementations limit macros such -- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ --#define __STDC_LIMIT_MACROS - %include "stdint.i" - - %include "lldb/lldb-defines.h" -diff --git a/src/llvm-project/lldb/bindings/python/python-typemaps.swig b/src/llvm-project/lldb/bindings/python/python-typemaps.swig -index bf3de66b9..d45431c77 100644 ---- a/src/llvm-project/lldb/bindings/python/python-typemaps.swig -+++ b/src/llvm-project/lldb/bindings/python/python-typemaps.swig -@@ -435,7 +435,7 @@ template <> bool SetNumberFromPyObject(double &number, PyObject *obj) { - - %typemap(out) lldb::FileSP { - $result = nullptr; -- lldb::FileSP &sp = $1; -+ const lldb::FileSP &sp = $1; - if (sp) { - PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); - if (!pyfile.IsValid()) -diff --git a/src/llvm-project/lldb/include/lldb/API/SBType.h b/src/llvm-project/lldb/include/lldb/API/SBType.h -index 244d328b5..aa45aeeec 100644 ---- a/src/llvm-project/lldb/include/lldb/API/SBType.h -+++ b/src/llvm-project/lldb/include/lldb/API/SBType.h -@@ -182,6 +182,8 @@ public: - - lldb::SBType GetTemplateArgumentType(uint32_t idx); - -+ /// Return the TemplateArgumentKind of the template argument at index idx. -+ /// Variadic argument packs are automatically expanded. - lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx); - - lldb::SBType GetFunctionReturnType(); -diff --git a/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h b/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h -index 0ad05a275..aefd19d0a 100644 ---- a/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h -+++ b/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h -@@ -338,14 +338,28 @@ public: - GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes, - std::vector &child_indexes) const; - -- size_t GetNumTemplateArguments() const; -- -- lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const; -- CompilerType GetTypeTemplateArgument(size_t idx) const; -+ /// Return the number of template arguments the type has. -+ /// If expand_pack is true, then variadic argument packs are automatically -+ /// expanded to their supplied arguments. If it is false an argument pack -+ /// will only count as 1 argument. -+ size_t GetNumTemplateArguments(bool expand_pack = false) const; -+ -+ // Return the TemplateArgumentKind of the template argument at index idx. -+ // If expand_pack is true, then variadic argument packs are automatically -+ // expanded to their supplied arguments. With expand_pack set to false, an -+ // arguement pack will count as 1 argument and return a type of Pack. -+ lldb::TemplateArgumentKind -+ GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const; -+ CompilerType GetTypeTemplateArgument(size_t idx, -+ bool expand_pack = false) const; - - /// Returns the value of the template argument and its type. -+ /// If expand_pack is true, then variadic argument packs are automatically -+ /// expanded to their supplied arguments. With expand_pack set to false, an -+ /// arguement pack will count as 1 argument and it is invalid to call this -+ /// method on the pack argument. - llvm::Optional -- GetIntegralTemplateArgument(size_t idx) const; -+ GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; - - CompilerType GetTypeForFormatters() const; - -diff --git a/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h b/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h -index be5783596..769449a49 100644 ---- a/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h -+++ b/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h -@@ -346,14 +346,18 @@ public: - const char *name, bool omit_empty_base_classes, - std::vector &child_indexes) = 0; - -- virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type); -+ virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, -+ bool expand_pack); - - virtual lldb::TemplateArgumentKind -- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx); -- virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, -- size_t idx); -+ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, -+ bool expand_pack); -+ virtual CompilerType -+ GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, -+ bool expand_pack); - virtual llvm::Optional -- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx); -+ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, -+ bool expand_pack); - - // Dumping types - -diff --git a/src/llvm-project/lldb/source/API/SBType.cpp b/src/llvm-project/lldb/source/API/SBType.cpp -index 533930c05..adc60a084 100644 ---- a/src/llvm-project/lldb/source/API/SBType.cpp -+++ b/src/llvm-project/lldb/source/API/SBType.cpp -@@ -542,7 +542,8 @@ uint32_t SBType::GetNumberOfTemplateArguments() { - LLDB_INSTRUMENT_VA(this); - - if (IsValid()) -- return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(); -+ return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments( -+ /*expand_pack=*/true); - return 0; - } - -@@ -553,13 +554,15 @@ lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) { - return SBType(); - - CompilerType type; -+ const bool expand_pack = true; - switch(GetTemplateArgumentKind(idx)) { - case eTemplateArgumentKindType: -- type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx); -+ type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument( -+ idx, expand_pack); - break; - case eTemplateArgumentKindIntegral: - type = m_opaque_sp->GetCompilerType(false) -- .GetIntegralTemplateArgument(idx) -+ .GetIntegralTemplateArgument(idx, expand_pack) - ->type; - break; - default: -@@ -574,7 +577,8 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) { - LLDB_INSTRUMENT_VA(this, idx); - - if (IsValid()) -- return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx); -+ return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind( -+ idx, /*expand_pack=*/true); - return eTemplateArgumentKindNull; - } - -diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp -index fa4e8fb42..c0a879555 100644 ---- a/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp -+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp -@@ -127,6 +127,10 @@ llvm::Error PerfEvent::MmapMetadataAndDataBuffer(size_t num_data_pages, - } - - llvm::Error PerfEvent::MmapAuxBuffer(size_t num_aux_pages) { -+#ifndef PERF_ATTR_SIZE_VER5 -+ return createStringError(inconvertibleErrorCode(), -+ "Intel PT Linux perf event not supported"); -+#else - if (num_aux_pages == 0) - return Error::success(); - -@@ -143,6 +147,7 @@ llvm::Error PerfEvent::MmapAuxBuffer(size_t num_aux_pages) { - return Error::success(); - } else - return mmap_aux.takeError(); -+#endif - } - - llvm::Error PerfEvent::MmapMetadataAndBuffers(size_t num_data_pages, -@@ -172,16 +177,24 @@ perf_event_mmap_page &PerfEvent::GetMetadataPage() const { - } - - ArrayRef PerfEvent::GetDataBuffer() const { -+#ifndef PERF_ATTR_SIZE_VER5 -+ llvm_unreachable("Intel PT Linux perf event not supported"); -+#else - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - return {reinterpret_cast(m_metadata_data_base.get()) + - mmap_metadata.data_offset, -- static_cast(mmap_metadata.data_size)}; -+ static_cast(mmap_metadata.data_size)}; -+#endif - } - - ArrayRef PerfEvent::GetAuxBuffer() const { -+#ifndef PERF_ATTR_SIZE_VER5 -+ llvm_unreachable("Intel PT Linux perf event not supported"); -+#else - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - return {reinterpret_cast(m_aux_base.get()), -- static_cast(mmap_metadata.aux_size)}; -+ static_cast(mmap_metadata.aux_size)}; -+#endif - } - - Expected> PerfEvent::GetReadOnlyDataBuffer() { -@@ -190,6 +203,10 @@ Expected> PerfEvent::GetReadOnlyDataBuffer() { - // this piece of code updates some pointers. See more about data_tail - // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. - -+#ifndef PERF_ATTR_SIZE_VER5 -+ return createStringError(inconvertibleErrorCode(), -+ "Intel PT Linux perf event not supported"); -+#else - bool was_enabled = m_enabled; - if (Error err = DisableWithIoctl()) - return std::move(err); -@@ -226,6 +243,7 @@ Expected> PerfEvent::GetReadOnlyDataBuffer() { - } - - return output; -+#endif - } - - Expected> PerfEvent::GetReadOnlyAuxBuffer() { -@@ -234,6 +252,10 @@ Expected> PerfEvent::GetReadOnlyAuxBuffer() { - // this piece of code updates some pointers. See more about aux_tail - // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. - -+#ifndef PERF_ATTR_SIZE_VER5 -+ return createStringError(inconvertibleErrorCode(), -+ "Intel PT Linux perf event not supported"); -+#else - bool was_enabled = m_enabled; - if (Error err = DisableWithIoctl()) - return std::move(err); -@@ -266,6 +288,7 @@ Expected> PerfEvent::GetReadOnlyAuxBuffer() { - } - - return output; -+#endif - } - - Error PerfEvent::DisableWithIoctl() { -@@ -297,11 +320,15 @@ Error PerfEvent::EnableWithIoctl() { - } - - size_t PerfEvent::GetEffectiveDataBufferSize() const { -+#ifndef PERF_ATTR_SIZE_VER5 -+ llvm_unreachable("Intel PT Linux perf event not supported"); -+#else - perf_event_mmap_page &mmap_metadata = GetMetadataPage(); - if (mmap_metadata.data_head < mmap_metadata.data_size) - return mmap_metadata.data_head; - else - return mmap_metadata.data_size; // The buffer has wrapped. -+#endif - } - - Expected -diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp -index c6eb693bb..a1ebe5830 100644 ---- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp -+++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp -@@ -7096,7 +7096,8 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, - } - - size_t --TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { -+TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, -+ bool expand_pack) { - if (!type) - return 0; - -@@ -7111,8 +7112,17 @@ TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { - const clang::ClassTemplateSpecializationDecl *template_decl = - llvm::dyn_cast( - cxx_record_decl); -- if (template_decl) -- return template_decl->getTemplateArgs().size(); -+ if (template_decl) { -+ const auto &template_arg_list = template_decl->getTemplateArgs(); -+ size_t num_args = template_arg_list.size(); -+ assert(num_args && "template specialization without any args"); -+ if (expand_pack && num_args) { -+ const auto &pack = template_arg_list[num_args - 1]; -+ if (pack.getKind() == clang::TemplateArgument::Pack) -+ num_args += pack.pack_size() - 1; -+ } -+ return num_args; -+ } - } - } - break; -@@ -7149,15 +7159,51 @@ TypeSystemClang::GetAsTemplateSpecialization( - } - } - -+const TemplateArgument * -+GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, -+ size_t idx, bool expand_pack) { -+ const auto &args = decl->getTemplateArgs(); -+ const size_t args_size = args.size(); -+ -+ assert(args_size && "template specialization without any args"); -+ if (!args_size) -+ return nullptr; -+ -+ const size_t last_idx = args_size - 1; -+ -+ // We're asked for a template argument that can't be a parameter pack, so -+ // return it without worrying about 'expand_pack'. -+ if (idx < last_idx) -+ return &args[idx]; -+ -+ // We're asked for the last template argument but we don't want/need to -+ // expand it. -+ if (!expand_pack || args[last_idx].getKind() != clang::TemplateArgument::Pack) -+ return idx >= args.size() ? nullptr : &args[idx]; -+ -+ // Index into the expanded pack. -+ // Note that 'idx' counts from the beginning of all template arguments -+ // (including the ones preceding the parameter pack). -+ const auto &pack = args[last_idx]; -+ const size_t pack_idx = idx - last_idx; -+ const size_t pack_size = pack.pack_size(); -+ assert(pack_idx < pack_size && "parameter pack index out-of-bounds"); -+ return &pack.pack_elements()[pack_idx]; -+} -+ - lldb::TemplateArgumentKind - TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, -- size_t arg_idx) { -+ size_t arg_idx, bool expand_pack) { - const clang::ClassTemplateSpecializationDecl *template_decl = - GetAsTemplateSpecialization(type); -- if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size()) -+ if (!template_decl) -+ return eTemplateArgumentKindNull; -+ -+ const auto *arg = GetNthTemplateArgument(template_decl, arg_idx, expand_pack); -+ if (!arg) - return eTemplateArgumentKindNull; - -- switch (template_decl->getTemplateArgs()[arg_idx].getKind()) { -+ switch (arg->getKind()) { - case clang::TemplateArgument::Null: - return eTemplateArgumentKindNull; - -@@ -7190,35 +7236,32 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, - - CompilerType - TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, -- size_t idx) { -+ size_t idx, bool expand_pack) { - const clang::ClassTemplateSpecializationDecl *template_decl = - GetAsTemplateSpecialization(type); -- if (!template_decl || idx >= template_decl->getTemplateArgs().size()) -+ if (!template_decl) - return CompilerType(); - -- const clang::TemplateArgument &template_arg = -- template_decl->getTemplateArgs()[idx]; -- if (template_arg.getKind() != clang::TemplateArgument::Type) -+ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); -+ if (!arg || arg->getKind() != clang::TemplateArgument::Type) - return CompilerType(); - -- return GetType(template_arg.getAsType()); -+ return GetType(arg->getAsType()); - } - - Optional - TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, -- size_t idx) { -+ size_t idx, bool expand_pack) { - const clang::ClassTemplateSpecializationDecl *template_decl = - GetAsTemplateSpecialization(type); -- if (! template_decl || idx >= template_decl->getTemplateArgs().size()) -+ if (!template_decl) - return llvm::None; - -- const clang::TemplateArgument &template_arg = -- template_decl->getTemplateArgs()[idx]; -- if (template_arg.getKind() != clang::TemplateArgument::Integral) -+ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); -+ if (!arg || arg->getKind() != clang::TemplateArgument::Integral) - return llvm::None; - -- return { -- {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}}; -+ return {{arg->getAsIntegral(), GetType(arg->getIntegralType())}}; - } - - CompilerType TypeSystemClang::GetTypeForFormatters(void *type) { -diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h -index 24dbb71c8..7f25a6df5 100644 ---- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h -+++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h -@@ -91,7 +91,7 @@ public: - void SetOwningModule(OptionalClangModuleID id); - /// \} - }; -- -+ - /// A TypeSystem implementation based on Clang. - /// - /// This class uses a single clang::ASTContext as the backend for storing -@@ -334,7 +334,7 @@ public: - - llvm::SmallVector names; - llvm::SmallVector args; -- -+ - const char * pack_name = nullptr; - std::unique_ptr packed_args; - }; -@@ -537,7 +537,7 @@ public: - #ifndef NDEBUG - bool Verify(lldb::opaque_compiler_type_t type) override; - #endif -- -+ - bool IsArrayType(lldb::opaque_compiler_type_t type, - CompilerType *element_type, uint64_t *size, - bool *is_incomplete) override; -@@ -810,16 +810,17 @@ public: - const char *name, bool omit_empty_base_classes, - std::vector &child_indexes) override; - -- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; -+ size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, -+ bool expand_pack) override; - - lldb::TemplateArgumentKind -- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, -- size_t idx) override; -+ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, -+ bool expand_pack) override; - CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, -- size_t idx) override; -+ size_t idx, bool expand_pack) override; - llvm::Optional -- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, -- size_t idx) override; -+ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, -+ bool expand_pack) override; - - CompilerType GetTypeForFormatters(void *type) override; - -diff --git a/src/llvm-project/lldb/source/Symbol/CompilerType.cpp b/src/llvm-project/lldb/source/Symbol/CompilerType.cpp -index ac98352c2..bef456583 100644 ---- a/src/llvm-project/lldb/source/Symbol/CompilerType.cpp -+++ b/src/llvm-project/lldb/source/Symbol/CompilerType.cpp -@@ -659,30 +659,32 @@ size_t CompilerType::GetIndexOfChildMemberWithName( - return 0; - } - --size_t CompilerType::GetNumTemplateArguments() const { -+size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const { - if (IsValid()) { -- return m_type_system->GetNumTemplateArguments(m_type); -+ return m_type_system->GetNumTemplateArguments(m_type, expand_pack); - } - return 0; - } - --TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const { -+TemplateArgumentKind -+CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const { - if (IsValid()) -- return m_type_system->GetTemplateArgumentKind(m_type, idx); -+ return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack); - return eTemplateArgumentKindNull; - } - --CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const { -+CompilerType CompilerType::GetTypeTemplateArgument(size_t idx, -+ bool expand_pack) const { - if (IsValid()) { -- return m_type_system->GetTypeTemplateArgument(m_type, idx); -+ return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack); - } - return CompilerType(); - } - - llvm::Optional --CompilerType::GetIntegralTemplateArgument(size_t idx) const { -+CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const { - if (IsValid()) -- return m_type_system->GetIntegralTemplateArgument(m_type, idx); -+ return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack); - return llvm::None; - } - -diff --git a/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp b/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp -index 3092dc0bf..412373533 100644 ---- a/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp -+++ b/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp -@@ -118,23 +118,25 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) { - return CompilerType(this, type); - } - --size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { -+size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, -+ bool expand_pack) { - return 0; - } - - TemplateArgumentKind --TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { -+TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx, -+ bool expand_pack) { - return eTemplateArgumentKindNull; - } - - CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, -- size_t idx) { -+ size_t idx, bool expand_pack) { - return CompilerType(); - } - - llvm::Optional --TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, -- size_t idx) { -+TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, -+ bool expand_pack) { - return llvm::None; - } - -diff --git a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py -new file mode 100644 -index 000000000..180d3f503 ---- /dev/null -+++ b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py -@@ -0,0 +1,38 @@ -+""" -+Test that the type of arguments to C++ template classes that have variadic -+parameters can be enumerated. -+""" -+import lldb -+from lldbsuite.test.decorators import * -+from lldbsuite.test.lldbtest import * -+from lldbsuite.test import lldbutil -+ -+ -+class TemplatePackArgsTestCase(TestBase): -+ -+ mydir = TestBase.compute_mydir(__file__) -+ -+ def test_template_argument_pack(self): -+ self.build() -+ (_, _, thread, _) = lldbutil.run_to_source_breakpoint(self, -+ 'breakpoint here', lldb.SBFileSpec('main.cpp'), exe_name = 'a.out') -+ frame = thread.GetSelectedFrame() -+ -+ empty_pack = frame.FindVariable('emptyPack') -+ self.assertTrue(empty_pack.IsValid(), -+ 'make sure we find the emptyPack variable') -+ -+ only_pack = frame.FindVariable('onlyPack') -+ self.assertTrue(only_pack.IsValid(), -+ 'make sure we find the onlyPack variable') -+ self.assertEqual(only_pack.GetType().GetNumberOfTemplateArguments(), 4) -+ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(0).GetName(), 'int') -+ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(1).GetName(), 'char') -+ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(2).GetName(), 'double') -+ # Access the C template parameter. -+ nested_template = only_pack.GetType().GetTemplateArgumentType(3) -+ self.assertEqual(nested_template.GetName(), 'D') -+ self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3) -+ self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), 'int') -+ self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), 'int') -+ self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), 'bool') -diff --git a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp -index 8bb0a42b5..26f8eab54 100644 ---- a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp -+++ b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp -@@ -26,7 +26,13 @@ template <> struct D : D { - bool argsAre_Int_bool() { return true; } - }; - -+template struct OnlyPack {}; -+template struct EmptyPack {}; -+ - int main(int argc, char const *argv[]) { -+ EmptyPack emptyPack; -+ OnlyPack> onlyPack; -+ - C myC; - C myLesserC; - myC.member = 64; -@@ -34,7 +40,7 @@ int main(int argc, char const *argv[]) { - (void)C().argsAre_16_32(); - (void)(myC.member != 64); - D myD; -- D myLesserD; -+ D myLesserD; // breakpoint here - myD.member = 64; - (void)D().argsAre_Int_bool(); - (void)D().argsAre_Int_bool(); -diff --git a/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt b/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt -index f636e387b..c6e7e8cf4 100644 ---- a/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt -+++ b/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt -@@ -95,7 +95,7 @@ check_c_source_compiles( - #else - #error Not building for ARM64 - #endif -- int main() { return 0; } -+ int main(void) { return 0; } - " - BUILDING_FOR_ARM64_OSX - ) -diff --git a/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp -index e78a084f5..4da17cf36 100644 ---- a/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp -+++ b/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp -@@ -500,18 +500,24 @@ TEST_F(TestTypeSystemClang, TemplateArguments) { - for (CompilerType t : {type, typedef_type, auto_type}) { - SCOPED_TRACE(t.GetTypeName().AsCString()); - -- EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0), -- eTemplateArgumentKindType); -- EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0), -- int_type); -- EXPECT_EQ(llvm::None, -- m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 0)); -- -- EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1), -- eTemplateArgumentKindIntegral); -- EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1), -- CompilerType()); -- auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1); -+ const bool expand_pack = false; -+ EXPECT_EQ( -+ m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack), -+ eTemplateArgumentKindType); -+ EXPECT_EQ( -+ m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack), -+ int_type); -+ EXPECT_EQ(llvm::None, m_ast->GetIntegralTemplateArgument( -+ t.GetOpaqueQualType(), 0, expand_pack)); -+ -+ EXPECT_EQ( -+ m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack), -+ eTemplateArgumentKindIntegral); -+ EXPECT_EQ( -+ m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack), -+ CompilerType()); -+ auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1, -+ expand_pack); - ASSERT_NE(llvm::None, result); - EXPECT_EQ(arg, result->value); - EXPECT_EQ(int_type, result->type); -diff --git a/src/llvm-project/llvm/CMakeLists.txt b/src/llvm-project/llvm/CMakeLists.txt -index 57eb01d6f..bae2cebaf 100644 ---- a/src/llvm-project/llvm/CMakeLists.txt -+++ b/src/llvm-project/llvm/CMakeLists.txt -@@ -22,7 +22,7 @@ if(NOT DEFINED LLVM_VERSION_MINOR) - set(LLVM_VERSION_MINOR 0) - endif() - if(NOT DEFINED LLVM_VERSION_PATCH) -- set(LLVM_VERSION_PATCH 2) -+ set(LLVM_VERSION_PATCH 7) - endif() - if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX) -@@ -373,6 +373,7 @@ set(LLVM_ALL_TARGETS - BPF - Hexagon - Lanai -+ LoongArch - Mips - MSP430 - NVPTX -@@ -446,6 +447,8 @@ set(LLVM_ENABLE_ZLIB "ON" CACHE STRING "Use zlib for compression/decompression i - - set(LLVM_ENABLE_ZSTD "ON" CACHE STRING "Use zstd for compression/decompression if available. Can be ON, OFF, or FORCE_ON") - -+set(LLVM_USE_STATIC_ZSTD FALSE CACHE BOOL "Use static version of zstd. Can be TRUE, FALSE") -+ - set(LLVM_ENABLE_CURL "OFF" CACHE STRING "Use libcurl for the HTTP client if available. Can be ON, OFF, or FORCE_ON") - - set(LLVM_ENABLE_HTTPLIB "OFF" CACHE STRING "Use cpp-httplib HTTP server library if available. Can be ON, OFF, or FORCE_ON") -diff --git a/src/llvm-project/llvm/cmake/config-ix.cmake b/src/llvm-project/llvm/cmake/config-ix.cmake -index 83512760d..b4b9b748c 100644 ---- a/src/llvm-project/llvm/cmake/config-ix.cmake -+++ b/src/llvm-project/llvm/cmake/config-ix.cmake -@@ -71,7 +71,7 @@ if(APPLE) - CHECK_C_SOURCE_COMPILES(" - static const char *__crashreporter_info__ = 0; - asm(\".desc ___crashreporter_info__, 0x10\"); -- int main() { return 0; }" -+ int main(void) { return 0; }" - HAVE_CRASHREPORTER_INFO) - endif() - -@@ -498,6 +498,8 @@ elseif (LLVM_NATIVE_ARCH MATCHES "riscv64") - set(LLVM_NATIVE_ARCH RISCV) - elseif (LLVM_NATIVE_ARCH STREQUAL "m68k") - set(LLVM_NATIVE_ARCH M68k) -+elseif (LLVM_NATIVE_ARCH MATCHES "loongarch") -+ set(LLVM_NATIVE_ARCH LoongArch) - else () - message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") - endif () -diff --git a/src/llvm-project/llvm/cmake/config.guess b/src/llvm-project/llvm/cmake/config.guess -index 60d3f588d..255257d40 100644 ---- a/src/llvm-project/llvm/cmake/config.guess -+++ b/src/llvm-project/llvm/cmake/config.guess -@@ -1021,6 +1021,9 @@ EOF - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; -+ loongarch64:Linux:*:*) -+ echo loongarch64-unknown-linux-gnu -+ exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; -diff --git a/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake b/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake -index 057431208..1f0507f39 100644 ---- a/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake -+++ b/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake -@@ -212,6 +212,7 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) - else() - if("${stdout}" MATCHES "^mold") - set(LLVM_LINKER_DETECTED YES CACHE INTERNAL "") -+ set(LLVM_LINKER_IS_MOLD YES CACHE INTERNAL "") - message(STATUS "Linker detection: mold") - elseif("${stdout}" MATCHES "GNU gold") - set(LLVM_LINKER_DETECTED YES CACHE INTERNAL "") -diff --git a/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake b/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake -index 3c5ba7299..f11cadf39 100644 ---- a/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake -+++ b/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake -@@ -82,6 +82,19 @@ elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL") - endif() - endif() - -+# Set variable LLVM_ATOMIC_LIB specifying flags for linking against libatomic. -+if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB) -+ # Use options --push-state, --as-needed and --pop-state if linker is known to support them. -+ # Use single option -Wl of compiler driver to avoid incorrect re-ordering of options by CMake. -+ if(LLVM_LINKER_IS_GNULD OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD OR LLVM_LINKER_IS_MOLD) -+ set(LLVM_ATOMIC_LIB "-Wl,--push-state,--as-needed,-latomic,--pop-state") -+ else() -+ set(LLVM_ATOMIC_LIB "-latomic") -+ endif() -+else() -+ set(LLVM_ATOMIC_LIB) -+endif() -+ - ## TODO: This define is only used for the legacy atomic operations in - ## llvm's Atomic.h, which should be replaced. Other code simply - ## assumes C++11 works. -diff --git a/src/llvm-project/llvm/cmake/modules/FindFFI.cmake b/src/llvm-project/llvm/cmake/modules/FindFFI.cmake -index b0d859af8..a493a89d6 100644 ---- a/src/llvm-project/llvm/cmake/modules/FindFFI.cmake -+++ b/src/llvm-project/llvm/cmake/modules/FindFFI.cmake -@@ -45,7 +45,7 @@ if(FFI_LIBRARIES) - struct ffi_cif; - typedef struct ffi_cif ffi_cif; - void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); -- int main() { ffi_call(0, 0, 0, 0); }" -+ int main(void) { ffi_call(0, 0, 0, 0); }" - HAVE_FFI_CALL) - cmake_pop_check_state() - endif() -diff --git a/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake b/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake -index 65edb80fa..eef1f9585 100644 ---- a/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake -+++ b/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake -@@ -20,7 +20,7 @@ if(Terminfo_LIBRARIES) - list(APPEND CMAKE_REQUIRED_LIBRARIES ${Terminfo_LIBRARIES}) - check_c_source_compiles(" - int setupterm(char *term, int filedes, int *errret); -- int main() { return setupterm(0, 0, 0); }" -+ int main(void) { return setupterm(0, 0, 0); }" - Terminfo_LINKABLE) - cmake_pop_check_state() - endif() -diff --git a/src/llvm-project/llvm/cmake/modules/FindZ3.cmake b/src/llvm-project/llvm/cmake/modules/FindZ3.cmake -index 118b1eac3..6fb56d741 100644 ---- a/src/llvm-project/llvm/cmake/modules/FindZ3.cmake -+++ b/src/llvm-project/llvm/cmake/modules/FindZ3.cmake -@@ -18,8 +18,9 @@ function(check_z3_version z3_include z3_lib) - # The program that will be executed to print Z3's version. - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testz3.cpp - "#include -+ #include - #include -- int main() { -+ int main(void) { - unsigned int major, minor, build, rev; - Z3_get_version(&major, &minor, &build, &rev); - printf(\"%u.%u.%u\", major, minor, build); -diff --git a/src/llvm-project/llvm/cmake/modules/Findzstd.cmake b/src/llvm-project/llvm/cmake/modules/Findzstd.cmake -new file mode 100644 -index 000000000..fab9ea803 ---- /dev/null -+++ b/src/llvm-project/llvm/cmake/modules/Findzstd.cmake -@@ -0,0 +1,49 @@ -+# Try to find the zstd library -+# -+# If successful, the following variables will be defined: -+# zstd_INCLUDE_DIR -+# zstd_LIBRARY -+# zstd_FOUND -+# -+# Additionally, one of the following import targets will be defined: -+# zstd::libzstd_shared -+# zstd::libzstd_static -+ -+if(MSVC) -+ set(zstd_SHARED_LIBRARY_SUFFIX "\\${CMAKE_LINK_LIBRARY_SUFFIX}$") -+ set(zstd_STATIC_LIBRARY_SUFFIX "_static\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") -+else() -+ set(zstd_SHARED_LIBRARY_SUFFIX "\\${CMAKE_SHARED_LIBRARY_SUFFIX}$") -+ set(zstd_STATIC_LIBRARY_SUFFIX "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") -+endif() -+ -+find_path(zstd_INCLUDE_DIR NAMES zstd.h) -+find_library(zstd_LIBRARY NAMES zstd zstd_static) -+ -+include(FindPackageHandleStandardArgs) -+find_package_handle_standard_args( -+ zstd DEFAULT_MSG -+ zstd_LIBRARY zstd_INCLUDE_DIR -+) -+ -+if(zstd_FOUND) -+ if(zstd_LIBRARY MATCHES "${zstd_SHARED_LIBRARY_SUFFIX}$" AND -+ NOT TARGET zstd::libzstd_shared) -+ add_library(zstd::libzstd_shared SHARED IMPORTED) -+ set_target_properties(zstd::libzstd_shared PROPERTIES -+ INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" -+ IMPORTED_LOCATION "${zstd_LIBRARY}") -+ endif() -+ if(zstd_LIBRARY MATCHES "${zstd_STATIC_LIBRARY_SUFFIX}$" AND -+ NOT TARGET zstd::libzstd_static) -+ add_library(zstd::libzstd_static STATIC IMPORTED) -+ set_target_properties(zstd::libzstd_static PROPERTIES -+ INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" -+ IMPORTED_LOCATION "${zstd_LIBRARY}") -+ endif() -+endif() -+ -+unset(zstd_SHARED_LIBRARY_SUFFIX) -+unset(zstd_STATIC_LIBRARY_SUFFIX) -+ -+mark_as_advanced(zstd_INCLUDE_DIR zstd_LIBRARY) -diff --git a/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake b/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake -index 56d05f5b5..0fca934be 100644 ---- a/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake -+++ b/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake -@@ -779,7 +779,7 @@ if (LLVM_ENABLE_WARNINGS AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL)) - # line is also a // comment. - set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror -Wcomment") -- CHECK_C_SOURCE_COMPILES("// \\\\\\n//\\nint main() {return 0;}" -+ CHECK_C_SOURCE_COMPILES("// \\\\\\n//\\nint main(void) {return 0;}" - C_WCOMMENT_ALLOWS_LINE_WRAP) - set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) - if (NOT C_WCOMMENT_ALLOWS_LINE_WRAP) -diff --git a/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in b/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in -index fbf28d36b..f1362fa03 100644 ---- a/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in -+++ b/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in -@@ -75,7 +75,6 @@ endif() - - set(LLVM_ENABLE_ZSTD @LLVM_ENABLE_ZSTD@) - if(LLVM_ENABLE_ZSTD) -- set(zstd_ROOT @zstd_ROOT@) - find_package(zstd) - endif() - -diff --git a/src/llvm-project/llvm/docs/ReleaseNotes.rst b/src/llvm-project/llvm/docs/ReleaseNotes.rst -index 9324d26cb..0660bc134 100644 ---- a/src/llvm-project/llvm/docs/ReleaseNotes.rst -+++ b/src/llvm-project/llvm/docs/ReleaseNotes.rst -@@ -227,6 +227,20 @@ Changes to the WebAssembly Backend - - * ... - -+Changes to the SystemZ Backend -+------------------------------ -+ -+* Support z16 processor name. -+* Machine scheduler description for z16. -+* Add support for inline assembly address operands ("p") as well as for SystemZ -+ specific address operands ("ZQ", "ZR", "ZS" and "ZT"). -+* Efficient handling of small memcpy/memset operations up to 32 bytes. -+* Tuning of the inliner. -+* Fixing emission of library calls so that narrow integer arguments are sign or -+ zero extended per the SystemZ ABI. -+* Support added for libunwind. -+* Various minor improvements and bugfixes. -+ - Changes to the X86 Backend - -------------------------- - -diff --git a/src/llvm-project/llvm/include/llvm/ADT/Triple.h b/src/llvm-project/llvm/include/llvm/ADT/Triple.h -index ba4584dc6..dbd0aeaab 100644 ---- a/src/llvm-project/llvm/include/llvm/ADT/Triple.h -+++ b/src/llvm-project/llvm/include/llvm/ADT/Triple.h -@@ -232,6 +232,7 @@ public: - GNUX32, - GNUILP32, - CODE16, -+ GNUABILPX32, - EABI, - EABIHF, - Android, -@@ -823,6 +824,16 @@ public: - : PointerWidth == 64; - } - -+ /// Tests whether the target is LoongArch 32-bit -+ bool isLoongArch32() const { -+ return getArch() == Triple::loongarch32; -+ } -+ -+ /// Tests whether the target is LoongArch 64-bit. -+ bool isLoongArch64() const { -+ return getArch() == Triple::loongarch64; -+ } -+ - /// Tests whether the target is LoongArch (32- and 64-bit). - bool isLoongArch() const { - return getArch() == Triple::loongarch32 || getArch() == Triple::loongarch64; -diff --git a/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h b/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h -index 99e7a9868..43f09b493 100644 ---- a/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h -+++ b/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h -@@ -902,22 +902,13 @@ enum { - - // LoongArch Specific e_flags - enum : unsigned { -- // Reference: https://github.com/loongson/LoongArch-Documentation. -- // The last commit hash (main branch) is -- // 99016636af64d02dee05e39974d4c1e55875c45b. -- // Note that there is an open PR -- // https://github.com/loongson/LoongArch-Documentation/pull/47 -- // talking about using 0x1, 0x2, 0x3 for ILP32S/F/D and use EI_CLASS to -- // distinguish LP64 and ILP32. If this PR get merged, we will update -- // the definition here. -- // Base ABI Types. -- EF_LOONGARCH_BASE_ABI_LP64S = 0x1, // LP64 soft-float ABI -- EF_LOONGARCH_BASE_ABI_LP64F = 0x2, // LP64 single-float ABI -- EF_LOONGARCH_BASE_ABI_LP64D = 0x3, // LP64 double-float ABI -- EF_LOONGARCH_BASE_ABI_ILP32S = 0x5, // ILP32 soft-float ABI -- EF_LOONGARCH_BASE_ABI_ILP32F = 0x6, // ILP32 single-float ABI -- EF_LOONGARCH_BASE_ABI_ILP32D = 0x7, // ILP32 double-float ABI -- EF_LOONGARCH_BASE_ABI_MASK = 0x7, // Mask for selecting base ABI -+ // FIXME: Change these when all ABIs definition were finalized. -+ // See current definitions: -+ // https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version -+ EF_LARCH_ABI = 0x0003, -+ EF_LARCH_ABI_LP32 = 0x0001, -+ EF_LARCH_ABI_LPX32 = 0x0002, -+ EF_LARCH_ABI_LP64 = 0x0003, - }; - - // ELF Relocation types for LoongArch -diff --git a/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt b/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt -index 5151f9125..468d66379 100644 ---- a/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt -+++ b/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt -@@ -10,6 +10,7 @@ tablegen(LLVM IntrinsicsARM.h -gen-intrinsic-enums -intrinsic-prefix=arm) - tablegen(LLVM IntrinsicsBPF.h -gen-intrinsic-enums -intrinsic-prefix=bpf) - tablegen(LLVM IntrinsicsDirectX.h -gen-intrinsic-enums -intrinsic-prefix=dx) - tablegen(LLVM IntrinsicsHexagon.h -gen-intrinsic-enums -intrinsic-prefix=hexagon) -+tablegen(LLVM IntrinsicsLoongArch.h -gen-intrinsic-enums -intrinsic-prefix=loongarch) - tablegen(LLVM IntrinsicsMips.h -gen-intrinsic-enums -intrinsic-prefix=mips) - tablegen(LLVM IntrinsicsNVPTX.h -gen-intrinsic-enums -intrinsic-prefix=nvvm) - tablegen(LLVM IntrinsicsPowerPC.h -gen-intrinsic-enums -intrinsic-prefix=ppc) -diff --git a/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h b/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h -index 0a8d27aad..3f78eb41f 100644 ---- a/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h -+++ b/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h -@@ -269,6 +269,7 @@ public: - Constraint_Uy, - Constraint_X, - Constraint_Z, -+ Constraint_ZB, - Constraint_ZC, - Constraint_Zy, - -diff --git a/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td b/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td -index d46fa4fbf..76f2d66b7 100644 ---- a/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td -+++ b/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td -@@ -2053,3 +2053,4 @@ include "llvm/IR/IntrinsicsRISCV.td" - include "llvm/IR/IntrinsicsSPIRV.td" - include "llvm/IR/IntrinsicsVE.td" - include "llvm/IR/IntrinsicsDirectX.td" -+include "llvm/IR/IntrinsicsLoongArch.td" -diff --git a/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td b/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td -new file mode 100644 -index 000000000..1cbf1d300 ---- /dev/null -+++ b/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td -@@ -0,0 +1,3657 @@ -+//===- IntrinsicsLoongArch.td - Defines LoongArch intrinsics ---------*- tablegen -*-===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+// -+// This file defines all of the LoongArch-specific intrinsics. -+// -+//===----------------------------------------------------------------------===// -+ -+let TargetPrefix = "loongarch" in { // All intrinsics start with "llvm.loongarch.". -+ -+//===----------------------------------------------------------------------===// -+// LoongArch LSX -+ -+def int_loongarch_lsx_vclo_b : ClangBuiltin<"__builtin_lsx_vclo_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclo_h : ClangBuiltin<"__builtin_lsx_vclo_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclo_w : ClangBuiltin<"__builtin_lsx_vclo_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclo_d : ClangBuiltin<"__builtin_lsx_vclo_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vflogb_s : ClangBuiltin<"__builtin_lsx_vflogb_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vflogb_d : ClangBuiltin<"__builtin_lsx_vflogb_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpickve2gr_b : ClangBuiltin<"__builtin_lsx_vpickve2gr_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_h : ClangBuiltin<"__builtin_lsx_vpickve2gr_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_w : ClangBuiltin<"__builtin_lsx_vpickve2gr_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_d : ClangBuiltin<"__builtin_lsx_vpickve2gr_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpickve2gr_bu : ClangBuiltin<"__builtin_lsx_vpickve2gr_bu">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_hu : ClangBuiltin<"__builtin_lsx_vpickve2gr_hu">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_wu : ClangBuiltin<"__builtin_lsx_vpickve2gr_wu">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickve2gr_du : ClangBuiltin<"__builtin_lsx_vpickve2gr_du">, -+ Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vreplvei_b : ClangBuiltin<"__builtin_lsx_vreplvei_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplvei_h : ClangBuiltin<"__builtin_lsx_vreplvei_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplvei_w : ClangBuiltin<"__builtin_lsx_vreplvei_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplvei_d : ClangBuiltin<"__builtin_lsx_vreplvei_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmskltz_b : ClangBuiltin<"__builtin_lsx_vmskltz_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmskltz_h : ClangBuiltin<"__builtin_lsx_vmskltz_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmskltz_w : ClangBuiltin<"__builtin_lsx_vmskltz_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmskltz_d : ClangBuiltin<"__builtin_lsx_vmskltz_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmadd_s : ClangBuiltin<"__builtin_lsx_vfmadd_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmadd_d : ClangBuiltin<"__builtin_lsx_vfmadd_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmsub_s : ClangBuiltin<"__builtin_lsx_vfmsub_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmsub_d : ClangBuiltin<"__builtin_lsx_vfmsub_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfnmadd_s : ClangBuiltin<"__builtin_lsx_vfnmadd_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfnmadd_d : ClangBuiltin<"__builtin_lsx_vfnmadd_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfnmsub_s : ClangBuiltin<"__builtin_lsx_vfnmsub_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfnmsub_d : ClangBuiltin<"__builtin_lsx_vfnmsub_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_caf_s : ClangBuiltin<"__builtin_lsx_vfcmp_caf_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_caf_d : ClangBuiltin<"__builtin_lsx_vfcmp_caf_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cor_s : ClangBuiltin<"__builtin_lsx_vfcmp_cor_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cor_d : ClangBuiltin<"__builtin_lsx_vfcmp_cor_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cun_s : ClangBuiltin<"__builtin_lsx_vfcmp_cun_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cun_d : ClangBuiltin<"__builtin_lsx_vfcmp_cun_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cune_s : ClangBuiltin<"__builtin_lsx_vfcmp_cune_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cune_d : ClangBuiltin<"__builtin_lsx_vfcmp_cune_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cueq_s : ClangBuiltin<"__builtin_lsx_vfcmp_cueq_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cueq_d : ClangBuiltin<"__builtin_lsx_vfcmp_cueq_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_ceq_s : ClangBuiltin<"__builtin_lsx_vfcmp_ceq_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_ceq_d : ClangBuiltin<"__builtin_lsx_vfcmp_ceq_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cne_s : ClangBuiltin<"__builtin_lsx_vfcmp_cne_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cne_d : ClangBuiltin<"__builtin_lsx_vfcmp_cne_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_clt_s : ClangBuiltin<"__builtin_lsx_vfcmp_clt_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_clt_d : ClangBuiltin<"__builtin_lsx_vfcmp_clt_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cult_s : ClangBuiltin<"__builtin_lsx_vfcmp_cult_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cult_d : ClangBuiltin<"__builtin_lsx_vfcmp_cult_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cle_s : ClangBuiltin<"__builtin_lsx_vfcmp_cle_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cle_d : ClangBuiltin<"__builtin_lsx_vfcmp_cle_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_cule_s : ClangBuiltin<"__builtin_lsx_vfcmp_cule_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_cule_d : ClangBuiltin<"__builtin_lsx_vfcmp_cule_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_saf_s : ClangBuiltin<"__builtin_lsx_vfcmp_saf_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_saf_d : ClangBuiltin<"__builtin_lsx_vfcmp_saf_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sor_s : ClangBuiltin<"__builtin_lsx_vfcmp_sor_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sor_d : ClangBuiltin<"__builtin_lsx_vfcmp_sor_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sun_s : ClangBuiltin<"__builtin_lsx_vfcmp_sun_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sun_d : ClangBuiltin<"__builtin_lsx_vfcmp_sun_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sune_s : ClangBuiltin<"__builtin_lsx_vfcmp_sune_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sune_d : ClangBuiltin<"__builtin_lsx_vfcmp_sune_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sueq_s : ClangBuiltin<"__builtin_lsx_vfcmp_sueq_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sueq_d : ClangBuiltin<"__builtin_lsx_vfcmp_sueq_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_seq_s : ClangBuiltin<"__builtin_lsx_vfcmp_seq_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_seq_d : ClangBuiltin<"__builtin_lsx_vfcmp_seq_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sne_s : ClangBuiltin<"__builtin_lsx_vfcmp_sne_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sne_d : ClangBuiltin<"__builtin_lsx_vfcmp_sne_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_slt_s : ClangBuiltin<"__builtin_lsx_vfcmp_slt_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_slt_d : ClangBuiltin<"__builtin_lsx_vfcmp_slt_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sult_s : ClangBuiltin<"__builtin_lsx_vfcmp_sult_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sult_d : ClangBuiltin<"__builtin_lsx_vfcmp_sult_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sle_s : ClangBuiltin<"__builtin_lsx_vfcmp_sle_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sle_d : ClangBuiltin<"__builtin_lsx_vfcmp_sle_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcmp_sule_s : ClangBuiltin<"__builtin_lsx_vfcmp_sule_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcmp_sule_d : ClangBuiltin<"__builtin_lsx_vfcmp_sule_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitsel_v : ClangBuiltin<"__builtin_lsx_vbitsel_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vshuf_b : ClangBuiltin<"__builtin_lsx_vshuf_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vldrepl_b : ClangBuiltin<"__builtin_lsx_vldrepl_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lsx_vldrepl_h : ClangBuiltin<"__builtin_lsx_vldrepl_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lsx_vldrepl_w : ClangBuiltin<"__builtin_lsx_vldrepl_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lsx_vldrepl_d : ClangBuiltin<"__builtin_lsx_vldrepl_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_vstelm_b : ClangBuiltin<"__builtin_lsx_vstelm_b">, -+ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lsx_vstelm_h : ClangBuiltin<"__builtin_lsx_vstelm_h">, -+ Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lsx_vstelm_w : ClangBuiltin<"__builtin_lsx_vstelm_w">, -+ Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lsx_vstelm_d : ClangBuiltin<"__builtin_lsx_vstelm_d">, -+ Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_vldx : ClangBuiltin<"__builtin_lsx_vldx">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i64_ty], -+ [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_vstx : ClangBuiltin<"__builtin_lsx_vstx">, -+ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i64_ty], -+ [IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_vaddwev_d_w : ClangBuiltin<"__builtin_lsx_vaddwev_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_w_h : ClangBuiltin<"__builtin_lsx_vaddwev_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_h_b : ClangBuiltin<"__builtin_lsx_vaddwev_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_q_d : ClangBuiltin<"__builtin_lsx_vaddwev_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsubwev_d_w : ClangBuiltin<"__builtin_lsx_vsubwev_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_w_h : ClangBuiltin<"__builtin_lsx_vsubwev_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_h_b : ClangBuiltin<"__builtin_lsx_vsubwev_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_q_d : ClangBuiltin<"__builtin_lsx_vsubwev_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+ -+def int_loongarch_lsx_vaddwod_d_w : ClangBuiltin<"__builtin_lsx_vaddwod_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_w_h : ClangBuiltin<"__builtin_lsx_vaddwod_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_h_b : ClangBuiltin<"__builtin_lsx_vaddwod_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_q_d : ClangBuiltin<"__builtin_lsx_vaddwod_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsubwod_d_w : ClangBuiltin<"__builtin_lsx_vsubwod_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_w_h : ClangBuiltin<"__builtin_lsx_vsubwod_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_h_b : ClangBuiltin<"__builtin_lsx_vsubwod_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_q_d : ClangBuiltin<"__builtin_lsx_vsubwod_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vaddwev_d_wu : ClangBuiltin<"__builtin_lsx_vaddwev_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_w_hu : ClangBuiltin<"__builtin_lsx_vaddwev_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_h_bu : ClangBuiltin<"__builtin_lsx_vaddwev_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_q_du : ClangBuiltin<"__builtin_lsx_vaddwev_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsubwev_d_wu : ClangBuiltin<"__builtin_lsx_vsubwev_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_w_hu : ClangBuiltin<"__builtin_lsx_vsubwev_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_h_bu : ClangBuiltin<"__builtin_lsx_vsubwev_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwev_q_du : ClangBuiltin<"__builtin_lsx_vsubwev_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vaddwod_d_wu : ClangBuiltin<"__builtin_lsx_vaddwod_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_w_hu : ClangBuiltin<"__builtin_lsx_vaddwod_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_h_bu : ClangBuiltin<"__builtin_lsx_vaddwod_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_q_du : ClangBuiltin<"__builtin_lsx_vaddwod_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsubwod_d_wu : ClangBuiltin<"__builtin_lsx_vsubwod_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_w_hu : ClangBuiltin<"__builtin_lsx_vsubwod_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_h_bu : ClangBuiltin<"__builtin_lsx_vsubwod_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubwod_q_du : ClangBuiltin<"__builtin_lsx_vsubwod_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vaddwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vaddwev_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vaddwev_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vaddwev_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwev_q_du_d : ClangBuiltin<"__builtin_lsx_vaddwev_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vaddwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vaddwod_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vaddwod_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vaddwod_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vaddwod_q_du_d : ClangBuiltin<"__builtin_lsx_vaddwod_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhaddw_qu_du : ClangBuiltin<"__builtin_lsx_vhaddw_qu_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_qu_du : ClangBuiltin<"__builtin_lsx_vhsubw_qu_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhaddw_q_d : ClangBuiltin<"__builtin_lsx_vhaddw_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_q_d : ClangBuiltin<"__builtin_lsx_vhsubw_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmuh_b : ClangBuiltin<"__builtin_lsx_vmuh_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_h : ClangBuiltin<"__builtin_lsx_vmuh_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_w : ClangBuiltin<"__builtin_lsx_vmuh_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_d : ClangBuiltin<"__builtin_lsx_vmuh_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmuh_bu : ClangBuiltin<"__builtin_lsx_vmuh_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_hu : ClangBuiltin<"__builtin_lsx_vmuh_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_wu : ClangBuiltin<"__builtin_lsx_vmuh_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmuh_du : ClangBuiltin<"__builtin_lsx_vmuh_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwev_d_w : ClangBuiltin<"__builtin_lsx_vmulwev_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_w_h : ClangBuiltin<"__builtin_lsx_vmulwev_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_h_b : ClangBuiltin<"__builtin_lsx_vmulwev_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_q_d : ClangBuiltin<"__builtin_lsx_vmulwev_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwod_d_w : ClangBuiltin<"__builtin_lsx_vmulwod_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_w_h : ClangBuiltin<"__builtin_lsx_vmulwod_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_h_b : ClangBuiltin<"__builtin_lsx_vmulwod_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_q_d : ClangBuiltin<"__builtin_lsx_vmulwod_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwev_d_wu : ClangBuiltin<"__builtin_lsx_vmulwev_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_w_hu : ClangBuiltin<"__builtin_lsx_vmulwev_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_h_bu : ClangBuiltin<"__builtin_lsx_vmulwev_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_q_du : ClangBuiltin<"__builtin_lsx_vmulwev_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwod_d_wu : ClangBuiltin<"__builtin_lsx_vmulwod_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_w_hu : ClangBuiltin<"__builtin_lsx_vmulwod_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_h_bu : ClangBuiltin<"__builtin_lsx_vmulwod_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_q_du : ClangBuiltin<"__builtin_lsx_vmulwod_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vmulwev_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vmulwev_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vmulwev_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwev_q_du_d : ClangBuiltin<"__builtin_lsx_vmulwev_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmulwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vmulwod_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vmulwod_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vmulwod_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmulwod_q_du_d : ClangBuiltin<"__builtin_lsx_vmulwod_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwev_d_w : ClangBuiltin<"__builtin_lsx_vmaddwev_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_w_h : ClangBuiltin<"__builtin_lsx_vmaddwev_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_h_b : ClangBuiltin<"__builtin_lsx_vmaddwev_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_q_d : ClangBuiltin<"__builtin_lsx_vmaddwev_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwod_d_w : ClangBuiltin<"__builtin_lsx_vmaddwod_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_w_h : ClangBuiltin<"__builtin_lsx_vmaddwod_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_h_b : ClangBuiltin<"__builtin_lsx_vmaddwod_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_q_d : ClangBuiltin<"__builtin_lsx_vmaddwod_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwev_d_wu : ClangBuiltin<"__builtin_lsx_vmaddwev_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_w_hu : ClangBuiltin<"__builtin_lsx_vmaddwev_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_h_bu : ClangBuiltin<"__builtin_lsx_vmaddwev_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_q_du : ClangBuiltin<"__builtin_lsx_vmaddwev_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwod_d_wu : ClangBuiltin<"__builtin_lsx_vmaddwod_d_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_w_hu : ClangBuiltin<"__builtin_lsx_vmaddwod_w_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_h_bu : ClangBuiltin<"__builtin_lsx_vmaddwod_h_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_q_du : ClangBuiltin<"__builtin_lsx_vmaddwod_q_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vmaddwev_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vmaddwev_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vmaddwev_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwev_q_du_d : ClangBuiltin<"__builtin_lsx_vmaddwev_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaddwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vmaddwod_d_wu_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vmaddwod_w_hu_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vmaddwod_h_bu_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaddwod_q_du_d : ClangBuiltin<"__builtin_lsx_vmaddwod_q_du_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrln_b_h : ClangBuiltin<"__builtin_lsx_vsrln_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrln_h_w : ClangBuiltin<"__builtin_lsx_vsrln_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrln_w_d : ClangBuiltin<"__builtin_lsx_vsrln_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsran_b_h : ClangBuiltin<"__builtin_lsx_vsran_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsran_h_w : ClangBuiltin<"__builtin_lsx_vsran_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsran_w_d : ClangBuiltin<"__builtin_lsx_vsran_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrlrn_b_h : ClangBuiltin<"__builtin_lsx_vsrlrn_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlrn_h_w : ClangBuiltin<"__builtin_lsx_vsrlrn_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlrn_w_d : ClangBuiltin<"__builtin_lsx_vsrlrn_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrarn_b_h : ClangBuiltin<"__builtin_lsx_vsrarn_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrarn_h_w : ClangBuiltin<"__builtin_lsx_vsrarn_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrarn_w_d : ClangBuiltin<"__builtin_lsx_vsrarn_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrln_b_h : ClangBuiltin<"__builtin_lsx_vssrln_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrln_h_w : ClangBuiltin<"__builtin_lsx_vssrln_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrln_w_d : ClangBuiltin<"__builtin_lsx_vssrln_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssran_b_h : ClangBuiltin<"__builtin_lsx_vssran_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssran_h_w : ClangBuiltin<"__builtin_lsx_vssran_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssran_w_d : ClangBuiltin<"__builtin_lsx_vssran_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlrn_b_h : ClangBuiltin<"__builtin_lsx_vssrlrn_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrn_h_w : ClangBuiltin<"__builtin_lsx_vssrlrn_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrn_w_d : ClangBuiltin<"__builtin_lsx_vssrlrn_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrarn_b_h : ClangBuiltin<"__builtin_lsx_vssrarn_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarn_h_w : ClangBuiltin<"__builtin_lsx_vssrarn_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarn_w_d : ClangBuiltin<"__builtin_lsx_vssrarn_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrln_bu_h : ClangBuiltin<"__builtin_lsx_vssrln_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrln_hu_w : ClangBuiltin<"__builtin_lsx_vssrln_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrln_wu_d : ClangBuiltin<"__builtin_lsx_vssrln_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssran_bu_h : ClangBuiltin<"__builtin_lsx_vssran_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssran_hu_w : ClangBuiltin<"__builtin_lsx_vssran_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssran_wu_d : ClangBuiltin<"__builtin_lsx_vssran_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlrn_bu_h : ClangBuiltin<"__builtin_lsx_vssrlrn_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrn_hu_w : ClangBuiltin<"__builtin_lsx_vssrlrn_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrn_wu_d : ClangBuiltin<"__builtin_lsx_vssrlrn_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrarn_bu_h : ClangBuiltin<"__builtin_lsx_vssrarn_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarn_hu_w : ClangBuiltin<"__builtin_lsx_vssrarn_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarn_wu_d : ClangBuiltin<"__builtin_lsx_vssrarn_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vandn_v : ClangBuiltin<"__builtin_lsx_vandn_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vorn_v : ClangBuiltin<"__builtin_lsx_vorn_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrstp_b : ClangBuiltin<"__builtin_lsx_vfrstp_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vfrstp_h : ClangBuiltin<"__builtin_lsx_vfrstp_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vadd_q : ClangBuiltin<"__builtin_lsx_vadd_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsub_q : ClangBuiltin<"__builtin_lsx_vsub_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsigncov_b : ClangBuiltin<"__builtin_lsx_vsigncov_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vsigncov_h : ClangBuiltin<"__builtin_lsx_vsigncov_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vsigncov_w : ClangBuiltin<"__builtin_lsx_vsigncov_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vsigncov_d : ClangBuiltin<"__builtin_lsx_vsigncov_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcvt_h_s : ClangBuiltin<"__builtin_lsx_vfcvt_h_s">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcvt_s_d : ClangBuiltin<"__builtin_lsx_vfcvt_s_d">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vffint_s_l : ClangBuiltin<"__builtin_lsx_vffint_s_l">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftint_w_d : ClangBuiltin<"__builtin_lsx_vftint_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrz_w_d : ClangBuiltin<"__builtin_lsx_vftintrz_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrp_w_d : ClangBuiltin<"__builtin_lsx_vftintrp_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrm_w_d : ClangBuiltin<"__builtin_lsx_vftintrm_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrne_w_d : ClangBuiltin<"__builtin_lsx_vftintrne_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbsrl_v : ClangBuiltin<"__builtin_lsx_vbsrl_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbsll_v : ClangBuiltin<"__builtin_lsx_vbsll_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrstpi_b : ClangBuiltin<"__builtin_lsx_vfrstpi_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrstpi_h : ClangBuiltin<"__builtin_lsx_vfrstpi_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vneg_b : ClangBuiltin<"__builtin_lsx_vneg_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vneg_h : ClangBuiltin<"__builtin_lsx_vneg_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vneg_w : ClangBuiltin<"__builtin_lsx_vneg_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vneg_d : ClangBuiltin<"__builtin_lsx_vneg_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmskgez_b : ClangBuiltin<"__builtin_lsx_vmskgez_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmsknz_b : ClangBuiltin<"__builtin_lsx_vmsknz_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrintrm_s : ClangBuiltin<"__builtin_lsx_vfrintrm_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrintrm_d : ClangBuiltin<"__builtin_lsx_vfrintrm_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrintrp_s : ClangBuiltin<"__builtin_lsx_vfrintrp_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrintrp_d : ClangBuiltin<"__builtin_lsx_vfrintrp_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrintrz_s : ClangBuiltin<"__builtin_lsx_vfrintrz_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrintrz_d : ClangBuiltin<"__builtin_lsx_vfrintrz_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrintrne_s : ClangBuiltin<"__builtin_lsx_vfrintrne_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrintrne_d : ClangBuiltin<"__builtin_lsx_vfrintrne_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vffinth_d_w : ClangBuiltin<"__builtin_lsx_vffinth_d_w">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vffintl_d_w : ClangBuiltin<"__builtin_lsx_vffintl_d_w">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrm_w_s : ClangBuiltin<"__builtin_lsx_vftintrm_w_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrm_l_d : ClangBuiltin<"__builtin_lsx_vftintrm_l_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrp_w_s : ClangBuiltin<"__builtin_lsx_vftintrp_w_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrp_l_d : ClangBuiltin<"__builtin_lsx_vftintrp_l_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrz_w_s : ClangBuiltin<"__builtin_lsx_vftintrz_w_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrz_l_d : ClangBuiltin<"__builtin_lsx_vftintrz_l_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrne_w_s : ClangBuiltin<"__builtin_lsx_vftintrne_w_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrne_l_d : ClangBuiltin<"__builtin_lsx_vftintrne_l_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftinth_l_s : ClangBuiltin<"__builtin_lsx_vftinth_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintl_l_s : ClangBuiltin<"__builtin_lsx_vftintl_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrmh_l_s : ClangBuiltin<"__builtin_lsx_vftintrmh_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrml_l_s : ClangBuiltin<"__builtin_lsx_vftintrml_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrph_l_s : ClangBuiltin<"__builtin_lsx_vftintrph_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrpl_l_s : ClangBuiltin<"__builtin_lsx_vftintrpl_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrzh_l_s : ClangBuiltin<"__builtin_lsx_vftintrzh_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrzl_l_s : ClangBuiltin<"__builtin_lsx_vftintrzl_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrneh_l_s : ClangBuiltin<"__builtin_lsx_vftintrneh_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrnel_l_s : ClangBuiltin<"__builtin_lsx_vftintrnel_l_s">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vexth_d_w : ClangBuiltin<"__builtin_lsx_vexth_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_w_h : ClangBuiltin<"__builtin_lsx_vexth_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_h_b : ClangBuiltin<"__builtin_lsx_vexth_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_q_d : ClangBuiltin<"__builtin_lsx_vexth_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vexth_du_wu : ClangBuiltin<"__builtin_lsx_vexth_du_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_wu_hu : ClangBuiltin<"__builtin_lsx_vexth_wu_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_hu_bu : ClangBuiltin<"__builtin_lsx_vexth_hu_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vexth_qu_du : ClangBuiltin<"__builtin_lsx_vexth_qu_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvexth_du_wu : ClangBuiltin<"__builtin_lasx_xvexth_du_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_wu_hu : ClangBuiltin<"__builtin_lasx_xvexth_wu_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_hu_bu : ClangBuiltin<"__builtin_lasx_xvexth_hu_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_qu_du : ClangBuiltin<"__builtin_lasx_xvexth_qu_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsllwil_d_w : ClangBuiltin<"__builtin_lsx_vsllwil_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsllwil_w_h : ClangBuiltin<"__builtin_lsx_vsllwil_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsllwil_h_b : ClangBuiltin<"__builtin_lsx_vsllwil_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vextl_q_d : ClangBuiltin<"__builtin_lsx_vextl_q_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsllwil_du_wu : ClangBuiltin<"__builtin_lsx_vsllwil_du_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsllwil_wu_hu : ClangBuiltin<"__builtin_lsx_vsllwil_wu_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsllwil_hu_bu : ClangBuiltin<"__builtin_lsx_vsllwil_hu_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vextl_qu_du : ClangBuiltin<"__builtin_lsx_vextl_qu_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitclri_b : ClangBuiltin<"__builtin_lsx_vbitclri_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclri_h : ClangBuiltin<"__builtin_lsx_vbitclri_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclri_w : ClangBuiltin<"__builtin_lsx_vbitclri_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclri_d : ClangBuiltin<"__builtin_lsx_vbitclri_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitseti_b : ClangBuiltin<"__builtin_lsx_vbitseti_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitseti_h : ClangBuiltin<"__builtin_lsx_vbitseti_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitseti_w : ClangBuiltin<"__builtin_lsx_vbitseti_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitseti_d : ClangBuiltin<"__builtin_lsx_vbitseti_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitrevi_b : ClangBuiltin<"__builtin_lsx_vbitrevi_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrevi_h : ClangBuiltin<"__builtin_lsx_vbitrevi_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrevi_w : ClangBuiltin<"__builtin_lsx_vbitrevi_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrevi_d : ClangBuiltin<"__builtin_lsx_vbitrevi_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlrni_b_h : ClangBuiltin<"__builtin_lsx_vssrlrni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_h_w : ClangBuiltin<"__builtin_lsx_vssrlrni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_w_d : ClangBuiltin<"__builtin_lsx_vssrlrni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_d_q : ClangBuiltin<"__builtin_lsx_vssrlrni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrani_b_h : ClangBuiltin<"__builtin_lsx_vsrani_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrani_h_w : ClangBuiltin<"__builtin_lsx_vsrani_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrani_w_d : ClangBuiltin<"__builtin_lsx_vsrani_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrani_d_q : ClangBuiltin<"__builtin_lsx_vsrani_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vextrins_b : ClangBuiltin<"__builtin_lsx_vextrins_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vextrins_h : ClangBuiltin<"__builtin_lsx_vextrins_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vextrins_w : ClangBuiltin<"__builtin_lsx_vextrins_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vextrins_d : ClangBuiltin<"__builtin_lsx_vextrins_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitseli_b : ClangBuiltin<"__builtin_lsx_vbitseli_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vandi_b : ClangBuiltin<"__builtin_lsx_vandi_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vori_b : ClangBuiltin<"__builtin_lsx_vori_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vxori_b : ClangBuiltin<"__builtin_lsx_vxori_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vnori_b : ClangBuiltin<"__builtin_lsx_vnori_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vldi : ClangBuiltin<"__builtin_lsx_vldi">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrepli_b : ClangBuiltin<"__builtin_lsx_vrepli_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrepli_h : ClangBuiltin<"__builtin_lsx_vrepli_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrepli_w : ClangBuiltin<"__builtin_lsx_vrepli_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrepli_d : ClangBuiltin<"__builtin_lsx_vrepli_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpermi_w : ClangBuiltin<"__builtin_lsx_vpermi_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsadd_b : ClangBuiltin<"__builtin_lsx_vsadd_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_h : ClangBuiltin<"__builtin_lsx_vsadd_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_w : ClangBuiltin<"__builtin_lsx_vsadd_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_d : ClangBuiltin<"__builtin_lsx_vsadd_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vssub_b : ClangBuiltin<"__builtin_lsx_vssub_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_h : ClangBuiltin<"__builtin_lsx_vssub_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_w : ClangBuiltin<"__builtin_lsx_vssub_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_d : ClangBuiltin<"__builtin_lsx_vssub_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsadd_bu : ClangBuiltin<"__builtin_lsx_vsadd_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_hu : ClangBuiltin<"__builtin_lsx_vsadd_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_wu : ClangBuiltin<"__builtin_lsx_vsadd_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vsadd_du : ClangBuiltin<"__builtin_lsx_vsadd_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vssub_bu : ClangBuiltin<"__builtin_lsx_vssub_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_hu : ClangBuiltin<"__builtin_lsx_vssub_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_wu : ClangBuiltin<"__builtin_lsx_vssub_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssub_du : ClangBuiltin<"__builtin_lsx_vssub_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhaddw_h_b : ClangBuiltin<"__builtin_lsx_vhaddw_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhaddw_w_h : ClangBuiltin<"__builtin_lsx_vhaddw_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhaddw_d_w : ClangBuiltin<"__builtin_lsx_vhaddw_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhsubw_h_b : ClangBuiltin<"__builtin_lsx_vhsubw_h_b">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_w_h : ClangBuiltin<"__builtin_lsx_vhsubw_w_h">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_d_w : ClangBuiltin<"__builtin_lsx_vhsubw_d_w">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhaddw_hu_bu : ClangBuiltin<"__builtin_lsx_vhaddw_hu_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhaddw_wu_hu : ClangBuiltin<"__builtin_lsx_vhaddw_wu_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhaddw_du_wu : ClangBuiltin<"__builtin_lsx_vhaddw_du_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vhsubw_hu_bu : ClangBuiltin<"__builtin_lsx_vhsubw_hu_bu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_wu_hu : ClangBuiltin<"__builtin_lsx_vhsubw_wu_hu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vhsubw_du_wu : ClangBuiltin<"__builtin_lsx_vhsubw_du_wu">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vadda_b : ClangBuiltin<"__builtin_lsx_vadda_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadda_h : ClangBuiltin<"__builtin_lsx_vadda_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadda_w : ClangBuiltin<"__builtin_lsx_vadda_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadda_d : ClangBuiltin<"__builtin_lsx_vadda_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vabsd_b : ClangBuiltin<"__builtin_lsx_vabsd_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_h : ClangBuiltin<"__builtin_lsx_vabsd_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_w : ClangBuiltin<"__builtin_lsx_vabsd_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_d : ClangBuiltin<"__builtin_lsx_vabsd_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vabsd_bu : ClangBuiltin<"__builtin_lsx_vabsd_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_hu : ClangBuiltin<"__builtin_lsx_vabsd_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_wu : ClangBuiltin<"__builtin_lsx_vabsd_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vabsd_du : ClangBuiltin<"__builtin_lsx_vabsd_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vavg_b : ClangBuiltin<"__builtin_lsx_vavg_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_h : ClangBuiltin<"__builtin_lsx_vavg_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_w : ClangBuiltin<"__builtin_lsx_vavg_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_d : ClangBuiltin<"__builtin_lsx_vavg_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vavg_bu : ClangBuiltin<"__builtin_lsx_vavg_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_hu : ClangBuiltin<"__builtin_lsx_vavg_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_wu : ClangBuiltin<"__builtin_lsx_vavg_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavg_du : ClangBuiltin<"__builtin_lsx_vavg_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vavgr_b : ClangBuiltin<"__builtin_lsx_vavgr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_h : ClangBuiltin<"__builtin_lsx_vavgr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_w : ClangBuiltin<"__builtin_lsx_vavgr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_d : ClangBuiltin<"__builtin_lsx_vavgr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vavgr_bu : ClangBuiltin<"__builtin_lsx_vavgr_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_hu : ClangBuiltin<"__builtin_lsx_vavgr_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_wu : ClangBuiltin<"__builtin_lsx_vavgr_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vavgr_du : ClangBuiltin<"__builtin_lsx_vavgr_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrlr_b : ClangBuiltin<"__builtin_lsx_vsrlr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlr_h : ClangBuiltin<"__builtin_lsx_vsrlr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlr_w : ClangBuiltin<"__builtin_lsx_vsrlr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlr_d : ClangBuiltin<"__builtin_lsx_vsrlr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrar_b : ClangBuiltin<"__builtin_lsx_vsrar_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrar_h : ClangBuiltin<"__builtin_lsx_vsrar_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrar_w : ClangBuiltin<"__builtin_lsx_vsrar_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrar_d : ClangBuiltin<"__builtin_lsx_vsrar_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmax_s : ClangBuiltin<"__builtin_lsx_vfmax_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmax_d : ClangBuiltin<"__builtin_lsx_vfmax_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmin_s : ClangBuiltin<"__builtin_lsx_vfmin_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmin_d : ClangBuiltin<"__builtin_lsx_vfmin_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmaxa_s : ClangBuiltin<"__builtin_lsx_vfmaxa_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmaxa_d : ClangBuiltin<"__builtin_lsx_vfmaxa_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmina_s : ClangBuiltin<"__builtin_lsx_vfmina_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmina_d : ClangBuiltin<"__builtin_lsx_vfmina_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfclass_s : ClangBuiltin<"__builtin_lsx_vfclass_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfclass_d : ClangBuiltin<"__builtin_lsx_vfclass_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrecip_s : ClangBuiltin<"__builtin_lsx_vfrecip_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrecip_d : ClangBuiltin<"__builtin_lsx_vfrecip_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrsqrt_s : ClangBuiltin<"__builtin_lsx_vfrsqrt_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrsqrt_d : ClangBuiltin<"__builtin_lsx_vfrsqrt_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcvtl_s_h : ClangBuiltin<"__builtin_lsx_vfcvtl_s_h">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcvtl_d_s : ClangBuiltin<"__builtin_lsx_vfcvtl_d_s">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfcvth_s_h : ClangBuiltin<"__builtin_lsx_vfcvth_s_h">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfcvth_d_s : ClangBuiltin<"__builtin_lsx_vfcvth_d_s">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftint_w_s : ClangBuiltin<"__builtin_lsx_vftint_w_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftint_l_d : ClangBuiltin<"__builtin_lsx_vftint_l_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftint_wu_s : ClangBuiltin<"__builtin_lsx_vftint_wu_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftint_lu_d : ClangBuiltin<"__builtin_lsx_vftint_lu_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrlri_b : ClangBuiltin<"__builtin_lsx_vsrlri_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlri_h : ClangBuiltin<"__builtin_lsx_vsrlri_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlri_w : ClangBuiltin<"__builtin_lsx_vsrlri_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlri_d : ClangBuiltin<"__builtin_lsx_vsrlri_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrari_b : ClangBuiltin<"__builtin_lsx_vsrari_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrari_h : ClangBuiltin<"__builtin_lsx_vsrari_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrari_w : ClangBuiltin<"__builtin_lsx_vsrari_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrari_d : ClangBuiltin<"__builtin_lsx_vsrari_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsat_b : ClangBuiltin<"__builtin_lsx_vsat_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_h : ClangBuiltin<"__builtin_lsx_vsat_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_w : ClangBuiltin<"__builtin_lsx_vsat_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_d : ClangBuiltin<"__builtin_lsx_vsat_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsat_bu : ClangBuiltin<"__builtin_lsx_vsat_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_hu : ClangBuiltin<"__builtin_lsx_vsat_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_wu : ClangBuiltin<"__builtin_lsx_vsat_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsat_du : ClangBuiltin<"__builtin_lsx_vsat_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrlni_b_h : ClangBuiltin<"__builtin_lsx_vsrlni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlni_h_w : ClangBuiltin<"__builtin_lsx_vsrlni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlni_w_d : ClangBuiltin<"__builtin_lsx_vsrlni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlni_d_q : ClangBuiltin<"__builtin_lsx_vsrlni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrlrni_b_h : ClangBuiltin<"__builtin_lsx_vsrlrni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlrni_h_w : ClangBuiltin<"__builtin_lsx_vsrlrni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlrni_w_d : ClangBuiltin<"__builtin_lsx_vsrlrni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrlrni_d_q : ClangBuiltin<"__builtin_lsx_vsrlrni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlni_b_h : ClangBuiltin<"__builtin_lsx_vssrlni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_h_w : ClangBuiltin<"__builtin_lsx_vssrlni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_w_d : ClangBuiltin<"__builtin_lsx_vssrlni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_d_q : ClangBuiltin<"__builtin_lsx_vssrlni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlrni_bu_h : ClangBuiltin<"__builtin_lsx_vssrlrni_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_hu_w : ClangBuiltin<"__builtin_lsx_vssrlrni_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_wu_d : ClangBuiltin<"__builtin_lsx_vssrlrni_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlrni_du_q : ClangBuiltin<"__builtin_lsx_vssrlrni_du_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrarni_b_h : ClangBuiltin<"__builtin_lsx_vsrarni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrarni_h_w : ClangBuiltin<"__builtin_lsx_vsrarni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrarni_w_d : ClangBuiltin<"__builtin_lsx_vsrarni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrarni_d_q : ClangBuiltin<"__builtin_lsx_vsrarni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrani_b_h : ClangBuiltin<"__builtin_lsx_vssrani_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_h_w : ClangBuiltin<"__builtin_lsx_vssrani_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_w_d : ClangBuiltin<"__builtin_lsx_vssrani_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_d_q : ClangBuiltin<"__builtin_lsx_vssrani_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrani_bu_h : ClangBuiltin<"__builtin_lsx_vssrani_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_hu_w : ClangBuiltin<"__builtin_lsx_vssrani_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_wu_d : ClangBuiltin<"__builtin_lsx_vssrani_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrani_du_q : ClangBuiltin<"__builtin_lsx_vssrani_du_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrarni_b_h : ClangBuiltin<"__builtin_lsx_vssrarni_b_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_h_w : ClangBuiltin<"__builtin_lsx_vssrarni_h_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_w_d : ClangBuiltin<"__builtin_lsx_vssrarni_w_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_d_q : ClangBuiltin<"__builtin_lsx_vssrarni_d_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrarni_bu_h : ClangBuiltin<"__builtin_lsx_vssrarni_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_hu_w : ClangBuiltin<"__builtin_lsx_vssrarni_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_wu_d : ClangBuiltin<"__builtin_lsx_vssrarni_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrarni_du_q : ClangBuiltin<"__builtin_lsx_vssrarni_du_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vssrlni_bu_h : ClangBuiltin<"__builtin_lsx_vssrlni_bu_h">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_hu_w : ClangBuiltin<"__builtin_lsx_vssrlni_hu_w">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_wu_d : ClangBuiltin<"__builtin_lsx_vssrlni_wu_d">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vssrlni_du_q : ClangBuiltin<"__builtin_lsx_vssrlni_du_q">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vseq_b : ClangBuiltin<"__builtin_lsx_vseq_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseq_h : ClangBuiltin<"__builtin_lsx_vseq_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseq_w : ClangBuiltin<"__builtin_lsx_vseq_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseq_d : ClangBuiltin<"__builtin_lsx_vseq_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsle_b : ClangBuiltin<"__builtin_lsx_vsle_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_h : ClangBuiltin<"__builtin_lsx_vsle_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_w : ClangBuiltin<"__builtin_lsx_vsle_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_d : ClangBuiltin<"__builtin_lsx_vsle_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsle_bu : ClangBuiltin<"__builtin_lsx_vsle_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_hu : ClangBuiltin<"__builtin_lsx_vsle_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_wu : ClangBuiltin<"__builtin_lsx_vsle_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsle_du : ClangBuiltin<"__builtin_lsx_vsle_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslt_b : ClangBuiltin<"__builtin_lsx_vslt_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_h : ClangBuiltin<"__builtin_lsx_vslt_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_w : ClangBuiltin<"__builtin_lsx_vslt_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_d : ClangBuiltin<"__builtin_lsx_vslt_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslt_bu : ClangBuiltin<"__builtin_lsx_vslt_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_hu : ClangBuiltin<"__builtin_lsx_vslt_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_wu : ClangBuiltin<"__builtin_lsx_vslt_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslt_du : ClangBuiltin<"__builtin_lsx_vslt_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vadd_b : ClangBuiltin<"__builtin_lsx_vadd_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadd_h : ClangBuiltin<"__builtin_lsx_vadd_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadd_w : ClangBuiltin<"__builtin_lsx_vadd_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vadd_d : ClangBuiltin<"__builtin_lsx_vadd_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vsub_b : ClangBuiltin<"__builtin_lsx_vsub_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsub_h : ClangBuiltin<"__builtin_lsx_vsub_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsub_w : ClangBuiltin<"__builtin_lsx_vsub_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsub_d : ClangBuiltin<"__builtin_lsx_vsub_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmax_b : ClangBuiltin<"__builtin_lsx_vmax_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_h : ClangBuiltin<"__builtin_lsx_vmax_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_w : ClangBuiltin<"__builtin_lsx_vmax_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_d : ClangBuiltin<"__builtin_lsx_vmax_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmin_b : ClangBuiltin<"__builtin_lsx_vmin_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_h : ClangBuiltin<"__builtin_lsx_vmin_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_w : ClangBuiltin<"__builtin_lsx_vmin_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_d : ClangBuiltin<"__builtin_lsx_vmin_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmax_bu : ClangBuiltin<"__builtin_lsx_vmax_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_hu : ClangBuiltin<"__builtin_lsx_vmax_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_wu : ClangBuiltin<"__builtin_lsx_vmax_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmax_du : ClangBuiltin<"__builtin_lsx_vmax_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmin_bu : ClangBuiltin<"__builtin_lsx_vmin_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_hu : ClangBuiltin<"__builtin_lsx_vmin_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_wu : ClangBuiltin<"__builtin_lsx_vmin_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmin_du : ClangBuiltin<"__builtin_lsx_vmin_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmul_b : ClangBuiltin<"__builtin_lsx_vmul_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmul_h : ClangBuiltin<"__builtin_lsx_vmul_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmul_w : ClangBuiltin<"__builtin_lsx_vmul_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmul_d : ClangBuiltin<"__builtin_lsx_vmul_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmadd_b : ClangBuiltin<"__builtin_lsx_vmadd_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmadd_h : ClangBuiltin<"__builtin_lsx_vmadd_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmadd_w : ClangBuiltin<"__builtin_lsx_vmadd_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmadd_d : ClangBuiltin<"__builtin_lsx_vmadd_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmsub_b : ClangBuiltin<"__builtin_lsx_vmsub_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmsub_h : ClangBuiltin<"__builtin_lsx_vmsub_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmsub_w : ClangBuiltin<"__builtin_lsx_vmsub_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vmsub_d : ClangBuiltin<"__builtin_lsx_vmsub_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vdiv_b : ClangBuiltin<"__builtin_lsx_vdiv_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_h : ClangBuiltin<"__builtin_lsx_vdiv_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_w : ClangBuiltin<"__builtin_lsx_vdiv_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_d : ClangBuiltin<"__builtin_lsx_vdiv_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmod_b : ClangBuiltin<"__builtin_lsx_vmod_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_h : ClangBuiltin<"__builtin_lsx_vmod_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_w : ClangBuiltin<"__builtin_lsx_vmod_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_d : ClangBuiltin<"__builtin_lsx_vmod_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vdiv_bu : ClangBuiltin<"__builtin_lsx_vdiv_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_hu : ClangBuiltin<"__builtin_lsx_vdiv_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_wu : ClangBuiltin<"__builtin_lsx_vdiv_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vdiv_du : ClangBuiltin<"__builtin_lsx_vdiv_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsll_b : ClangBuiltin<"__builtin_lsx_vsll_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsll_h : ClangBuiltin<"__builtin_lsx_vsll_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsll_w : ClangBuiltin<"__builtin_lsx_vsll_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsll_d : ClangBuiltin<"__builtin_lsx_vsll_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrl_b : ClangBuiltin<"__builtin_lsx_vsrl_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrl_h : ClangBuiltin<"__builtin_lsx_vsrl_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrl_w : ClangBuiltin<"__builtin_lsx_vsrl_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrl_d : ClangBuiltin<"__builtin_lsx_vsrl_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitclr_b : ClangBuiltin<"__builtin_lsx_vbitclr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclr_h : ClangBuiltin<"__builtin_lsx_vbitclr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclr_w : ClangBuiltin<"__builtin_lsx_vbitclr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitclr_d : ClangBuiltin<"__builtin_lsx_vbitclr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitset_b : ClangBuiltin<"__builtin_lsx_vbitset_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitset_h : ClangBuiltin<"__builtin_lsx_vbitset_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitset_w : ClangBuiltin<"__builtin_lsx_vbitset_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitset_d : ClangBuiltin<"__builtin_lsx_vbitset_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpackev_b : ClangBuiltin<"__builtin_lsx_vpackev_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackev_h : ClangBuiltin<"__builtin_lsx_vpackev_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackev_w : ClangBuiltin<"__builtin_lsx_vpackev_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackev_d : ClangBuiltin<"__builtin_lsx_vpackev_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpackod_b : ClangBuiltin<"__builtin_lsx_vpackod_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackod_h : ClangBuiltin<"__builtin_lsx_vpackod_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackod_w : ClangBuiltin<"__builtin_lsx_vpackod_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpackod_d : ClangBuiltin<"__builtin_lsx_vpackod_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vilvl_b : ClangBuiltin<"__builtin_lsx_vilvl_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvl_h : ClangBuiltin<"__builtin_lsx_vilvl_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvl_w : ClangBuiltin<"__builtin_lsx_vilvl_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvl_d : ClangBuiltin<"__builtin_lsx_vilvl_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vilvh_b : ClangBuiltin<"__builtin_lsx_vilvh_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvh_h : ClangBuiltin<"__builtin_lsx_vilvh_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvh_w : ClangBuiltin<"__builtin_lsx_vilvh_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vilvh_d : ClangBuiltin<"__builtin_lsx_vilvh_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpickev_b : ClangBuiltin<"__builtin_lsx_vpickev_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickev_h : ClangBuiltin<"__builtin_lsx_vpickev_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickev_w : ClangBuiltin<"__builtin_lsx_vpickev_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickev_d : ClangBuiltin<"__builtin_lsx_vpickev_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vand_v : ClangBuiltin<"__builtin_lsx_vand_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vor_v : ClangBuiltin<"__builtin_lsx_vor_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vbitrev_b : ClangBuiltin<"__builtin_lsx_vbitrev_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrev_h : ClangBuiltin<"__builtin_lsx_vbitrev_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrev_w : ClangBuiltin<"__builtin_lsx_vbitrev_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vbitrev_d : ClangBuiltin<"__builtin_lsx_vbitrev_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmod_bu : ClangBuiltin<"__builtin_lsx_vmod_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_hu : ClangBuiltin<"__builtin_lsx_vmod_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_wu : ClangBuiltin<"__builtin_lsx_vmod_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmod_du : ClangBuiltin<"__builtin_lsx_vmod_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpickod_b : ClangBuiltin<"__builtin_lsx_vpickod_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickod_h : ClangBuiltin<"__builtin_lsx_vpickod_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickod_w : ClangBuiltin<"__builtin_lsx_vpickod_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpickod_d : ClangBuiltin<"__builtin_lsx_vpickod_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vreplve_b : ClangBuiltin<"__builtin_lsx_vreplve_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplve_h : ClangBuiltin<"__builtin_lsx_vreplve_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplve_w : ClangBuiltin<"__builtin_lsx_vreplve_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplve_d : ClangBuiltin<"__builtin_lsx_vreplve_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsra_b : ClangBuiltin<"__builtin_lsx_vsra_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsra_h : ClangBuiltin<"__builtin_lsx_vsra_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsra_w : ClangBuiltin<"__builtin_lsx_vsra_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsra_d : ClangBuiltin<"__builtin_lsx_vsra_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vxor_v : ClangBuiltin<"__builtin_lsx_vxor_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vnor_v : ClangBuiltin<"__builtin_lsx_vnor_v">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfadd_s : ClangBuiltin<"__builtin_lsx_vfadd_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfadd_d : ClangBuiltin<"__builtin_lsx_vfadd_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfsub_s : ClangBuiltin<"__builtin_lsx_vfsub_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfsub_d : ClangBuiltin<"__builtin_lsx_vfsub_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfmul_s : ClangBuiltin<"__builtin_lsx_vfmul_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfmul_d : ClangBuiltin<"__builtin_lsx_vfmul_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vshuf_h : ClangBuiltin<"__builtin_lsx_vshuf_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vshuf_w : ClangBuiltin<"__builtin_lsx_vshuf_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vshuf_d : ClangBuiltin<"__builtin_lsx_vshuf_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vseqi_b : ClangBuiltin<"__builtin_lsx_vseqi_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseqi_h : ClangBuiltin<"__builtin_lsx_vseqi_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseqi_w : ClangBuiltin<"__builtin_lsx_vseqi_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vseqi_d : ClangBuiltin<"__builtin_lsx_vseqi_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslei_b : ClangBuiltin<"__builtin_lsx_vslei_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_h : ClangBuiltin<"__builtin_lsx_vslei_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_w : ClangBuiltin<"__builtin_lsx_vslei_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_d : ClangBuiltin<"__builtin_lsx_vslei_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslei_bu : ClangBuiltin<"__builtin_lsx_vslei_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_hu : ClangBuiltin<"__builtin_lsx_vslei_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_wu : ClangBuiltin<"__builtin_lsx_vslei_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslei_du : ClangBuiltin<"__builtin_lsx_vslei_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslti_b : ClangBuiltin<"__builtin_lsx_vslti_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_h : ClangBuiltin<"__builtin_lsx_vslti_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_w : ClangBuiltin<"__builtin_lsx_vslti_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_d : ClangBuiltin<"__builtin_lsx_vslti_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslti_bu : ClangBuiltin<"__builtin_lsx_vslti_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_hu : ClangBuiltin<"__builtin_lsx_vslti_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_wu : ClangBuiltin<"__builtin_lsx_vslti_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslti_du : ClangBuiltin<"__builtin_lsx_vslti_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vaddi_bu : ClangBuiltin<"__builtin_lsx_vaddi_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vaddi_hu : ClangBuiltin<"__builtin_lsx_vaddi_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vaddi_wu : ClangBuiltin<"__builtin_lsx_vaddi_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lsx_vaddi_du : ClangBuiltin<"__builtin_lsx_vaddi_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lsx_vsubi_bu : ClangBuiltin<"__builtin_lsx_vsubi_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubi_hu : ClangBuiltin<"__builtin_lsx_vsubi_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubi_wu : ClangBuiltin<"__builtin_lsx_vsubi_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsubi_du : ClangBuiltin<"__builtin_lsx_vsubi_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaxi_b : ClangBuiltin<"__builtin_lsx_vmaxi_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_h : ClangBuiltin<"__builtin_lsx_vmaxi_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_w : ClangBuiltin<"__builtin_lsx_vmaxi_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_d : ClangBuiltin<"__builtin_lsx_vmaxi_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmini_b : ClangBuiltin<"__builtin_lsx_vmini_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_h : ClangBuiltin<"__builtin_lsx_vmini_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_w : ClangBuiltin<"__builtin_lsx_vmini_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_d : ClangBuiltin<"__builtin_lsx_vmini_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmaxi_bu : ClangBuiltin<"__builtin_lsx_vmaxi_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_hu : ClangBuiltin<"__builtin_lsx_vmaxi_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_wu : ClangBuiltin<"__builtin_lsx_vmaxi_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmaxi_du : ClangBuiltin<"__builtin_lsx_vmaxi_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vmini_bu : ClangBuiltin<"__builtin_lsx_vmini_bu">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_hu : ClangBuiltin<"__builtin_lsx_vmini_hu">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_wu : ClangBuiltin<"__builtin_lsx_vmini_wu">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vmini_du : ClangBuiltin<"__builtin_lsx_vmini_du">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vclz_b : ClangBuiltin<"__builtin_lsx_vclz_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclz_h : ClangBuiltin<"__builtin_lsx_vclz_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclz_w : ClangBuiltin<"__builtin_lsx_vclz_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vclz_d : ClangBuiltin<"__builtin_lsx_vclz_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vpcnt_b : ClangBuiltin<"__builtin_lsx_vpcnt_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpcnt_h : ClangBuiltin<"__builtin_lsx_vpcnt_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpcnt_w : ClangBuiltin<"__builtin_lsx_vpcnt_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vpcnt_d : ClangBuiltin<"__builtin_lsx_vpcnt_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfsqrt_s : ClangBuiltin<"__builtin_lsx_vfsqrt_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfsqrt_d : ClangBuiltin<"__builtin_lsx_vfsqrt_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfrint_s : ClangBuiltin<"__builtin_lsx_vfrint_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfrint_d : ClangBuiltin<"__builtin_lsx_vfrint_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vffint_s_w : ClangBuiltin<"__builtin_lsx_vffint_s_w">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vffint_d_l : ClangBuiltin<"__builtin_lsx_vffint_d_l">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vffint_s_wu : ClangBuiltin<"__builtin_lsx_vffint_s_wu">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vffint_d_lu : ClangBuiltin<"__builtin_lsx_vffint_d_lu">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vftintrz_wu_s : ClangBuiltin<"__builtin_lsx_vftintrz_wu_s">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vftintrz_lu_d : ClangBuiltin<"__builtin_lsx_vftintrz_lu_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vreplgr2vr_b : ClangBuiltin<"__builtin_lsx_vreplgr2vr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplgr2vr_h : ClangBuiltin<"__builtin_lsx_vreplgr2vr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplgr2vr_w : ClangBuiltin<"__builtin_lsx_vreplgr2vr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vreplgr2vr_d : ClangBuiltin<"__builtin_lsx_vreplgr2vr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vinsgr2vr_b : ClangBuiltin<"__builtin_lsx_vinsgr2vr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vinsgr2vr_h : ClangBuiltin<"__builtin_lsx_vinsgr2vr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vinsgr2vr_w : ClangBuiltin<"__builtin_lsx_vinsgr2vr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lsx_vinsgr2vr_d : ClangBuiltin<"__builtin_lsx_vinsgr2vr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i64_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lsx_vfdiv_s : ClangBuiltin<"__builtin_lsx_vfdiv_s">, -+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vfdiv_d : ClangBuiltin<"__builtin_lsx_vfdiv_d">, -+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vslli_b : ClangBuiltin<"__builtin_lsx_vslli_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslli_h : ClangBuiltin<"__builtin_lsx_vslli_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslli_w : ClangBuiltin<"__builtin_lsx_vslli_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vslli_d : ClangBuiltin<"__builtin_lsx_vslli_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrli_b : ClangBuiltin<"__builtin_lsx_vsrli_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrli_h : ClangBuiltin<"__builtin_lsx_vsrli_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrli_w : ClangBuiltin<"__builtin_lsx_vsrli_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrli_d : ClangBuiltin<"__builtin_lsx_vsrli_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vsrai_b : ClangBuiltin<"__builtin_lsx_vsrai_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrai_h : ClangBuiltin<"__builtin_lsx_vsrai_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrai_w : ClangBuiltin<"__builtin_lsx_vsrai_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vsrai_d : ClangBuiltin<"__builtin_lsx_vsrai_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vshuf4i_b : ClangBuiltin<"__builtin_lsx_vshuf4i_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vshuf4i_h : ClangBuiltin<"__builtin_lsx_vshuf4i_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vshuf4i_w : ClangBuiltin<"__builtin_lsx_vshuf4i_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vshuf4i_d : ClangBuiltin<"__builtin_lsx_vshuf4i_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrotr_b : ClangBuiltin<"__builtin_lsx_vrotr_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotr_h : ClangBuiltin<"__builtin_lsx_vrotr_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotr_w : ClangBuiltin<"__builtin_lsx_vrotr_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotr_d : ClangBuiltin<"__builtin_lsx_vrotr_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vrotri_b : ClangBuiltin<"__builtin_lsx_vrotri_b">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotri_h : ClangBuiltin<"__builtin_lsx_vrotri_h">, -+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotri_w : ClangBuiltin<"__builtin_lsx_vrotri_w">, -+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_vrotri_d : ClangBuiltin<"__builtin_lsx_vrotri_d">, -+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_vld : ClangBuiltin<"__builtin_lsx_vld">, -+ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], -+ [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_vst : ClangBuiltin<"__builtin_lsx_vst">, -+ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], -+ [IntrArgMemOnly]>; -+ -+def int_loongarch_lsx_bz_v : ClangBuiltin<"__builtin_lsx_bz_v">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_bnz_v : ClangBuiltin<"__builtin_lsx_bnz_v">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_bz_b : ClangBuiltin<"__builtin_lsx_bz_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bz_h : ClangBuiltin<"__builtin_lsx_bz_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bz_w : ClangBuiltin<"__builtin_lsx_bz_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bz_d : ClangBuiltin<"__builtin_lsx_bz_d">, -+ Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lsx_bnz_b : ClangBuiltin<"__builtin_lsx_bnz_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bnz_h : ClangBuiltin<"__builtin_lsx_bnz_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bnz_w : ClangBuiltin<"__builtin_lsx_bnz_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; -+def int_loongarch_lsx_bnz_d : ClangBuiltin<"__builtin_lsx_bnz_d">, -+ Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; -+ -+//===----------------------------------------------------------------------===// -+//LoongArch LASX -+ -+def int_loongarch_lasx_xvfmadd_s : ClangBuiltin<"__builtin_lasx_xvfmadd_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvfmadd_d : ClangBuiltin<"__builtin_lasx_xvfmadd_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmsub_s : ClangBuiltin<"__builtin_lasx_xvfmsub_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvfmsub_d : ClangBuiltin<"__builtin_lasx_xvfmsub_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], -+ [IntrNoMem]>; -+ -+ -+def int_loongarch_lasx_xvfnmadd_s : ClangBuiltin<"__builtin_lasx_xvfnmadd_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvfnmadd_d : ClangBuiltin<"__builtin_lasx_xvfnmadd_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfnmsub_s : ClangBuiltin<"__builtin_lasx_xvfnmsub_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvfnmsub_d : ClangBuiltin<"__builtin_lasx_xvfnmsub_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvclo_b : ClangBuiltin<"__builtin_lasx_xvclo_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclo_h : ClangBuiltin<"__builtin_lasx_xvclo_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclo_w : ClangBuiltin<"__builtin_lasx_xvclo_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclo_d : ClangBuiltin<"__builtin_lasx_xvclo_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvflogb_s : ClangBuiltin<"__builtin_lasx_xvflogb_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvflogb_d : ClangBuiltin<"__builtin_lasx_xvflogb_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickve2gr_w : ClangBuiltin<"__builtin_lasx_xvpickve2gr_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickve2gr_d : ClangBuiltin<"__builtin_lasx_xvpickve2gr_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickve2gr_wu : ClangBuiltin<"__builtin_lasx_xvpickve2gr_wu">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickve2gr_du : ClangBuiltin<"__builtin_lasx_xvpickve2gr_du">, -+ Intrinsic<[llvm_i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmskltz_b : ClangBuiltin<"__builtin_lasx_xvmskltz_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmskltz_h : ClangBuiltin<"__builtin_lasx_xvmskltz_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmskltz_w : ClangBuiltin<"__builtin_lasx_xvmskltz_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmskltz_d : ClangBuiltin<"__builtin_lasx_xvmskltz_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_caf_s : ClangBuiltin<"__builtin_lasx_xvfcmp_caf_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_caf_d : ClangBuiltin<"__builtin_lasx_xvfcmp_caf_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cor_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cor_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cor_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cor_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cun_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cun_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cun_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cun_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cune_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cune_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cune_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cune_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cueq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cueq_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cueq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cueq_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_ceq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_ceq_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_ceq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_ceq_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cne_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cne_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cne_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cne_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_clt_s : ClangBuiltin<"__builtin_lasx_xvfcmp_clt_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_clt_d : ClangBuiltin<"__builtin_lasx_xvfcmp_clt_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cult_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cult_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cult_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cult_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cle_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cle_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cle_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cle_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_cule_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cule_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_cule_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cule_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_saf_s : ClangBuiltin<"__builtin_lasx_xvfcmp_saf_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_saf_d : ClangBuiltin<"__builtin_lasx_xvfcmp_saf_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sor_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sor_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sor_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sor_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sun_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sun_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sun_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sun_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sune_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sune_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sune_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sune_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sueq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sueq_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sueq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sueq_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_seq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_seq_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_seq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_seq_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sne_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sne_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sne_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sne_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_slt_s : ClangBuiltin<"__builtin_lasx_xvfcmp_slt_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_slt_d : ClangBuiltin<"__builtin_lasx_xvfcmp_slt_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sult_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sult_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sult_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sult_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sle_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sle_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sle_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sle_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcmp_sule_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sule_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcmp_sule_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sule_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitsel_v : ClangBuiltin<"__builtin_lasx_xvbitsel_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvshuf_b : ClangBuiltin<"__builtin_lasx_xvshuf_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvldrepl_b : ClangBuiltin<"__builtin_lasx_xvldrepl_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lasx_xvldrepl_h : ClangBuiltin<"__builtin_lasx_xvldrepl_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lasx_xvldrepl_w : ClangBuiltin<"__builtin_lasx_xvldrepl_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+def int_loongarch_lasx_xvldrepl_d : ClangBuiltin<"__builtin_lasx_xvldrepl_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvstelm_b : ClangBuiltin<"__builtin_lasx_xvstelm_b">, -+ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lasx_xvstelm_h : ClangBuiltin<"__builtin_lasx_xvstelm_h">, -+ Intrinsic<[], [llvm_v16i16_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lasx_xvstelm_w : ClangBuiltin<"__builtin_lasx_xvstelm_w">, -+ Intrinsic<[], [llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+def int_loongarch_lasx_xvstelm_d : ClangBuiltin<"__builtin_lasx_xvstelm_d">, -+ Intrinsic<[], [llvm_v4i64_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvldx : ClangBuiltin<"__builtin_lasx_xvldx">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i64_ty], -+ [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvstx : ClangBuiltin<"__builtin_lasx_xvstx">, -+ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i64_ty], -+ [IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvaddwev_d_w : ClangBuiltin<"__builtin_lasx_xvaddwev_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_w_h : ClangBuiltin<"__builtin_lasx_xvaddwev_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_h_b : ClangBuiltin<"__builtin_lasx_xvaddwev_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_q_d : ClangBuiltin<"__builtin_lasx_xvaddwev_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsubwev_d_w : ClangBuiltin<"__builtin_lasx_xvsubwev_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_w_h : ClangBuiltin<"__builtin_lasx_xvsubwev_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_h_b : ClangBuiltin<"__builtin_lasx_xvsubwev_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_q_d : ClangBuiltin<"__builtin_lasx_xvsubwev_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddwod_d_w : ClangBuiltin<"__builtin_lasx_xvaddwod_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_w_h : ClangBuiltin<"__builtin_lasx_xvaddwod_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_h_b : ClangBuiltin<"__builtin_lasx_xvaddwod_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_q_d : ClangBuiltin<"__builtin_lasx_xvaddwod_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsubwod_d_w : ClangBuiltin<"__builtin_lasx_xvsubwod_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_w_h : ClangBuiltin<"__builtin_lasx_xvsubwod_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_h_b : ClangBuiltin<"__builtin_lasx_xvsubwod_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_q_d : ClangBuiltin<"__builtin_lasx_xvsubwod_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddwev_d_wu : ClangBuiltin<"__builtin_lasx_xvaddwev_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_w_hu : ClangBuiltin<"__builtin_lasx_xvaddwev_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_h_bu : ClangBuiltin<"__builtin_lasx_xvaddwev_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_q_du : ClangBuiltin<"__builtin_lasx_xvaddwev_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsubwev_d_wu : ClangBuiltin<"__builtin_lasx_xvsubwev_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_w_hu : ClangBuiltin<"__builtin_lasx_xvsubwev_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_h_bu : ClangBuiltin<"__builtin_lasx_xvsubwev_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwev_q_du : ClangBuiltin<"__builtin_lasx_xvsubwev_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddwod_d_wu : ClangBuiltin<"__builtin_lasx_xvaddwod_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_w_hu : ClangBuiltin<"__builtin_lasx_xvaddwod_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_h_bu : ClangBuiltin<"__builtin_lasx_xvaddwod_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_q_du : ClangBuiltin<"__builtin_lasx_xvaddwod_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsubwod_d_wu : ClangBuiltin<"__builtin_lasx_xvsubwod_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_w_hu : ClangBuiltin<"__builtin_lasx_xvsubwod_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_h_bu : ClangBuiltin<"__builtin_lasx_xvsubwod_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubwod_q_du : ClangBuiltin<"__builtin_lasx_xvsubwod_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvaddwev_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvaddwev_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvaddwev_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvaddwev_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvaddwod_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvaddwod_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvaddwod_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvaddwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvaddwod_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhaddw_qu_du : ClangBuiltin<"__builtin_lasx_xvhaddw_qu_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_qu_du : ClangBuiltin<"__builtin_lasx_xvhsubw_qu_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhaddw_q_d : ClangBuiltin<"__builtin_lasx_xvhaddw_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_q_d : ClangBuiltin<"__builtin_lasx_xvhsubw_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmuh_b : ClangBuiltin<"__builtin_lasx_xvmuh_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_h : ClangBuiltin<"__builtin_lasx_xvmuh_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_w : ClangBuiltin<"__builtin_lasx_xvmuh_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_d : ClangBuiltin<"__builtin_lasx_xvmuh_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmuh_bu : ClangBuiltin<"__builtin_lasx_xvmuh_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_hu : ClangBuiltin<"__builtin_lasx_xvmuh_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_wu : ClangBuiltin<"__builtin_lasx_xvmuh_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmuh_du : ClangBuiltin<"__builtin_lasx_xvmuh_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwev_d_w : ClangBuiltin<"__builtin_lasx_xvmulwev_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_w_h : ClangBuiltin<"__builtin_lasx_xvmulwev_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_h_b : ClangBuiltin<"__builtin_lasx_xvmulwev_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_q_d : ClangBuiltin<"__builtin_lasx_xvmulwev_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwod_d_w : ClangBuiltin<"__builtin_lasx_xvmulwod_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_w_h : ClangBuiltin<"__builtin_lasx_xvmulwod_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_h_b : ClangBuiltin<"__builtin_lasx_xvmulwod_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_q_d : ClangBuiltin<"__builtin_lasx_xvmulwod_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwev_d_wu : ClangBuiltin<"__builtin_lasx_xvmulwev_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_w_hu : ClangBuiltin<"__builtin_lasx_xvmulwev_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_h_bu : ClangBuiltin<"__builtin_lasx_xvmulwev_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_q_du : ClangBuiltin<"__builtin_lasx_xvmulwev_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwod_d_wu : ClangBuiltin<"__builtin_lasx_xvmulwod_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_w_hu : ClangBuiltin<"__builtin_lasx_xvmulwod_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_h_bu : ClangBuiltin<"__builtin_lasx_xvmulwod_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_q_du : ClangBuiltin<"__builtin_lasx_xvmulwod_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmulwev_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmulwev_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmulwev_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvmulwev_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmulwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmulwod_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmulwod_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmulwod_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmulwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvmulwod_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwev_d_w : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_w_h : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_h_b : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_q_d : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwod_d_w : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_w_h : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_h_b : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_q_d : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwev_d_wu : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_w_hu : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_h_bu : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_q_du : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwod_d_wu : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_w_hu : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_h_bu : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_q_du : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaddwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_wu_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_hu_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_bu_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaddwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_du_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrln_b_h : ClangBuiltin<"__builtin_lasx_xvsrln_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrln_h_w : ClangBuiltin<"__builtin_lasx_xvsrln_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrln_w_d : ClangBuiltin<"__builtin_lasx_xvsrln_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsran_b_h : ClangBuiltin<"__builtin_lasx_xvsran_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsran_h_w : ClangBuiltin<"__builtin_lasx_xvsran_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsran_w_d : ClangBuiltin<"__builtin_lasx_xvsran_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrlrn_b_h : ClangBuiltin<"__builtin_lasx_xvsrlrn_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlrn_h_w : ClangBuiltin<"__builtin_lasx_xvsrlrn_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlrn_w_d : ClangBuiltin<"__builtin_lasx_xvsrlrn_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrarn_b_h : ClangBuiltin<"__builtin_lasx_xvsrarn_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrarn_h_w : ClangBuiltin<"__builtin_lasx_xvsrarn_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrarn_w_d : ClangBuiltin<"__builtin_lasx_xvsrarn_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrln_b_h : ClangBuiltin<"__builtin_lasx_xvssrln_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrln_h_w : ClangBuiltin<"__builtin_lasx_xvssrln_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrln_w_d : ClangBuiltin<"__builtin_lasx_xvssrln_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssran_b_h : ClangBuiltin<"__builtin_lasx_xvssran_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssran_h_w : ClangBuiltin<"__builtin_lasx_xvssran_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssran_w_d : ClangBuiltin<"__builtin_lasx_xvssran_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlrn_b_h : ClangBuiltin<"__builtin_lasx_xvssrlrn_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrn_h_w : ClangBuiltin<"__builtin_lasx_xvssrlrn_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrn_w_d : ClangBuiltin<"__builtin_lasx_xvssrlrn_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrarn_b_h : ClangBuiltin<"__builtin_lasx_xvssrarn_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarn_h_w : ClangBuiltin<"__builtin_lasx_xvssrarn_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarn_w_d : ClangBuiltin<"__builtin_lasx_xvssrarn_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrln_bu_h : ClangBuiltin<"__builtin_lasx_xvssrln_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrln_hu_w : ClangBuiltin<"__builtin_lasx_xvssrln_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrln_wu_d : ClangBuiltin<"__builtin_lasx_xvssrln_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssran_bu_h : ClangBuiltin<"__builtin_lasx_xvssran_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssran_hu_w : ClangBuiltin<"__builtin_lasx_xvssran_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssran_wu_d : ClangBuiltin<"__builtin_lasx_xvssran_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlrn_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlrn_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrn_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlrn_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrn_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlrn_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrarn_bu_h : ClangBuiltin<"__builtin_lasx_xvssrarn_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarn_hu_w : ClangBuiltin<"__builtin_lasx_xvssrarn_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarn_wu_d : ClangBuiltin<"__builtin_lasx_xvssrarn_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvandn_v : ClangBuiltin<"__builtin_lasx_xvandn_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvorn_v : ClangBuiltin<"__builtin_lasx_xvorn_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrstp_b : ClangBuiltin<"__builtin_lasx_xvfrstp_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvfrstp_h : ClangBuiltin<"__builtin_lasx_xvfrstp_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvadd_q : ClangBuiltin<"__builtin_lasx_xvadd_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsub_q : ClangBuiltin<"__builtin_lasx_xvsub_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsigncov_b : ClangBuiltin<"__builtin_lasx_xvsigncov_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvsigncov_h : ClangBuiltin<"__builtin_lasx_xvsigncov_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvsigncov_w : ClangBuiltin<"__builtin_lasx_xvsigncov_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvsigncov_d : ClangBuiltin<"__builtin_lasx_xvsigncov_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcvt_h_s : ClangBuiltin<"__builtin_lasx_xvfcvt_h_s">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcvt_s_d : ClangBuiltin<"__builtin_lasx_xvfcvt_s_d">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvffint_s_l : ClangBuiltin<"__builtin_lasx_xvffint_s_l">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftint_w_d : ClangBuiltin<"__builtin_lasx_xvftint_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrz_w_d : ClangBuiltin<"__builtin_lasx_xvftintrz_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrp_w_d : ClangBuiltin<"__builtin_lasx_xvftintrp_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrm_w_d : ClangBuiltin<"__builtin_lasx_xvftintrm_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrne_w_d : ClangBuiltin<"__builtin_lasx_xvftintrne_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbsrl_v : ClangBuiltin<"__builtin_lasx_xvbsrl_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbsll_v : ClangBuiltin<"__builtin_lasx_xvbsll_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrstpi_b : ClangBuiltin<"__builtin_lasx_xvfrstpi_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrstpi_h : ClangBuiltin<"__builtin_lasx_xvfrstpi_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvneg_b : ClangBuiltin<"__builtin_lasx_xvneg_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvneg_h : ClangBuiltin<"__builtin_lasx_xvneg_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvneg_w : ClangBuiltin<"__builtin_lasx_xvneg_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvneg_d : ClangBuiltin<"__builtin_lasx_xvneg_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmskgez_b : ClangBuiltin<"__builtin_lasx_xvmskgez_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmsknz_b : ClangBuiltin<"__builtin_lasx_xvmsknz_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrintrm_s : ClangBuiltin<"__builtin_lasx_xvfrintrm_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrintrm_d : ClangBuiltin<"__builtin_lasx_xvfrintrm_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrintrp_s : ClangBuiltin<"__builtin_lasx_xvfrintrp_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrintrp_d : ClangBuiltin<"__builtin_lasx_xvfrintrp_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrintrz_s : ClangBuiltin<"__builtin_lasx_xvfrintrz_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrintrz_d : ClangBuiltin<"__builtin_lasx_xvfrintrz_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrintrne_s : ClangBuiltin<"__builtin_lasx_xvfrintrne_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrintrne_d : ClangBuiltin<"__builtin_lasx_xvfrintrne_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvffinth_d_w : ClangBuiltin<"__builtin_lasx_xvffinth_d_w">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvffintl_d_w : ClangBuiltin<"__builtin_lasx_xvffintl_d_w">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrm_w_s : ClangBuiltin<"__builtin_lasx_xvftintrm_w_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrm_l_d : ClangBuiltin<"__builtin_lasx_xvftintrm_l_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrp_w_s : ClangBuiltin<"__builtin_lasx_xvftintrp_w_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrp_l_d : ClangBuiltin<"__builtin_lasx_xvftintrp_l_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrz_w_s : ClangBuiltin<"__builtin_lasx_xvftintrz_w_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrz_l_d : ClangBuiltin<"__builtin_lasx_xvftintrz_l_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrne_w_s : ClangBuiltin<"__builtin_lasx_xvftintrne_w_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrne_l_d : ClangBuiltin<"__builtin_lasx_xvftintrne_l_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftinth_l_s : ClangBuiltin<"__builtin_lasx_xvftinth_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintl_l_s : ClangBuiltin<"__builtin_lasx_xvftintl_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrmh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrmh_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrml_l_s : ClangBuiltin<"__builtin_lasx_xvftintrml_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrph_l_s : ClangBuiltin<"__builtin_lasx_xvftintrph_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrpl_l_s : ClangBuiltin<"__builtin_lasx_xvftintrpl_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrzh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrzh_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrzl_l_s : ClangBuiltin<"__builtin_lasx_xvftintrzl_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrneh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrneh_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrnel_l_s : ClangBuiltin<"__builtin_lasx_xvftintrnel_l_s">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvexth_d_w : ClangBuiltin<"__builtin_lasx_xvexth_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_w_h : ClangBuiltin<"__builtin_lasx_xvexth_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_h_b : ClangBuiltin<"__builtin_lasx_xvexth_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvexth_q_d : ClangBuiltin<"__builtin_lasx_xvexth_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsllwil_d_w : ClangBuiltin<"__builtin_lasx_xvsllwil_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsllwil_w_h : ClangBuiltin<"__builtin_lasx_xvsllwil_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsllwil_h_b : ClangBuiltin<"__builtin_lasx_xvsllwil_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsllwil_du_wu : ClangBuiltin<"__builtin_lasx_xvsllwil_du_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsllwil_wu_hu : ClangBuiltin<"__builtin_lasx_xvsllwil_wu_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsllwil_hu_bu : ClangBuiltin<"__builtin_lasx_xvsllwil_hu_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitclri_b : ClangBuiltin<"__builtin_lasx_xvbitclri_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclri_h : ClangBuiltin<"__builtin_lasx_xvbitclri_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclri_w : ClangBuiltin<"__builtin_lasx_xvbitclri_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclri_d : ClangBuiltin<"__builtin_lasx_xvbitclri_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitseti_b : ClangBuiltin<"__builtin_lasx_xvbitseti_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitseti_h : ClangBuiltin<"__builtin_lasx_xvbitseti_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitseti_w : ClangBuiltin<"__builtin_lasx_xvbitseti_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitseti_d : ClangBuiltin<"__builtin_lasx_xvbitseti_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitrevi_b : ClangBuiltin<"__builtin_lasx_xvbitrevi_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrevi_h : ClangBuiltin<"__builtin_lasx_xvbitrevi_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrevi_w : ClangBuiltin<"__builtin_lasx_xvbitrevi_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrevi_d : ClangBuiltin<"__builtin_lasx_xvbitrevi_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlrni_b_h : ClangBuiltin<"__builtin_lasx_xvssrlrni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_h_w : ClangBuiltin<"__builtin_lasx_xvssrlrni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_w_d : ClangBuiltin<"__builtin_lasx_xvssrlrni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_d_q : ClangBuiltin<"__builtin_lasx_xvssrlrni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrani_b_h : ClangBuiltin<"__builtin_lasx_xvsrani_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrani_h_w : ClangBuiltin<"__builtin_lasx_xvsrani_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrani_w_d : ClangBuiltin<"__builtin_lasx_xvsrani_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrani_d_q : ClangBuiltin<"__builtin_lasx_xvsrani_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvextrins_b : ClangBuiltin<"__builtin_lasx_xvextrins_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvextrins_h : ClangBuiltin<"__builtin_lasx_xvextrins_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvextrins_w : ClangBuiltin<"__builtin_lasx_xvextrins_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvextrins_d : ClangBuiltin<"__builtin_lasx_xvextrins_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitseli_b : ClangBuiltin<"__builtin_lasx_xvbitseli_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvandi_b : ClangBuiltin<"__builtin_lasx_xvandi_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvori_b : ClangBuiltin<"__builtin_lasx_xvori_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvxori_b : ClangBuiltin<"__builtin_lasx_xvxori_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvnori_b : ClangBuiltin<"__builtin_lasx_xvnori_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvldi : ClangBuiltin<"__builtin_lasx_xvldi">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrepli_b : ClangBuiltin<"__builtin_lasx_xvrepli_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrepli_h : ClangBuiltin<"__builtin_lasx_xvrepli_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrepli_w : ClangBuiltin<"__builtin_lasx_xvrepli_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrepli_d : ClangBuiltin<"__builtin_lasx_xvrepli_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpermi_w : ClangBuiltin<"__builtin_lasx_xvpermi_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsadd_b : ClangBuiltin<"__builtin_lasx_xvsadd_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_h : ClangBuiltin<"__builtin_lasx_xvsadd_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_w : ClangBuiltin<"__builtin_lasx_xvsadd_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_d : ClangBuiltin<"__builtin_lasx_xvsadd_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssub_b : ClangBuiltin<"__builtin_lasx_xvssub_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_h : ClangBuiltin<"__builtin_lasx_xvssub_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_w : ClangBuiltin<"__builtin_lasx_xvssub_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_d : ClangBuiltin<"__builtin_lasx_xvssub_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsadd_bu : ClangBuiltin<"__builtin_lasx_xvsadd_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_hu : ClangBuiltin<"__builtin_lasx_xvsadd_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_wu : ClangBuiltin<"__builtin_lasx_xvsadd_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvsadd_du : ClangBuiltin<"__builtin_lasx_xvsadd_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssub_bu : ClangBuiltin<"__builtin_lasx_xvssub_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_hu : ClangBuiltin<"__builtin_lasx_xvssub_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_wu : ClangBuiltin<"__builtin_lasx_xvssub_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssub_du : ClangBuiltin<"__builtin_lasx_xvssub_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhaddw_h_b : ClangBuiltin<"__builtin_lasx_xvhaddw_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhaddw_w_h : ClangBuiltin<"__builtin_lasx_xvhaddw_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhaddw_d_w : ClangBuiltin<"__builtin_lasx_xvhaddw_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhsubw_h_b : ClangBuiltin<"__builtin_lasx_xvhsubw_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_w_h : ClangBuiltin<"__builtin_lasx_xvhsubw_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_d_w : ClangBuiltin<"__builtin_lasx_xvhsubw_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhaddw_hu_bu : ClangBuiltin<"__builtin_lasx_xvhaddw_hu_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhaddw_wu_hu : ClangBuiltin<"__builtin_lasx_xvhaddw_wu_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhaddw_du_wu : ClangBuiltin<"__builtin_lasx_xvhaddw_du_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvhsubw_hu_bu : ClangBuiltin<"__builtin_lasx_xvhsubw_hu_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_wu_hu : ClangBuiltin<"__builtin_lasx_xvhsubw_wu_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvhsubw_du_wu : ClangBuiltin<"__builtin_lasx_xvhsubw_du_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvadda_b : ClangBuiltin<"__builtin_lasx_xvadda_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadda_h : ClangBuiltin<"__builtin_lasx_xvadda_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadda_w : ClangBuiltin<"__builtin_lasx_xvadda_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadda_d : ClangBuiltin<"__builtin_lasx_xvadda_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvabsd_b : ClangBuiltin<"__builtin_lasx_xvabsd_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_h : ClangBuiltin<"__builtin_lasx_xvabsd_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_w : ClangBuiltin<"__builtin_lasx_xvabsd_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_d : ClangBuiltin<"__builtin_lasx_xvabsd_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvabsd_bu : ClangBuiltin<"__builtin_lasx_xvabsd_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_hu : ClangBuiltin<"__builtin_lasx_xvabsd_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_wu : ClangBuiltin<"__builtin_lasx_xvabsd_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvabsd_du : ClangBuiltin<"__builtin_lasx_xvabsd_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvavg_b : ClangBuiltin<"__builtin_lasx_xvavg_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_h : ClangBuiltin<"__builtin_lasx_xvavg_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_w : ClangBuiltin<"__builtin_lasx_xvavg_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_d : ClangBuiltin<"__builtin_lasx_xvavg_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvavg_bu : ClangBuiltin<"__builtin_lasx_xvavg_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_hu : ClangBuiltin<"__builtin_lasx_xvavg_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_wu : ClangBuiltin<"__builtin_lasx_xvavg_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavg_du : ClangBuiltin<"__builtin_lasx_xvavg_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvavgr_b : ClangBuiltin<"__builtin_lasx_xvavgr_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_h : ClangBuiltin<"__builtin_lasx_xvavgr_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_w : ClangBuiltin<"__builtin_lasx_xvavgr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_d : ClangBuiltin<"__builtin_lasx_xvavgr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvavgr_bu : ClangBuiltin<"__builtin_lasx_xvavgr_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_hu : ClangBuiltin<"__builtin_lasx_xvavgr_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_wu : ClangBuiltin<"__builtin_lasx_xvavgr_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvavgr_du : ClangBuiltin<"__builtin_lasx_xvavgr_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrlr_b : ClangBuiltin<"__builtin_lasx_xvsrlr_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlr_h : ClangBuiltin<"__builtin_lasx_xvsrlr_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlr_w : ClangBuiltin<"__builtin_lasx_xvsrlr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlr_d : ClangBuiltin<"__builtin_lasx_xvsrlr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrar_b : ClangBuiltin<"__builtin_lasx_xvsrar_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrar_h : ClangBuiltin<"__builtin_lasx_xvsrar_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrar_w : ClangBuiltin<"__builtin_lasx_xvsrar_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrar_d : ClangBuiltin<"__builtin_lasx_xvsrar_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmax_s : ClangBuiltin<"__builtin_lasx_xvfmax_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfmax_d : ClangBuiltin<"__builtin_lasx_xvfmax_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmin_s : ClangBuiltin<"__builtin_lasx_xvfmin_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfmin_d : ClangBuiltin<"__builtin_lasx_xvfmin_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmaxa_s : ClangBuiltin<"__builtin_lasx_xvfmaxa_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfmaxa_d : ClangBuiltin<"__builtin_lasx_xvfmaxa_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmina_s : ClangBuiltin<"__builtin_lasx_xvfmina_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfmina_d : ClangBuiltin<"__builtin_lasx_xvfmina_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfclass_s : ClangBuiltin<"__builtin_lasx_xvfclass_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfclass_d : ClangBuiltin<"__builtin_lasx_xvfclass_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrecip_s : ClangBuiltin<"__builtin_lasx_xvfrecip_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrecip_d : ClangBuiltin<"__builtin_lasx_xvfrecip_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrsqrt_s : ClangBuiltin<"__builtin_lasx_xvfrsqrt_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrsqrt_d : ClangBuiltin<"__builtin_lasx_xvfrsqrt_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcvtl_s_h : ClangBuiltin<"__builtin_lasx_xvfcvtl_s_h">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcvtl_d_s : ClangBuiltin<"__builtin_lasx_xvfcvtl_d_s">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfcvth_s_h : ClangBuiltin<"__builtin_lasx_xvfcvth_s_h">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfcvth_d_s : ClangBuiltin<"__builtin_lasx_xvfcvth_d_s">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftint_w_s : ClangBuiltin<"__builtin_lasx_xvftint_w_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftint_l_d : ClangBuiltin<"__builtin_lasx_xvftint_l_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftint_wu_s : ClangBuiltin<"__builtin_lasx_xvftint_wu_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftint_lu_d : ClangBuiltin<"__builtin_lasx_xvftint_lu_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrlri_b : ClangBuiltin<"__builtin_lasx_xvsrlri_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlri_h : ClangBuiltin<"__builtin_lasx_xvsrlri_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlri_w : ClangBuiltin<"__builtin_lasx_xvsrlri_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlri_d : ClangBuiltin<"__builtin_lasx_xvsrlri_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrari_b : ClangBuiltin<"__builtin_lasx_xvsrari_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrari_h : ClangBuiltin<"__builtin_lasx_xvsrari_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrari_w : ClangBuiltin<"__builtin_lasx_xvsrari_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrari_d : ClangBuiltin<"__builtin_lasx_xvsrari_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsat_b : ClangBuiltin<"__builtin_lasx_xvsat_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_h : ClangBuiltin<"__builtin_lasx_xvsat_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_w : ClangBuiltin<"__builtin_lasx_xvsat_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_d : ClangBuiltin<"__builtin_lasx_xvsat_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsat_bu : ClangBuiltin<"__builtin_lasx_xvsat_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_hu : ClangBuiltin<"__builtin_lasx_xvsat_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_wu : ClangBuiltin<"__builtin_lasx_xvsat_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsat_du : ClangBuiltin<"__builtin_lasx_xvsat_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrlni_b_h : ClangBuiltin<"__builtin_lasx_xvsrlni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlni_h_w : ClangBuiltin<"__builtin_lasx_xvsrlni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlni_w_d : ClangBuiltin<"__builtin_lasx_xvsrlni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlni_d_q : ClangBuiltin<"__builtin_lasx_xvsrlni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlni_b_h : ClangBuiltin<"__builtin_lasx_xvssrlni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_h_w : ClangBuiltin<"__builtin_lasx_xvssrlni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_w_d : ClangBuiltin<"__builtin_lasx_xvssrlni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_d_q : ClangBuiltin<"__builtin_lasx_xvssrlni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlrni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlrni_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlrni_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlrni_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlrni_du_q : ClangBuiltin<"__builtin_lasx_xvssrlrni_du_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrarni_b_h : ClangBuiltin<"__builtin_lasx_xvsrarni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrarni_h_w : ClangBuiltin<"__builtin_lasx_xvsrarni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrarni_w_d : ClangBuiltin<"__builtin_lasx_xvsrarni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrarni_d_q : ClangBuiltin<"__builtin_lasx_xvsrarni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrani_b_h : ClangBuiltin<"__builtin_lasx_xvssrani_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_h_w : ClangBuiltin<"__builtin_lasx_xvssrani_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_w_d : ClangBuiltin<"__builtin_lasx_xvssrani_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_d_q : ClangBuiltin<"__builtin_lasx_xvssrani_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrani_bu_h : ClangBuiltin<"__builtin_lasx_xvssrani_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_hu_w : ClangBuiltin<"__builtin_lasx_xvssrani_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_wu_d : ClangBuiltin<"__builtin_lasx_xvssrani_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrani_du_q : ClangBuiltin<"__builtin_lasx_xvssrani_du_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrarni_b_h : ClangBuiltin<"__builtin_lasx_xvssrarni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_h_w : ClangBuiltin<"__builtin_lasx_xvssrarni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_w_d : ClangBuiltin<"__builtin_lasx_xvssrarni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_d_q : ClangBuiltin<"__builtin_lasx_xvssrarni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrarni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrarni_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrarni_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrarni_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrarni_du_q : ClangBuiltin<"__builtin_lasx_xvssrarni_du_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvssrlni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlni_bu_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlni_hu_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlni_wu_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvssrlni_du_q : ClangBuiltin<"__builtin_lasx_xvssrlni_du_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvseq_b : ClangBuiltin<"__builtin_lasx_xvseq_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseq_h : ClangBuiltin<"__builtin_lasx_xvseq_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseq_w : ClangBuiltin<"__builtin_lasx_xvseq_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseq_d : ClangBuiltin<"__builtin_lasx_xvseq_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsle_b : ClangBuiltin<"__builtin_lasx_xvsle_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_h : ClangBuiltin<"__builtin_lasx_xvsle_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_w : ClangBuiltin<"__builtin_lasx_xvsle_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_d : ClangBuiltin<"__builtin_lasx_xvsle_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsle_bu : ClangBuiltin<"__builtin_lasx_xvsle_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_hu : ClangBuiltin<"__builtin_lasx_xvsle_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_wu : ClangBuiltin<"__builtin_lasx_xvsle_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsle_du : ClangBuiltin<"__builtin_lasx_xvsle_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslt_b : ClangBuiltin<"__builtin_lasx_xvslt_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_h : ClangBuiltin<"__builtin_lasx_xvslt_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_w : ClangBuiltin<"__builtin_lasx_xvslt_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_d : ClangBuiltin<"__builtin_lasx_xvslt_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslt_bu : ClangBuiltin<"__builtin_lasx_xvslt_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_hu : ClangBuiltin<"__builtin_lasx_xvslt_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_wu : ClangBuiltin<"__builtin_lasx_xvslt_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslt_du : ClangBuiltin<"__builtin_lasx_xvslt_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvadd_b : ClangBuiltin<"__builtin_lasx_xvadd_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadd_h : ClangBuiltin<"__builtin_lasx_xvadd_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadd_w : ClangBuiltin<"__builtin_lasx_xvadd_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvadd_d : ClangBuiltin<"__builtin_lasx_xvadd_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsub_b : ClangBuiltin<"__builtin_lasx_xvsub_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsub_h : ClangBuiltin<"__builtin_lasx_xvsub_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsub_w : ClangBuiltin<"__builtin_lasx_xvsub_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsub_d : ClangBuiltin<"__builtin_lasx_xvsub_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmax_b : ClangBuiltin<"__builtin_lasx_xvmax_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_h : ClangBuiltin<"__builtin_lasx_xvmax_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_w : ClangBuiltin<"__builtin_lasx_xvmax_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_d : ClangBuiltin<"__builtin_lasx_xvmax_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmin_b : ClangBuiltin<"__builtin_lasx_xvmin_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_h : ClangBuiltin<"__builtin_lasx_xvmin_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_w : ClangBuiltin<"__builtin_lasx_xvmin_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_d : ClangBuiltin<"__builtin_lasx_xvmin_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmax_bu : ClangBuiltin<"__builtin_lasx_xvmax_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_hu : ClangBuiltin<"__builtin_lasx_xvmax_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_wu : ClangBuiltin<"__builtin_lasx_xvmax_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmax_du : ClangBuiltin<"__builtin_lasx_xvmax_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmin_bu : ClangBuiltin<"__builtin_lasx_xvmin_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_hu : ClangBuiltin<"__builtin_lasx_xvmin_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_wu : ClangBuiltin<"__builtin_lasx_xvmin_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmin_du : ClangBuiltin<"__builtin_lasx_xvmin_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmul_b : ClangBuiltin<"__builtin_lasx_xvmul_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmul_h : ClangBuiltin<"__builtin_lasx_xvmul_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmul_w : ClangBuiltin<"__builtin_lasx_xvmul_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmul_d : ClangBuiltin<"__builtin_lasx_xvmul_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmadd_b : ClangBuiltin<"__builtin_lasx_xvmadd_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmadd_h : ClangBuiltin<"__builtin_lasx_xvmadd_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmadd_w : ClangBuiltin<"__builtin_lasx_xvmadd_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmadd_d : ClangBuiltin<"__builtin_lasx_xvmadd_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmsub_b : ClangBuiltin<"__builtin_lasx_xvmsub_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmsub_h : ClangBuiltin<"__builtin_lasx_xvmsub_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmsub_w : ClangBuiltin<"__builtin_lasx_xvmsub_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvmsub_d : ClangBuiltin<"__builtin_lasx_xvmsub_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvdiv_b : ClangBuiltin<"__builtin_lasx_xvdiv_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_h : ClangBuiltin<"__builtin_lasx_xvdiv_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_w : ClangBuiltin<"__builtin_lasx_xvdiv_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_d : ClangBuiltin<"__builtin_lasx_xvdiv_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmod_b : ClangBuiltin<"__builtin_lasx_xvmod_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_h : ClangBuiltin<"__builtin_lasx_xvmod_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_w : ClangBuiltin<"__builtin_lasx_xvmod_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_d : ClangBuiltin<"__builtin_lasx_xvmod_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvdiv_bu : ClangBuiltin<"__builtin_lasx_xvdiv_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_hu : ClangBuiltin<"__builtin_lasx_xvdiv_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_wu : ClangBuiltin<"__builtin_lasx_xvdiv_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvdiv_du : ClangBuiltin<"__builtin_lasx_xvdiv_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsll_b : ClangBuiltin<"__builtin_lasx_xvsll_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsll_h : ClangBuiltin<"__builtin_lasx_xvsll_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsll_w : ClangBuiltin<"__builtin_lasx_xvsll_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsll_d : ClangBuiltin<"__builtin_lasx_xvsll_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrl_b : ClangBuiltin<"__builtin_lasx_xvsrl_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrl_h : ClangBuiltin<"__builtin_lasx_xvsrl_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrl_w : ClangBuiltin<"__builtin_lasx_xvsrl_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrl_d : ClangBuiltin<"__builtin_lasx_xvsrl_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitclr_b : ClangBuiltin<"__builtin_lasx_xvbitclr_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclr_h : ClangBuiltin<"__builtin_lasx_xvbitclr_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclr_w : ClangBuiltin<"__builtin_lasx_xvbitclr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitclr_d : ClangBuiltin<"__builtin_lasx_xvbitclr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitset_b : ClangBuiltin<"__builtin_lasx_xvbitset_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitset_h : ClangBuiltin<"__builtin_lasx_xvbitset_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitset_w : ClangBuiltin<"__builtin_lasx_xvbitset_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitset_d : ClangBuiltin<"__builtin_lasx_xvbitset_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpackev_b : ClangBuiltin<"__builtin_lasx_xvpackev_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackev_h : ClangBuiltin<"__builtin_lasx_xvpackev_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackev_w : ClangBuiltin<"__builtin_lasx_xvpackev_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackev_d : ClangBuiltin<"__builtin_lasx_xvpackev_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpackod_b : ClangBuiltin<"__builtin_lasx_xvpackod_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackod_h : ClangBuiltin<"__builtin_lasx_xvpackod_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackod_w : ClangBuiltin<"__builtin_lasx_xvpackod_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpackod_d : ClangBuiltin<"__builtin_lasx_xvpackod_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvilvl_b : ClangBuiltin<"__builtin_lasx_xvilvl_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvl_h : ClangBuiltin<"__builtin_lasx_xvilvl_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvl_w : ClangBuiltin<"__builtin_lasx_xvilvl_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvl_d : ClangBuiltin<"__builtin_lasx_xvilvl_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvilvh_b : ClangBuiltin<"__builtin_lasx_xvilvh_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvh_h : ClangBuiltin<"__builtin_lasx_xvilvh_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvh_w : ClangBuiltin<"__builtin_lasx_xvilvh_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvilvh_d : ClangBuiltin<"__builtin_lasx_xvilvh_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickev_b : ClangBuiltin<"__builtin_lasx_xvpickev_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickev_h : ClangBuiltin<"__builtin_lasx_xvpickev_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickev_w : ClangBuiltin<"__builtin_lasx_xvpickev_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickev_d : ClangBuiltin<"__builtin_lasx_xvpickev_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvand_v : ClangBuiltin<"__builtin_lasx_xvand_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvor_v : ClangBuiltin<"__builtin_lasx_xvor_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvbitrev_b : ClangBuiltin<"__builtin_lasx_xvbitrev_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrev_h : ClangBuiltin<"__builtin_lasx_xvbitrev_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrev_w : ClangBuiltin<"__builtin_lasx_xvbitrev_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvbitrev_d : ClangBuiltin<"__builtin_lasx_xvbitrev_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmod_bu : ClangBuiltin<"__builtin_lasx_xvmod_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_hu : ClangBuiltin<"__builtin_lasx_xvmod_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_wu : ClangBuiltin<"__builtin_lasx_xvmod_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmod_du : ClangBuiltin<"__builtin_lasx_xvmod_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickod_b : ClangBuiltin<"__builtin_lasx_xvpickod_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickod_h : ClangBuiltin<"__builtin_lasx_xvpickod_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickod_w : ClangBuiltin<"__builtin_lasx_xvpickod_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickod_d : ClangBuiltin<"__builtin_lasx_xvpickod_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvreplve_b : ClangBuiltin<"__builtin_lasx_xvreplve_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve_h : ClangBuiltin<"__builtin_lasx_xvreplve_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve_w : ClangBuiltin<"__builtin_lasx_xvreplve_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve_d : ClangBuiltin<"__builtin_lasx_xvreplve_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsra_b : ClangBuiltin<"__builtin_lasx_xvsra_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsra_h : ClangBuiltin<"__builtin_lasx_xvsra_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsra_w : ClangBuiltin<"__builtin_lasx_xvsra_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsra_d : ClangBuiltin<"__builtin_lasx_xvsra_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvxor_v : ClangBuiltin<"__builtin_lasx_xvxor_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvnor_v : ClangBuiltin<"__builtin_lasx_xvnor_v">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfadd_s : ClangBuiltin<"__builtin_lasx_xvfadd_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfadd_d : ClangBuiltin<"__builtin_lasx_xvfadd_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfsub_s : ClangBuiltin<"__builtin_lasx_xvfsub_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfsub_d : ClangBuiltin<"__builtin_lasx_xvfsub_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfmul_s : ClangBuiltin<"__builtin_lasx_xvfmul_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfmul_d : ClangBuiltin<"__builtin_lasx_xvfmul_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvshuf_h : ClangBuiltin<"__builtin_lasx_xvshuf_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvshuf_w : ClangBuiltin<"__builtin_lasx_xvshuf_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvshuf_d : ClangBuiltin<"__builtin_lasx_xvshuf_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvseqi_b : ClangBuiltin<"__builtin_lasx_xvseqi_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseqi_h : ClangBuiltin<"__builtin_lasx_xvseqi_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseqi_w : ClangBuiltin<"__builtin_lasx_xvseqi_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvseqi_d : ClangBuiltin<"__builtin_lasx_xvseqi_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslei_b : ClangBuiltin<"__builtin_lasx_xvslei_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_h : ClangBuiltin<"__builtin_lasx_xvslei_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_w : ClangBuiltin<"__builtin_lasx_xvslei_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_d : ClangBuiltin<"__builtin_lasx_xvslei_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslei_bu : ClangBuiltin<"__builtin_lasx_xvslei_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_hu : ClangBuiltin<"__builtin_lasx_xvslei_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_wu : ClangBuiltin<"__builtin_lasx_xvslei_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslei_du : ClangBuiltin<"__builtin_lasx_xvslei_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslti_b : ClangBuiltin<"__builtin_lasx_xvslti_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_h : ClangBuiltin<"__builtin_lasx_xvslti_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_w : ClangBuiltin<"__builtin_lasx_xvslti_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_d : ClangBuiltin<"__builtin_lasx_xvslti_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslti_bu : ClangBuiltin<"__builtin_lasx_xvslti_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_hu : ClangBuiltin<"__builtin_lasx_xvslti_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_wu : ClangBuiltin<"__builtin_lasx_xvslti_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslti_du : ClangBuiltin<"__builtin_lasx_xvslti_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvaddi_bu : ClangBuiltin<"__builtin_lasx_xvaddi_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvaddi_hu : ClangBuiltin<"__builtin_lasx_xvaddi_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvaddi_wu : ClangBuiltin<"__builtin_lasx_xvaddi_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+def int_loongarch_lasx_xvaddi_du : ClangBuiltin<"__builtin_lasx_xvaddi_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], -+ [Commutative, IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsubi_bu : ClangBuiltin<"__builtin_lasx_xvsubi_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubi_hu : ClangBuiltin<"__builtin_lasx_xvsubi_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubi_wu : ClangBuiltin<"__builtin_lasx_xvsubi_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsubi_du : ClangBuiltin<"__builtin_lasx_xvsubi_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaxi_b : ClangBuiltin<"__builtin_lasx_xvmaxi_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_h : ClangBuiltin<"__builtin_lasx_xvmaxi_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_w : ClangBuiltin<"__builtin_lasx_xvmaxi_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_d : ClangBuiltin<"__builtin_lasx_xvmaxi_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmini_b : ClangBuiltin<"__builtin_lasx_xvmini_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_h : ClangBuiltin<"__builtin_lasx_xvmini_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_w : ClangBuiltin<"__builtin_lasx_xvmini_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_d : ClangBuiltin<"__builtin_lasx_xvmini_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmaxi_bu : ClangBuiltin<"__builtin_lasx_xvmaxi_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_hu : ClangBuiltin<"__builtin_lasx_xvmaxi_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_wu : ClangBuiltin<"__builtin_lasx_xvmaxi_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmaxi_du : ClangBuiltin<"__builtin_lasx_xvmaxi_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvmini_bu : ClangBuiltin<"__builtin_lasx_xvmini_bu">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_hu : ClangBuiltin<"__builtin_lasx_xvmini_hu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_wu : ClangBuiltin<"__builtin_lasx_xvmini_wu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvmini_du : ClangBuiltin<"__builtin_lasx_xvmini_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvclz_b : ClangBuiltin<"__builtin_lasx_xvclz_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclz_h : ClangBuiltin<"__builtin_lasx_xvclz_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclz_w : ClangBuiltin<"__builtin_lasx_xvclz_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvclz_d : ClangBuiltin<"__builtin_lasx_xvclz_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpcnt_b : ClangBuiltin<"__builtin_lasx_xvpcnt_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpcnt_h : ClangBuiltin<"__builtin_lasx_xvpcnt_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpcnt_w : ClangBuiltin<"__builtin_lasx_xvpcnt_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpcnt_d : ClangBuiltin<"__builtin_lasx_xvpcnt_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfsqrt_s : ClangBuiltin<"__builtin_lasx_xvfsqrt_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfsqrt_d : ClangBuiltin<"__builtin_lasx_xvfsqrt_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfrint_s : ClangBuiltin<"__builtin_lasx_xvfrint_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfrint_d : ClangBuiltin<"__builtin_lasx_xvfrint_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvffint_s_w : ClangBuiltin<"__builtin_lasx_xvffint_s_w">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvffint_d_l : ClangBuiltin<"__builtin_lasx_xvffint_d_l">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvffint_s_wu : ClangBuiltin<"__builtin_lasx_xvffint_s_wu">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvffint_d_lu : ClangBuiltin<"__builtin_lasx_xvffint_d_lu">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvftintrz_wu_s : ClangBuiltin<"__builtin_lasx_xvftintrz_wu_s">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvftintrz_lu_d : ClangBuiltin<"__builtin_lasx_xvftintrz_lu_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvreplgr2vr_b : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplgr2vr_h : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplgr2vr_w : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplgr2vr_d : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvinsgr2vr_w : ClangBuiltin<"__builtin_lasx_xvinsgr2vr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+def int_loongarch_lasx_xvinsgr2vr_d : ClangBuiltin<"__builtin_lasx_xvinsgr2vr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i64_ty, llvm_i32_ty], -+ [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvfdiv_s : ClangBuiltin<"__builtin_lasx_xvfdiv_s">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvfdiv_d : ClangBuiltin<"__builtin_lasx_xvfdiv_d">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvslli_b : ClangBuiltin<"__builtin_lasx_xvslli_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslli_h : ClangBuiltin<"__builtin_lasx_xvslli_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslli_w : ClangBuiltin<"__builtin_lasx_xvslli_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvslli_d : ClangBuiltin<"__builtin_lasx_xvslli_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrli_b : ClangBuiltin<"__builtin_lasx_xvsrli_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrli_h : ClangBuiltin<"__builtin_lasx_xvsrli_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrli_w : ClangBuiltin<"__builtin_lasx_xvsrli_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrli_d : ClangBuiltin<"__builtin_lasx_xvsrli_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrai_b : ClangBuiltin<"__builtin_lasx_xvsrai_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrai_h : ClangBuiltin<"__builtin_lasx_xvsrai_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrai_w : ClangBuiltin<"__builtin_lasx_xvsrai_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrai_d : ClangBuiltin<"__builtin_lasx_xvsrai_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvshuf4i_b : ClangBuiltin<"__builtin_lasx_xvshuf4i_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvshuf4i_h : ClangBuiltin<"__builtin_lasx_xvshuf4i_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvshuf4i_w : ClangBuiltin<"__builtin_lasx_xvshuf4i_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvshuf4i_d : ClangBuiltin<"__builtin_lasx_xvshuf4i_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrotr_b : ClangBuiltin<"__builtin_lasx_xvrotr_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotr_h : ClangBuiltin<"__builtin_lasx_xvrotr_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotr_w : ClangBuiltin<"__builtin_lasx_xvrotr_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotr_d : ClangBuiltin<"__builtin_lasx_xvrotr_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvrotri_b : ClangBuiltin<"__builtin_lasx_xvrotri_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotri_h : ClangBuiltin<"__builtin_lasx_xvrotri_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotri_w : ClangBuiltin<"__builtin_lasx_xvrotri_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrotri_d : ClangBuiltin<"__builtin_lasx_xvrotri_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvld : ClangBuiltin<"__builtin_lasx_xvld">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i32_ty], -+ [IntrReadMem, IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvst : ClangBuiltin<"__builtin_lasx_xvst">, -+ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i32_ty], -+ [IntrArgMemOnly]>; -+ -+def int_loongarch_lasx_xvrepl128vei_b : ClangBuiltin<"__builtin_lasx_xvrepl128vei_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrepl128vei_h : ClangBuiltin<"__builtin_lasx_xvrepl128vei_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrepl128vei_w : ClangBuiltin<"__builtin_lasx_xvrepl128vei_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvrepl128vei_d : ClangBuiltin<"__builtin_lasx_xvrepl128vei_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvinsve0_w : ClangBuiltin<"__builtin_lasx_xvinsve0_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvinsve0_d : ClangBuiltin<"__builtin_lasx_xvinsve0_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickve_w : ClangBuiltin<"__builtin_lasx_xvpickve_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickve_d : ClangBuiltin<"__builtin_lasx_xvpickve_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpickve_w_f : ClangBuiltin<"__builtin_lasx_xvpickve_w_f">, -+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpickve_d_f : ClangBuiltin<"__builtin_lasx_xvpickve_d_f">, -+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvreplve0_b : ClangBuiltin<"__builtin_lasx_xvreplve0_b">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve0_h : ClangBuiltin<"__builtin_lasx_xvreplve0_h">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve0_w : ClangBuiltin<"__builtin_lasx_xvreplve0_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve0_d : ClangBuiltin<"__builtin_lasx_xvreplve0_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvreplve0_q : ClangBuiltin<"__builtin_lasx_xvreplve0_q">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_vext2xv_d_w : ClangBuiltin<"__builtin_lasx_vext2xv_d_w">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_w_h : ClangBuiltin<"__builtin_lasx_vext2xv_w_h">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_h_b : ClangBuiltin<"__builtin_lasx_vext2xv_h_b">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_vext2xv_d_h : ClangBuiltin<"__builtin_lasx_vext2xv_d_h">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_w_b : ClangBuiltin<"__builtin_lasx_vext2xv_w_b">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_d_b : ClangBuiltin<"__builtin_lasx_vext2xv_d_b">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_vext2xv_du_wu : ClangBuiltin<"__builtin_lasx_vext2xv_du_wu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_wu_hu : ClangBuiltin<"__builtin_lasx_vext2xv_wu_hu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_hu_bu : ClangBuiltin<"__builtin_lasx_vext2xv_hu_bu">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_vext2xv_du_hu : ClangBuiltin<"__builtin_lasx_vext2xv_du_hu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_wu_bu : ClangBuiltin<"__builtin_lasx_vext2xv_wu_bu">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_vext2xv_du_bu : ClangBuiltin<"__builtin_lasx_vext2xv_du_bu">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvpermi_q : ClangBuiltin<"__builtin_lasx_xvpermi_q">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvpermi_d : ClangBuiltin<"__builtin_lasx_xvpermi_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvperm_w : ClangBuiltin<"__builtin_lasx_xvperm_w">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvsrlrni_b_h : ClangBuiltin<"__builtin_lasx_xvsrlrni_b_h">, -+ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlrni_h_w : ClangBuiltin<"__builtin_lasx_xvsrlrni_h_w">, -+ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlrni_w_d : ClangBuiltin<"__builtin_lasx_xvsrlrni_w_d">, -+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvsrlrni_d_q : ClangBuiltin<"__builtin_lasx_xvsrlrni_d_q">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xbz_v : ClangBuiltin<"__builtin_lasx_xbz_v">, -+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xbnz_v : ClangBuiltin<"__builtin_lasx_xbnz_v">, -+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xbz_b : ClangBuiltin<"__builtin_lasx_xbz_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbz_h : ClangBuiltin<"__builtin_lasx_xbz_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbz_w : ClangBuiltin<"__builtin_lasx_xbz_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbz_d : ClangBuiltin<"__builtin_lasx_xbz_d">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xbnz_b : ClangBuiltin<"__builtin_lasx_xbnz_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbnz_h : ClangBuiltin<"__builtin_lasx_xbnz_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbnz_w : ClangBuiltin<"__builtin_lasx_xbnz_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xbnz_d : ClangBuiltin<"__builtin_lasx_xbnz_d">, -+ Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+def int_loongarch_lasx_xvextl_q_d : ClangBuiltin<"__builtin_lasx_xvextl_q_d">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+def int_loongarch_lasx_xvextl_qu_du : ClangBuiltin<"__builtin_lasx_xvextl_qu_du">, -+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; -+ -+//===----------------------------------------------------------------------===// -+// LoongArch BASE -+ -+def int_loongarch_cpucfg : ClangBuiltin<"__builtin_loongarch_cpucfg">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_csrrd_w : ClangBuiltin<"__builtin_loongarch_csrrd_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_csrrd_d : ClangBuiltin<"__builtin_loongarch_csrrd_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty], []>; -+ -+def int_loongarch_csrwr_w : ClangBuiltin<"__builtin_loongarch_csrwr_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_csrwr_d : ClangBuiltin<"__builtin_loongarch_csrwr_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], []>; -+ -+def int_loongarch_csrxchg_w : ClangBuiltin<"__builtin_loongarch_csrxchg_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_csrxchg_d : ClangBuiltin<"__builtin_loongarch_csrxchg_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], []>; -+ -+def int_loongarch_iocsrrd_b : ClangBuiltin<"__builtin_loongarch_iocsrrd_b">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrrd_h : ClangBuiltin<"__builtin_loongarch_iocsrrd_h">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrrd_w : ClangBuiltin<"__builtin_loongarch_iocsrrd_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrrd_d : ClangBuiltin<"__builtin_loongarch_iocsrrd_d">, -+ Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrwr_b : ClangBuiltin<"__builtin_loongarch_iocsrwr_b">, -+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrwr_h : ClangBuiltin<"__builtin_loongarch_iocsrwr_h">, -+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrwr_w : ClangBuiltin<"__builtin_loongarch_iocsrwr_w">, -+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_iocsrwr_d : ClangBuiltin<"__builtin_loongarch_iocsrwr_d">, -+ Intrinsic<[], [llvm_i64_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_cacop_w : ClangBuiltin<"__builtin_loongarch_cacop_w">, -+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_cacop_d : ClangBuiltin<"__builtin_loongarch_cacop_d">, -+ Intrinsic<[], [llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], []>; -+ -+def int_loongarch_crc_w_b_w : ClangBuiltin<"__builtin_loongarch_crc_w_b_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crc_w_h_w : ClangBuiltin<"__builtin_loongarch_crc_w_h_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crc_w_w_w : ClangBuiltin<"__builtin_loongarch_crc_w_w_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crc_w_d_w : ClangBuiltin<"__builtin_loongarch_crc_w_d_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crcc_w_b_w : ClangBuiltin<"__builtin_loongarch_crcc_w_b_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crcc_w_h_w : ClangBuiltin<"__builtin_loongarch_crcc_w_h_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crcc_w_w_w : ClangBuiltin<"__builtin_loongarch_crcc_w_w_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_crcc_w_d_w : ClangBuiltin<"__builtin_loongarch_crcc_w_d_w">, -+ Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; -+ -+def int_loongarch_tlbclr : ClangBuiltin<"__builtin_loongarch_tlbclr">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_tlbflush : ClangBuiltin<"__builtin_loongarch_tlbflush">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_tlbfill : ClangBuiltin<"__builtin_loongarch_tlbfill">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_tlbrd : ClangBuiltin<"__builtin_loongarch_tlbrd">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_tlbwr : ClangBuiltin<"__builtin_loongarch_tlbwr">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_tlbsrch : ClangBuiltin<"__builtin_loongarch_tlbsrch">, -+ Intrinsic<[], [], []>; -+ -+def int_loongarch_syscall : ClangBuiltin<"__builtin_loongarch_syscall">, -+ Intrinsic<[], [llvm_i64_ty], []>; -+ -+def int_loongarch_break : ClangBuiltin<"__builtin_loongarch_break">, -+ Intrinsic<[], [llvm_i64_ty], []>; -+ -+def int_loongarch_asrtle_d : ClangBuiltin<"__builtin_loongarch_asrtle_d">, -+ Intrinsic<[], [llvm_i64_ty, llvm_i64_ty], []>; -+ -+def int_loongarch_asrtgt_d : ClangBuiltin<"__builtin_loongarch_asrtgt_d">, -+ Intrinsic<[], [llvm_i64_ty, llvm_i64_ty], []>; -+ -+def int_loongarch_dbar : ClangBuiltin<"__builtin_loongarch_dbar">, -+ Intrinsic<[], [llvm_i64_ty], []>; -+ -+def int_loongarch_ibar : ClangBuiltin<"__builtin_loongarch_ibar">, -+ Intrinsic<[], [llvm_i64_ty], []>; -+ -+} -diff --git a/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp b/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp -index 2958a5054..c784c27d3 100644 ---- a/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp -+++ b/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp -@@ -5917,8 +5917,13 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { - if (const SCEV *S = createNodeFromSelectLikePHI(PN)) - return S; - -+ // If the PHI has a single incoming value, follow that value, unless the -+ // PHI's incoming blocks are in a different loop, in which case doing so -+ // risks breaking LCSSA form. Instcombine would normally zap these, but -+ // it doesn't have DominatorTree information, so it may miss cases. - if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC})) -- return getSCEV(V); -+ if (LI.replacementPreservesLCSSAForm(PN, V)) -+ return getSCEV(V); - - // If it's not a loop phi, we can't handle it yet. - return getUnknown(PN); -diff --git a/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp b/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp -index c4795a80e..bc20f33f1 100644 ---- a/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp -+++ b/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp -@@ -1110,6 +1110,12 @@ void InterleavedAccessInfo::collectConstStrideAccesses( - continue; - Type *ElementTy = getLoadStoreType(&I); - -+ // Currently, codegen doesn't support cases where the type size doesn't -+ // match the alloc size. Skip them for now. -+ uint64_t Size = DL.getTypeAllocSize(ElementTy); -+ if (Size * 8 != DL.getTypeSizeInBits(ElementTy)) -+ continue; -+ - // We don't check wrapping here because we don't know yet if Ptr will be - // part of a full group or a group with gaps. Checking wrapping for all - // pointers (even those that end up in groups with no gaps) will be overly -@@ -1121,7 +1127,6 @@ void InterleavedAccessInfo::collectConstStrideAccesses( - /*Assume=*/true, /*ShouldCheckWrap=*/false); - - const SCEV *Scev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); -- uint64_t Size = DL.getTypeAllocSize(ElementTy); - AccessStrideInfo[&I] = StrideDescriptor(Stride, Scev, Size, - getLoadStoreAlignment(&I)); - } -diff --git a/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp -index 85d051cfd..a8d40edd8 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp -@@ -1237,7 +1237,13 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) { - if (!MO.isReg()) - continue; - -- for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(MO.getReg())) -+ MCRegister Reg = MO.getReg(); -+ -+ // This picks up sibling registers (e.q. %al -> %ah). -+ for (MCRegUnitIterator Unit(Reg, &TRI); Unit.isValid(); ++Unit) -+ RegsToZero.reset(*Unit); -+ -+ for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(Reg)) - RegsToZero.reset(SReg); - } - } -diff --git a/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp b/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp -index 9e4e26f13..cb552f212 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp -@@ -443,6 +443,9 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg, - SpilledOperandsMap[MO->getParent()].push_back(MO); - for (auto MISpilledOperands : SpilledOperandsMap) { - MachineInstr &DBG = *MISpilledOperands.first; -+ // We don't have enough support for tracking operands of DBG_VALUE_LISTs. -+ if (DBG.isDebugValueList()) -+ continue; - MachineInstr *NewDV = buildDbgValueForSpill( - *MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second); - assert(NewDV->getParent() == MBB && "dangling parent pointer"); -diff --git a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp -index 3d3b504c6..96cfe1fc0 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp -@@ -701,6 +701,9 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD, - MIB.addMetadata(Var); - MIB.addMetadata(Expr); - AddDbgValueLocationOps(MIB, DbgValDesc, LocationOps, VRBaseMap); -+ // FIXME: Fix rustc build error with lto=thin option on loongarch. -+ if (MF->getTarget().getTargetTriple().isLoongArch()) -+ return nullptr; - return &*MIB; - } - -diff --git a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -index 35650b9bd..ecdaef044 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp -@@ -9693,6 +9693,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { - Entry.Alignment = Alignment; - CLI.getArgs().insert(CLI.getArgs().begin(), Entry); - CLI.NumFixedArgs += 1; -+ CLI.getArgs()[0].IndirectType = CLI.RetTy; - CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext()); - - // sret demotion isn't compatible with tail-calls, since the sret argument -diff --git a/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp -index 2badbe34a..88b8d1cf3 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp -@@ -207,6 +207,16 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, - PersonalityEncoding = dwarf::DW_EH_PE_absptr; - TTypeEncoding = dwarf::DW_EH_PE_absptr; - break; -+ case Triple::loongarch32: -+ case Triple::loongarch64: -+ PersonalityEncoding = dwarf::DW_EH_PE_indirect; -+ -+ // Note: gas does not support pc-relative LSDA references. -+ LSDAEncoding = dwarf::DW_EH_PE_absptr; -+ -+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | -+ dwarf::DW_EH_PE_sdata4; -+ break; - case Triple::mips: - case Triple::mipsel: - case Triple::mips64: -diff --git a/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp b/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp -index 8dc8d381a..36e3c1245 100644 ---- a/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp -+++ b/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp -@@ -569,7 +569,7 @@ void IRPromoter::TruncateSinks() { - void IRPromoter::Cleanup() { - LLVM_DEBUG(dbgs() << "IR Promotion: Cleanup..\n"); - // Some zexts will now have become redundant, along with their trunc -- // operands, so remove them -+ // operands, so remove them. - for (auto *V : Visited) { - if (!isa(V)) - continue; -@@ -620,6 +620,8 @@ void IRPromoter::ConvertTruncs() { - ConstantInt *Mask = - ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue()); - Value *Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask); -+ if (SrcTy != ExtTy) -+ Masked = Builder.CreateTrunc(Masked, ExtTy); - - if (auto *I = dyn_cast(Masked)) - NewInsts.insert(I); -diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp -index aec42d295..2be2a12aa 100644 ---- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp -+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp -@@ -413,12 +413,12 @@ unsigned DWARFVerifier::verifyIndex(StringRef Name, - uint64_t Sig = E.getSignature(); - if (!E.getContributions()) - continue; -- for (auto P : enumerate(InfoColumnKind == DW_SECT_INFO -+ for (auto E : enumerate(InfoColumnKind == DW_SECT_INFO - ? makeArrayRef(E.getContributions(), - Index.getColumnKinds().size()) - : makeArrayRef(E.getContribution(), 1))) { -- const DWARFUnitIndex::Entry::SectionContribution &SC = P.value(); -- int Col = P.index(); -+ const DWARFUnitIndex::Entry::SectionContribution &SC = E.value(); -+ int Col = E.index(); - if (SC.Length == 0) - continue; - if (!Sections[Col]) -diff --git a/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp b/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp -index 75594f90c..b9962da1d 100644 ---- a/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp -+++ b/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp -@@ -1040,7 +1040,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { - Name, F->getParent()); - - // The new function may also need remangling. -- if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F)) -+ if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn)) - NewFn = *Result; - return true; - } -diff --git a/src/llvm-project/llvm/lib/IR/Function.cpp b/src/llvm-project/llvm/lib/IR/Function.cpp -index d41381337..3ef27601f 100644 ---- a/src/llvm-project/llvm/lib/IR/Function.cpp -+++ b/src/llvm-project/llvm/lib/IR/Function.cpp -@@ -38,6 +38,7 @@ - #include "llvm/IR/IntrinsicsBPF.h" - #include "llvm/IR/IntrinsicsDirectX.h" - #include "llvm/IR/IntrinsicsHexagon.h" -+#include "llvm/IR/IntrinsicsLoongArch.h" - #include "llvm/IR/IntrinsicsMips.h" - #include "llvm/IR/IntrinsicsNVPTX.h" - #include "llvm/IR/IntrinsicsPowerPC.h" -diff --git a/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp b/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp -index d6fe952c0..254c2fa60 100644 ---- a/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp -+++ b/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp -@@ -332,6 +332,12 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { - - void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { - switch (T.getArch()) { -+ case Triple::loongarch32: -+ case Triple::loongarch64: -+ FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4 -+ ? dwarf::DW_EH_PE_sdata4 -+ : dwarf::DW_EH_PE_sdata8; -+ break; - case Triple::mips: - case Triple::mipsel: - case Triple::mips64: -diff --git a/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp -index e14301663..ec54d7b59 100644 ---- a/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp -+++ b/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp -@@ -511,6 +511,28 @@ static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S, - } - } - -+static bool supportsLoongArch(uint64_t Type) { -+ switch (Type) { -+ case ELF::R_LARCH_32: -+ case ELF::R_LARCH_64: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S, -+ uint64_t LocData, int64_t Addend) { -+ switch (Type) { -+ case ELF::R_LARCH_32: -+ return (S + Addend) & 0xFFFFFFFF; -+ case ELF::R_LARCH_64: -+ return S + Addend; -+ default: -+ llvm_unreachable("Invalid relocation type"); -+ } -+} -+ - static bool supportsCOFFX86(uint64_t Type) { - switch (Type) { - case COFF::IMAGE_REL_I386_SECREL: -@@ -725,6 +747,8 @@ getRelocationResolver(const ObjectFile &Obj) { - return {supportsAmdgpu, resolveAmdgpu}; - case Triple::riscv64: - return {supportsRISCV, resolveRISCV}; -+ case Triple::loongarch64: -+ return {supportsLoongArch, resolveLoongArch}; - default: - return {nullptr, nullptr}; - } -@@ -760,6 +784,8 @@ getRelocationResolver(const ObjectFile &Obj) { - return {supportsRISCV, resolveRISCV}; - case Triple::csky: - return {supportsCSKY, resolveCSKY}; -+ case Triple::loongarch32: -+ return {supportsLoongArch, resolveLoongArch}; - default: - return {nullptr, nullptr}; - } -diff --git a/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp b/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp -index 9ad2c4135..b778006cf 100644 ---- a/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp -+++ b/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp -@@ -518,14 +518,6 @@ void ScalarBitSetTraits::bitset(IO &IO, - BCaseMask(EF_AVR_ARCH_XMEGA7, EF_AVR_ARCH_MASK); - BCase(EF_AVR_LINKRELAX_PREPARED); - break; -- case ELF::EM_LOONGARCH: -- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32S, EF_LOONGARCH_BASE_ABI_MASK); -- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32F, EF_LOONGARCH_BASE_ABI_MASK); -- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32D, EF_LOONGARCH_BASE_ABI_MASK); -- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64S, EF_LOONGARCH_BASE_ABI_MASK); -- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64F, EF_LOONGARCH_BASE_ABI_MASK); -- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64D, EF_LOONGARCH_BASE_ABI_MASK); -- break; - case ELF::EM_RISCV: - BCase(EF_RISCV_RVC); - BCaseMask(EF_RISCV_FLOAT_ABI_SOFT, EF_RISCV_FLOAT_ABI); -diff --git a/src/llvm-project/llvm/lib/Support/CMakeLists.txt b/src/llvm-project/llvm/lib/Support/CMakeLists.txt -index 5044b2639..ff23ec74d 100644 ---- a/src/llvm-project/llvm/lib/Support/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Support/CMakeLists.txt -@@ -22,11 +22,19 @@ if (HAS_WERROR_GLOBAL_CTORS) - endif() - - if(LLVM_ENABLE_ZLIB) -- set(imported_libs ZLIB::ZLIB) -+ list(APPEND imported_libs ZLIB::ZLIB) - endif() - - if(LLVM_ENABLE_ZSTD) -- list(APPEND imported_libs zstd::libzstd_shared) -+ if(TARGET zstd::libzstd_shared AND NOT LLVM_USE_STATIC_ZSTD) -+ set(zstd_target zstd::libzstd_shared) -+ else() -+ set(zstd_target zstd::libzstd_static) -+ endif() -+endif() -+ -+if(LLVM_ENABLE_ZSTD) -+ list(APPEND imported_libs ${zstd_target}) - endif() - - if( MSVC OR MINGW ) -@@ -51,9 +59,7 @@ elseif( CMAKE_HOST_UNIX ) - if( LLVM_ENABLE_TERMINFO ) - set(imported_libs ${imported_libs} Terminfo::terminfo) - endif() -- if( LLVM_ENABLE_THREADS AND (HAVE_LIBATOMIC OR HAVE_CXX_LIBATOMICS64) ) -- set(system_libs ${system_libs} atomic) -- endif() -+ set(system_libs ${system_libs} ${LLVM_ATOMIC_LIB}) - set(system_libs ${system_libs} ${LLVM_PTHREAD_LIB}) - if( UNIX AND NOT (BEOS OR HAIKU) ) - set(system_libs ${system_libs} m) -@@ -300,11 +306,12 @@ if(LLVM_ENABLE_ZSTD) - # CMAKE_BUILD_TYPE is only meaningful to single-configuration generators. - if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} build_type) -- get_property(zstd_library TARGET zstd::libzstd_shared PROPERTY LOCATION_${build_type}) -+ get_property(zstd_library TARGET ${zstd_target} PROPERTY LOCATION_${build_type}) - endif() - if(NOT zstd_library) -- get_property(zstd_library TARGET zstd::libzstd_shared PROPERTY LOCATION) -+ get_property(zstd_library TARGET ${zstd_target} PROPERTY LOCATION) - endif() -+ get_library_name(${zstd_library} zstd_library) - set(llvm_system_libs ${llvm_system_libs} "${zstd_library}") - endif() - -diff --git a/src/llvm-project/llvm/lib/Support/Triple.cpp b/src/llvm-project/llvm/lib/Support/Triple.cpp -index 6696d158b..2c07c1a29 100644 ---- a/src/llvm-project/llvm/lib/Support/Triple.cpp -+++ b/src/llvm-project/llvm/lib/Support/Triple.cpp -@@ -257,6 +257,7 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { - case GNU: return "gnu"; - case GNUABI64: return "gnuabi64"; - case GNUABIN32: return "gnuabin32"; -+ case GNUABILPX32: return "gnuabilpx32"; - case GNUEABI: return "gnueabi"; - case GNUEABIHF: return "gnueabihf"; - case GNUX32: return "gnux32"; -diff --git a/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp b/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp -index 194e8d88a..1e8aebf1b 100644 ---- a/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp -+++ b/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp -@@ -499,8 +499,8 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { - // Filling (and overriding) the matrix for the name fragment of each node - // iteratively. CompleteName is used to collect the actual name of potential - // match, respecting case and spacing. -- std::function VisitNode; -- VisitNode = [&](const Node &N, std::size_t Row) -> void { -+ auto VisitNode = [&](const Node &N, std::size_t Row, -+ auto &VisitNode) -> void { - std::size_t J = 0; - for (; J < N.Name.size(); J++) { - if (!isAlnum(N.Name[J])) -@@ -533,7 +533,7 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { - ChildOffset += C.Size; - if (!C.isValid()) - break; -- VisitNode(C, Row); -+ VisitNode(C, Row, VisitNode); - if (!C.HasSibling) - break; - } -@@ -541,7 +541,7 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { - }; - - Node Root = createRoot(); -- VisitNode(Root, 1); -+ VisitNode(Root, 1, VisitNode); - return Matches; - } - -diff --git a/src/llvm-project/llvm/lib/Support/Unix/Path.inc b/src/llvm-project/llvm/lib/Support/Unix/Path.inc -index 6f85ee0db..2ae7c6dc4 100644 ---- a/src/llvm-project/llvm/lib/Support/Unix/Path.inc -+++ b/src/llvm-project/llvm/lib/Support/Unix/Path.inc -@@ -1476,7 +1476,7 @@ namespace fs { - std::error_code copy_file(const Twine &From, const Twine &To) { - std::string FromS = From.str(); - std::string ToS = To.str(); --#if 0 && __has_builtin(__builtin_available) -+#if __has_builtin(__builtin_available) - if (__builtin_available(macos 10.12, *)) { - // Optimistically try to use clonefile() and handle errors, rather than - // calling stat() to see if it'll work. -diff --git a/src/llvm-project/llvm/lib/Support/Unix/Signals.inc b/src/llvm-project/llvm/lib/Support/Unix/Signals.inc -index bf145bffe..23ac012b9 100644 ---- a/src/llvm-project/llvm/lib/Support/Unix/Signals.inc -+++ b/src/llvm-project/llvm/lib/Support/Unix/Signals.inc -@@ -432,10 +432,6 @@ void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { - } - - void llvm::sys::DefaultOneShotPipeSignalHandler() { -- // UNIX03 conformance requires a non-zero exit code and an error message -- // to stderr when writing to a closed stdout fails. -- errs() << "error: write on a pipe with no reader\n"; -- - // Send a special return code that drivers can check for, from sysexits.h. - exit(EX_IOERR); - } -diff --git a/src/llvm-project/llvm/lib/Support/Windows/Threading.inc b/src/llvm-project/llvm/lib/Support/Windows/Threading.inc -index ed4b0d316..11f34817d 100644 ---- a/src/llvm-project/llvm/lib/Support/Windows/Threading.inc -+++ b/src/llvm-project/llvm/lib/Support/Windows/Threading.inc -@@ -144,11 +144,6 @@ struct ProcessorGroup { - - template - static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship, F Fn) { --#if !defined(_WIN64) && defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 7 -- // `GetLogicalProcessorInformationEx@12` was only added to i386 mingw-w64 in v7.0.0 -- // https://github.com/mingw-w64/mingw-w64/commit/24842d45e025db0d38fa2bbd932b95a83282efa2#diff-faf1d8a1556e75a84b7cef2e89512e79R634 -- return false; --#else - DWORD Len = 0; - BOOL R = ::GetLogicalProcessorInformationEx(Relationship, NULL, &Len); - if (R || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { -@@ -169,7 +164,6 @@ static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship, F Fn) { - } - free(Info); - return true; --#endif - } - - static ArrayRef getProcessorGroups() { -diff --git a/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp b/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp -index 2567f3ed8..0daaa6d81 100644 ---- a/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp -+++ b/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp -@@ -203,10 +203,10 @@ constexpr FeatureBitset FeaturesTigerlake = - FeatureCLWB | FeatureMOVDIRI | FeatureSHSTK | FeatureKL | FeatureWIDEKL; - constexpr FeatureBitset FeaturesSapphireRapids = - FeaturesICLServer | FeatureAMX_BF16 | FeatureAMX_INT8 | FeatureAMX_TILE | -- FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVX512VP2INTERSECT | -- FeatureAVXVNNI | FeatureCLDEMOTE | FeatureENQCMD | FeatureMOVDIR64B | -- FeatureMOVDIRI | FeaturePTWRITE | FeatureSERIALIZE | FeatureSHSTK | -- FeatureTSXLDTRK | FeatureUINTR | FeatureWAITPKG; -+ FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVXVNNI | FeatureCLDEMOTE | -+ FeatureENQCMD | FeatureMOVDIR64B | FeatureMOVDIRI | FeaturePTWRITE | -+ FeatureSERIALIZE | FeatureSHSTK | FeatureTSXLDTRK | FeatureUINTR | -+ FeatureWAITPKG; - - // Intel Atom processors. - // Bonnell has feature parity with Core2 and adds MOVBE. -@@ -367,7 +367,7 @@ constexpr ProcInfo Processors[] = { - // Tigerlake microarchitecture based processors. - { {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, FeaturesTigerlake }, - // Sapphire Rapids microarchitecture based processors. -- { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512VP2INTERSECT, FeaturesSapphireRapids }, -+ { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512BF16, FeaturesSapphireRapids }, - // Alderlake microarchitecture based processors. - { {"alderlake"}, CK_Alderlake, FEATURE_AVX2, FeaturesAlderlake }, - // Knights Landing processor. -diff --git a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -index c28216048..06e21f90e 100644 ---- a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -+++ b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -@@ -5805,7 +5805,7 @@ SDValue AArch64TargetLowering::LowerFormalArguments( - assert(!Res && "Call operand has unhandled type"); - (void)Res; - } -- SmallVector ArgValues; -+ - unsigned ExtraArgLocs = 0; - for (unsigned i = 0, e = Ins.size(); i != e; ++i) { - CCValAssign &VA = ArgLocs[i - ExtraArgLocs]; -@@ -6157,17 +6157,10 @@ void AArch64TargetLowering::saveVarArgRegisters(CCState &CCInfo, - /// appropriate copies out of appropriate physical registers. - SDValue AArch64TargetLowering::LowerCallResult( - SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, -- const SmallVectorImpl &Ins, const SDLoc &DL, -+ const SmallVectorImpl &RVLocs, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl &InVals, bool isThisReturn, - SDValue ThisVal) const { -- CCAssignFn *RetCC = CCAssignFnForReturn(CallConv); -- // Assign locations to each value returned by this call. -- SmallVector RVLocs; - DenseMap CopiedRegs; -- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, -- *DAG.getContext()); -- CCInfo.AnalyzeCallResult(Ins, RetCC); -- - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign VA = RVLocs[i]; -@@ -6508,17 +6501,39 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, - GuardWithBTI = FuncInfo->branchTargetEnforcement(); - } - -+ // Analyze operands of the call, assigning locations to each operand. -+ SmallVector ArgLocs; -+ CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); -+ -+ if (IsVarArg) { -+ unsigned NumArgs = Outs.size(); -+ -+ for (unsigned i = 0; i != NumArgs; ++i) { -+ if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector()) -+ report_fatal_error("Passing SVE types to variadic functions is " -+ "currently not supported"); -+ } -+ } -+ -+ analyzeCallOperands(*this, Subtarget, CLI, CCInfo); -+ -+ CCAssignFn *RetCC = CCAssignFnForReturn(CallConv); -+ // Assign locations to each value returned by this call. -+ SmallVector RVLocs; -+ CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, -+ *DAG.getContext()); -+ RetCCInfo.AnalyzeCallResult(Ins, RetCC); -+ - // Check callee args/returns for SVE registers and set calling convention - // accordingly. - if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) { -- bool CalleeOutSVE = any_of(Outs, [](ISD::OutputArg &Out){ -- return Out.VT.isScalableVector(); -- }); -- bool CalleeInSVE = any_of(Ins, [](ISD::InputArg &In){ -- return In.VT.isScalableVector(); -- }); -- -- if (CalleeInSVE || CalleeOutSVE) -+ auto HasSVERegLoc = [](CCValAssign &Loc) { -+ if (!Loc.isRegLoc()) -+ return false; -+ return AArch64::ZPRRegClass.contains(Loc.getLocReg()) || -+ AArch64::PPRRegClass.contains(Loc.getLocReg()); -+ }; -+ if (any_of(RVLocs, HasSVERegLoc) || any_of(ArgLocs, HasSVERegLoc)) - CallConv = CallingConv::AArch64_SVE_VectorCall; - } - -@@ -6540,22 +6555,6 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, - report_fatal_error("failed to perform tail call elimination on a call " - "site marked musttail"); - -- // Analyze operands of the call, assigning locations to each operand. -- SmallVector ArgLocs; -- CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); -- -- if (IsVarArg) { -- unsigned NumArgs = Outs.size(); -- -- for (unsigned i = 0; i != NumArgs; ++i) { -- if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector()) -- report_fatal_error("Passing SVE types to variadic functions is " -- "currently not supported"); -- } -- } -- -- analyzeCallOperands(*this, Subtarget, CLI, CCInfo); -- - // Get a count of how many bytes are to be pushed on the stack. - unsigned NumBytes = CCInfo.getNextStackOffset(); - -@@ -6961,7 +6960,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, - - // Handle result values, copying them out of physregs into vregs that we - // return. -- return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, -+ return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, RVLocs, DL, DAG, - InVals, IsThisReturn, - IsThisReturn ? OutVals[0] : SDValue()); - } -diff --git a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h -index 1ba2e2f31..ff3bfe897 100644 ---- a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h -+++ b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h -@@ -894,7 +894,7 @@ private: - - SDValue LowerCallResult(SDValue Chain, SDValue InFlag, - CallingConv::ID CallConv, bool isVarArg, -- const SmallVectorImpl &Ins, -+ const SmallVectorImpl &RVLocs, - const SDLoc &DL, SelectionDAG &DAG, - SmallVectorImpl &InVals, bool isThisReturn, - SDValue ThisVal) const; -diff --git a/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp -index f7d139adc..f6b7d1ffc 100644 ---- a/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp -+++ b/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp -@@ -249,6 +249,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, - case ISD::STORE: - case ISD::BUILD_VECTOR: - case ISD::BITCAST: -+ case ISD::UNDEF: - case ISD::EXTRACT_VECTOR_ELT: - case ISD::INSERT_VECTOR_ELT: - case ISD::EXTRACT_SUBVECTOR: -@@ -516,6 +517,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, - case ISD::STORE: - case ISD::BUILD_VECTOR: - case ISD::BITCAST: -+ case ISD::UNDEF: - case ISD::EXTRACT_VECTOR_ELT: - case ISD::INSERT_VECTOR_ELT: - case ISD::INSERT_SUBVECTOR: -diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp -index 3c102463b..cbfd2bc68 100644 ---- a/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp -+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp -@@ -1036,7 +1036,7 @@ InstructionCost ARMTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - // split, we may need an expensive shuffle to get two in sync. This has the - // effect of making larger than legal compares (v8i32 for example) - // expensive. -- if (LT.second.getVectorNumElements() > 2) { -+ if (LT.second.isVector() && LT.second.getVectorNumElements() > 2) { - if (LT.first > 1) - return LT.first * BaseCost + - BaseT::getScalarizationOverhead(VecCondTy, true, false); -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt -index 296160531..cb8b768d5 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt -@@ -2,10 +2,10 @@ add_llvm_component_library(LLVMLoongArchAsmParser - LoongArchAsmParser.cpp - - LINK_COMPONENTS -- LoongArchDesc -- LoongArchInfo - MC - MCParser -+ LoongArchDesc -+ LoongArchInfo - Support - - ADD_TO_COMPONENT -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp -index 9793c7bc3..2d35dfd0c 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp -@@ -1,4 +1,4 @@ --// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=// -+//===-- LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions ----===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,551 +6,2278 @@ - // - //===----------------------------------------------------------------------===// - --#include "MCTargetDesc/LoongArchInstPrinter.h" -+#include "LoongArchTargetStreamer.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" - #include "MCTargetDesc/LoongArchMCTargetDesc.h" - #include "TargetInfo/LoongArchTargetInfo.h" -+#include "llvm/ADT/APFloat.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/ADT/SmallVector.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/ADT/StringSwitch.h" -+#include "llvm/ADT/Triple.h" -+#include "llvm/ADT/Twine.h" -+#include "llvm/BinaryFormat/ELF.h" - #include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/MC/MCInst.h" -+#include "llvm/MC/MCInstrDesc.h" - #include "llvm/MC/MCInstrInfo.h" -+#include "llvm/MC/MCObjectFileInfo.h" - #include "llvm/MC/MCParser/MCAsmLexer.h" -+#include "llvm/MC/MCParser/MCAsmParser.h" -+#include "llvm/MC/MCParser/MCAsmParserExtension.h" - #include "llvm/MC/MCParser/MCParsedAsmOperand.h" - #include "llvm/MC/MCParser/MCTargetAsmParser.h" --#include "llvm/MC/MCRegisterInfo.h" -+#include "llvm/MC/MCSectionELF.h" - #include "llvm/MC/MCStreamer.h" - #include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/MC/MCSymbol.h" -+#include "llvm/MC/MCSymbolELF.h" -+#include "llvm/MC/MCValue.h" -+#include "llvm/MC/SubtargetFeature.h" - #include "llvm/MC/TargetRegistry.h" - #include "llvm/Support/Casting.h" -+#include "llvm/Support/CommandLine.h" -+#include "llvm/Support/Compiler.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Support/SMLoc.h" -+#include "llvm/Support/SourceMgr.h" -+#include "llvm/Support/raw_ostream.h" -+#include -+#include -+#include -+#include -+#include -+#include - - using namespace llvm; - - #define DEBUG_TYPE "loongarch-asm-parser" - -+namespace llvm { -+ -+class MCInstrInfo; -+ -+} // end namespace llvm -+ -+namespace { -+ -+class LoongArchAssemblerOptions { -+public: -+ LoongArchAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {} -+ -+ LoongArchAssemblerOptions(const LoongArchAssemblerOptions *Opts) { -+ Features = Opts->getFeatures(); -+ } -+ -+ const FeatureBitset &getFeatures() const { return Features; } -+ void setFeatures(const FeatureBitset &Features_) { Features = Features_; } -+ -+private: -+ FeatureBitset Features; -+}; -+ -+} // end anonymous namespace -+ - namespace { -+ - class LoongArchAsmParser : public MCTargetAsmParser { -- SMLoc getLoc() const { return getParser().getTok().getLoc(); } -+ LoongArchTargetStreamer &getTargetStreamer() { -+ MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); -+ return static_cast(TS); -+ } -+ -+ LoongArchABIInfo ABI; -+ SmallVector, 2> AssemblerOptions; -+ MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a -+ // nullptr, which indicates that no function is currently -+ // selected. This usually happens after an '.end' -+ // directive. -+ bool IsPicEnabled; - -- /// Parse a register as used in CFI directives. -+ // Map of register aliases created via the .set directive. -+ StringMap RegisterSets; -+ -+#define GET_ASSEMBLER_HEADER -+#include "LoongArchGenAsmMatcher.inc" -+ -+ unsigned checkTargetMatchPredicate(MCInst &Inst) override; -+ -+ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, -+ OperandVector &Operands, MCStreamer &Out, -+ uint64_t &ErrorInfo, -+ bool MatchingInlineAsm) override; -+ -+ /// Parse a register as used in CFI directives - bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) override; - -+ bool mnemonicIsValid(StringRef Mnemonic); -+ - bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, OperandVector &Operands) override; - -- bool ParseDirective(AsmToken DirectiveID) override { return true; } -+ bool ParseDirective(AsmToken DirectiveID) override; -+ -+ OperandMatchResultTy parseMemOperand(OperandVector &Operands); -+ OperandMatchResultTy parseAMemOperand(OperandVector &Operands); -+ OperandMatchResultTy -+ matchAnyRegisterNameWithoutDollar(OperandVector &Operands, -+ StringRef Identifier, SMLoc S); -+ OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, -+ const AsmToken &Token, -+ SMLoc S); -+ OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, -+ SMLoc S); -+ OperandMatchResultTy parseAnyRegister(OperandVector &Operands); -+ OperandMatchResultTy parseJumpTarget(OperandVector &Operands); -+ -+ bool searchSymbolAlias(OperandVector &Operands); -+ -+ bool parseOperand(OperandVector &, StringRef Mnemonic); -+ -+ enum MacroExpanderResultTy { -+ MER_NotAMacro, -+ MER_Success, -+ MER_Fail, -+ }; - -- bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, -- OperandVector &Operands, MCStreamer &Out, -- uint64_t &ErrorInfo, -- bool MatchingInlineAsm) override; -+ // Expands assembly pseudo instructions. -+ MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, -+ MCStreamer &Out, -+ const MCSubtargetInfo *STI); - -- unsigned checkTargetMatchPredicate(MCInst &Inst) override; -+ bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -+ const MCSubtargetInfo *STI); - -- unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, -- unsigned Kind) override; -+ bool expandLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -+ const MCSubtargetInfo *STI); - -- bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, -- int64_t Lower, int64_t Upper, Twine Msg); -+ bool reportParseError(Twine ErrorMsg); - -- /// Helper for processing MC instructions that have been successfully matched -- /// by MatchAndEmitInstruction. -- bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, -- MCStreamer &Out); -+ bool parseMemOffset(const MCExpr *&Res); - --// Auto-generated instruction matching functions. --#define GET_ASSEMBLER_HEADER --#include "LoongArchGenAsmMatcher.inc" -+ bool isEvaluated(const MCExpr *Expr); -+ bool parseDirectiveSet(); -+ -+ bool parseSetAssignment(); -+ -+ bool parseInternalDirectiveReallowModule(); -+ -+ int matchCPURegisterName(StringRef Symbol); -+ -+ int matchFPURegisterName(StringRef Name); -+ -+ int matchFCFRRegisterName(StringRef Name); -+ int matchFCSRRegisterName(StringRef Name); -+ -+ int matchLSX128RegisterName(StringRef Name); -+ -+ int matchLASX256RegisterName(StringRef Name); -+ -+ bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -+ const MCSubtargetInfo *STI); -+ -+ // Helper function that checks if the value of a vector index is within the -+ // boundaries of accepted values for each RegisterKind -+ // Example: VINSGR2VR.B $v0[n], $1 => 16 > n >= 0 -+ bool validateLSXIndex(int Val, int RegKind); -+ -+ void setFeatureBits(uint64_t Feature, StringRef FeatureString) { -+ if (!(getSTI().getFeatureBits()[Feature])) { -+ MCSubtargetInfo &STI = copySTI(); -+ setAvailableFeatures( -+ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); -+ AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); -+ } -+ } - -- OperandMatchResultTy parseRegister(OperandVector &Operands); -- OperandMatchResultTy parseImmediate(OperandVector &Operands); -+ void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { -+ if (getSTI().getFeatureBits()[Feature]) { -+ MCSubtargetInfo &STI = copySTI(); -+ setAvailableFeatures( -+ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); -+ AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); -+ } -+ } -+ -+ void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { -+ setFeatureBits(Feature, FeatureString); -+ AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); -+ } - -- bool parseOperand(OperandVector &Operands, StringRef Mnemonic); -+ void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { -+ clearFeatureBits(Feature, FeatureString); -+ AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); -+ } - - public: - enum LoongArchMatchResultTy { -- Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, -- Match_RequiresMsbNotLessThanLsb, -- Match_RequiresOpnd2NotR0R1, -+ Match_RequiresNoZeroRegister = FIRST_TARGET_MATCH_RESULT_TY, -+ Match_RequiresNoRaRegister, -+ Match_RequiresRange0_31, -+ Match_RequiresRange0_63, -+ Match_MsbHigherThanLsb, -+ Match_RequiresPosSizeUImm6, - #define GET_OPERAND_DIAGNOSTIC_TYPES - #include "LoongArchGenAsmMatcher.inc" - #undef GET_OPERAND_DIAGNOSTIC_TYPES - }; - -- LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, -+ LoongArchAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, - const MCInstrInfo &MII, const MCTargetOptions &Options) -- : MCTargetAsmParser(Options, STI, MII) { -- Parser.addAliasForDirective(".half", ".2byte"); -- Parser.addAliasForDirective(".hword", ".2byte"); -- Parser.addAliasForDirective(".word", ".4byte"); -- Parser.addAliasForDirective(".dword", ".8byte"); -+ : MCTargetAsmParser(Options, sti, MII), -+ ABI(LoongArchABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), -+ sti.getCPU(), Options)) { -+ MCAsmParserExtension::Initialize(parser); -+ -+ parser.addAliasForDirective(".asciiz", ".asciz"); -+ parser.addAliasForDirective(".hword", ".2byte"); -+ parser.addAliasForDirective(".word", ".4byte"); -+ parser.addAliasForDirective(".dword", ".8byte"); - - // Initialize the set of available features. -- setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); -+ setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); -+ -+ // Remember the initial assembler options. The user can not modify these. -+ AssemblerOptions.push_back( -+ std::make_unique(getSTI().getFeatureBits())); -+ -+ // Create an assembler options environment for the user to modify. -+ AssemblerOptions.push_back( -+ std::make_unique(getSTI().getFeatureBits())); -+ -+ getTargetStreamer().updateABIInfo(*this); -+ -+ CurrentFn = nullptr; -+ -+ IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); -+ } -+ -+ bool is64Bit() const { -+ return getSTI().getFeatureBits()[LoongArch::Feature64Bit]; -+ } -+ -+ bool isFP64bit() const { -+ return getSTI().getFeatureBits()[LoongArch::FeatureFP64Bit]; -+ } -+ -+ const LoongArchABIInfo &getABI() const { return ABI; } -+ bool isABI_LPX32() const { return ABI.IsLPX32(); } -+ bool isABI_LP64() const { return ABI.IsLP64(); } -+ bool isABI_LP32() const { return ABI.IsLP32(); } -+ -+ bool hasLSX() const { -+ return getSTI().getFeatureBits()[LoongArch::FeatureLSX]; -+ } -+ -+ bool hasLASX() const { -+ return getSTI().getFeatureBits()[LoongArch::FeatureLASX]; -+ } -+ -+ bool inPicMode() { -+ return IsPicEnabled; -+ } -+ -+ bool useSoftFloat() const { -+ return getSTI().getFeatureBits()[LoongArch::FeatureSoftFloat]; -+ } -+ -+ const MCExpr *createTargetUnaryExpr(const MCExpr *E, -+ AsmToken::TokenKind OperatorToken, -+ MCContext &Ctx) override { -+ switch(OperatorToken) { -+ default: -+ llvm_unreachable("Unknown token"); -+ return nullptr; -+#if 0 -+ case AsmToken::PercentPlt: -+ return LoongArchMCExpr::create(LoongArchMCExpr::MEK_PLT, E, Ctx); -+#endif -+ } - } - }; - --// Instances of this class represent a parsed LoongArch machine instruction. -+/// LoongArchOperand - Instances of this class represent a parsed LoongArch machine -+/// instruction. - class LoongArchOperand : public MCParsedAsmOperand { -- enum class KindTy { -- Token, -- Register, -- Immediate, -+public: -+ /// Broad categories of register classes -+ /// The exact class is finalized by the render method. -+ enum RegKind { -+ RegKind_GPR = 1, /// GPR32 and GPR64 (depending on is64Bit()) -+ RegKind_FGR = 2, /// FGR32, FGR64 (depending on isFP64bit()) -+ RegKind_FCFR = 4, /// FCFR -+ RegKind_FCSR = 8, /// FCSR -+ RegKind_LSX128 = 16, /// LSX128[BHWD] (makes no difference which) -+ RegKind_LASX256 = 32, /// LASX256[BHWD] (makes no difference which) -+ RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCFR | RegKind_FCSR | -+ RegKind_LSX128 | RegKind_LASX256 -+ }; -+ -+private: -+ enum KindTy { -+ k_Immediate, /// An immediate (possibly involving symbol references) -+ k_Memory, /// Base + Offset Memory Address -+ k_RegisterIndex, /// A register index in one or more RegKind. -+ k_Token, /// A simple token -+ k_RegList, /// A physical register list - } Kind; - -- struct RegOp { -- MCRegister RegNum; -+public: -+ LoongArchOperand(KindTy K, LoongArchAsmParser &Parser) -+ : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} -+ -+ ~LoongArchOperand() override { -+ switch (Kind) { -+ case k_Memory: -+ delete Mem.Base; -+ break; -+ case k_RegList: -+ delete RegList.List; -+ break; -+ case k_Immediate: -+ case k_RegisterIndex: -+ case k_Token: -+ break; -+ } -+ } -+ -+private: -+ /// For diagnostics, and checking the assembler temporary -+ LoongArchAsmParser &AsmParser; -+ -+ struct Token { -+ const char *Data; -+ unsigned Length; -+ }; -+ -+ struct RegIdxOp { -+ unsigned Index; /// Index into the register class -+ RegKind Kind; /// Bitfield of the kinds it could possibly be -+ struct Token Tok; /// The input token this operand originated from. -+ const MCRegisterInfo *RegInfo; - }; - - struct ImmOp { - const MCExpr *Val; - }; - -- SMLoc StartLoc, EndLoc; -- union { -- StringRef Tok; -- struct RegOp Reg; -- struct ImmOp Imm; -+ struct MemOp { -+ LoongArchOperand *Base; -+ const MCExpr *Off; - }; - --public: -- LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} -+ struct RegListOp { -+ SmallVector *List; -+ }; - -- bool isToken() const override { return Kind == KindTy::Token; } -- bool isReg() const override { return Kind == KindTy::Register; } -- bool isImm() const override { return Kind == KindTy::Immediate; } -- bool isMem() const override { return false; } -- void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } -+ union { -+ struct Token Tok; -+ struct RegIdxOp RegIdx; -+ struct ImmOp Imm; -+ struct MemOp Mem; -+ struct RegListOp RegList; -+ }; - -- static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) { -- if (auto CE = dyn_cast(Expr)) { -- Imm = CE->getValue(); -- return true; -- } -+ SMLoc StartLoc, EndLoc; - -- return false; -+ /// Internal constructor for register kinds -+ static std::unique_ptr CreateReg(unsigned Index, StringRef Str, -+ RegKind RegKind, -+ const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, -+ LoongArchAsmParser &Parser) { -+ auto Op = std::make_unique(k_RegisterIndex, Parser); -+ Op->RegIdx.Index = Index; -+ Op->RegIdx.RegInfo = RegInfo; -+ Op->RegIdx.Kind = RegKind; -+ Op->RegIdx.Tok.Data = Str.data(); -+ Op->RegIdx.Tok.Length = Str.size(); -+ Op->StartLoc = S; -+ Op->EndLoc = E; -+ return Op; - } - -- template bool isUImm() const { -- if (!isImm()) -- return false; -- -- int64_t Imm; -- bool IsConstantImm = evaluateConstantImm(getImm(), Imm); -- return IsConstantImm && isUInt(Imm - P); -+public: -+ /// Coerce the register to GPR32 and return the real register for the current -+ /// target. -+ unsigned getGPR32Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -+ unsigned ClassID = LoongArch::GPR32RegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -- template bool isSImm() const { -- if (!isImm()) -- return false; -- -- int64_t Imm; -- bool IsConstantImm = evaluateConstantImm(getImm(), Imm); -- return IsConstantImm && isShiftedInt(Imm); -- } -- -- bool isUImm2() const { return isUImm<2>(); } -- bool isUImm2plus1() const { return isUImm<2, 1>(); } -- bool isUImm3() const { return isUImm<3>(); } -- bool isUImm5() const { return isUImm<5>(); } -- bool isUImm6() const { return isUImm<6>(); } -- bool isUImm8() const { return isUImm<8>(); } -- bool isUImm12() const { return isUImm<12>(); } -- bool isUImm14() const { return isUImm<14>(); } -- bool isUImm15() const { return isUImm<15>(); } -- bool isSImm12() const { return isSImm<12>(); } -- bool isSImm14lsl2() const { return isSImm<14, 2>(); } -- bool isSImm16() const { return isSImm<16>(); } -- bool isSImm16lsl2() const { return isSImm<16, 2>(); } -- bool isSImm20() const { return isSImm<20>(); } -- bool isSImm21lsl2() const { return isSImm<21, 2>(); } -- bool isSImm26lsl2() const { return isSImm<26, 2>(); } -- -- /// Gets location of the first token of this operand. -- SMLoc getStartLoc() const override { return StartLoc; } -- /// Gets location of the last token of this operand. -- SMLoc getEndLoc() const override { return EndLoc; } -- -- unsigned getReg() const override { -- assert(Kind == KindTy::Register && "Invalid type access!"); -- return Reg.RegNum.id(); -+ /// Coerce the register to GPR32 and return the real register for the current -+ /// target. -+ unsigned getGPRMM16Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -+ unsigned ClassID = LoongArch::GPR32RegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -- const MCExpr *getImm() const { -- assert(Kind == KindTy::Immediate && "Invalid type access!"); -- return Imm.Val; -+ /// Coerce the register to GPR64 and return the real register for the current -+ /// target. -+ unsigned getGPR64Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -+ unsigned ClassID = LoongArch::GPR64RegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -- StringRef getToken() const { -- assert(Kind == KindTy::Token && "Invalid type access!"); -- return Tok; -+private: -+ /// Coerce the register to FGR64 and return the real register for the current -+ /// target. -+ unsigned getFGR64Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); -+ return RegIdx.RegInfo->getRegClass(LoongArch::FGR64RegClassID) -+ .getRegister(RegIdx.Index); - } - -- void print(raw_ostream &OS) const override { -- auto RegName = [](unsigned Reg) { -- if (Reg) -- return LoongArchInstPrinter::getRegisterName(Reg); -- else -- return "noreg"; -- }; -+ /// Coerce the register to FGR32 and return the real register for the current -+ /// target. -+ unsigned getFGR32Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); -+ return RegIdx.RegInfo->getRegClass(LoongArch::FGR32RegClassID) -+ .getRegister(RegIdx.Index); -+ } - -- switch (Kind) { -- case KindTy::Immediate: -- OS << *getImm(); -- break; -- case KindTy::Register: -- OS << ""; -- break; -- case KindTy::Token: -- OS << "'" << getToken() << "'"; -- break; -- } -+ /// Coerce the register to FCFR and return the real register for the current -+ /// target. -+ unsigned getFCFRReg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCFR) && "Invalid access!"); -+ return RegIdx.RegInfo->getRegClass(LoongArch::FCFRRegClassID) -+ .getRegister(RegIdx.Index); - } - -- static std::unique_ptr createToken(StringRef Str, SMLoc S) { -- auto Op = std::make_unique(KindTy::Token); -- Op->Tok = Str; -- Op->StartLoc = S; -- Op->EndLoc = S; -- return Op; -+ /// Coerce the register to LSX128 and return the real register for the current -+ /// target. -+ unsigned getLSX128Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_LSX128) && "Invalid access!"); -+ // It doesn't matter which of the LSX128[BHWD] classes we use. They are all -+ // identical -+ unsigned ClassID = LoongArch::LSX128BRegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -- static std::unique_ptr createReg(unsigned RegNo, SMLoc S, -- SMLoc E) { -- auto Op = std::make_unique(KindTy::Register); -- Op->Reg.RegNum = RegNo; -- Op->StartLoc = S; -- Op->EndLoc = E; -- return Op; -+ unsigned getLASX256Reg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_LASX256) && "Invalid access!"); -+ unsigned ClassID = LoongArch::LASX256BRegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -- static std::unique_ptr createImm(const MCExpr *Val, SMLoc S, -- SMLoc E) { -- auto Op = std::make_unique(KindTy::Immediate); -- Op->Imm.Val = Val; -- Op->StartLoc = S; -- Op->EndLoc = E; -- return Op; -+ /// Coerce the register to CCR and return the real register for the -+ /// current target. -+ unsigned getFCSRReg() const { -+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCSR) && "Invalid access!"); -+ unsigned ClassID = LoongArch::FCSRRegClassID; -+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -+public: - void addExpr(MCInst &Inst, const MCExpr *Expr) const { -- if (auto CE = dyn_cast(Expr)) -+ // Add as immediate when possible. Null MCExpr = 0. -+ if (!Expr) -+ Inst.addOperand(MCOperand::createImm(0)); -+ else if (const MCConstantExpr *CE = dyn_cast(Expr)) - Inst.addOperand(MCOperand::createImm(CE->getValue())); - else - Inst.addOperand(MCOperand::createExpr(Expr)); - } - -- // Used by the TableGen Code. - void addRegOperands(MCInst &Inst, unsigned N) const { -- assert(N == 1 && "Invalid number of operands!"); -- Inst.addOperand(MCOperand::createReg(getReg())); -+ llvm_unreachable("Use a custom parser instead"); - } -- void addImmOperands(MCInst &Inst, unsigned N) const { -+ -+ /// Render the operand to an MCInst as a GPR32 -+ /// Asserts if the wrong number of operands are requested, or the operand -+ /// is not a k_RegisterIndex compatible with RegKind_GPR -+ void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); -- addExpr(Inst, getImm()); -+ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); - } --}; --} // end namespace - --#define GET_REGISTER_MATCHER --#define GET_SUBTARGET_FEATURE_NAME --#define GET_MATCHER_IMPLEMENTATION --#define GET_MNEMONIC_SPELL_CHECKER --#include "LoongArchGenAsmMatcher.inc" -+ void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); -+ } - --static MCRegister convertFPR32ToFPR64(MCRegister Reg) { -- assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); -- return Reg - LoongArch::F0 + LoongArch::F0_64; --} -+ void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); -+ } - --// Attempts to match Name as a register (either using the default name or --// alternative ABI names), setting RegNo to the matching register. Upon --// failure, returns true and sets RegNo to 0. --static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { -- RegNo = MatchRegisterName(Name); -- // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial -- // match always matches the 32-bit variant, and not the 64-bit one. -- assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); -- // The default FPR register class is based on the tablegen enum ordering. -- static_assert(LoongArch::F0 < LoongArch::F0_64, -- "FPR matching must be updated"); -- if (RegNo == LoongArch::NoRegister) -- RegNo = MatchRegisterAltName(Name); -+ void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -+ } - -- return RegNo == LoongArch::NoRegister; --} -+ void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -+ } - --bool LoongArchAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, -- SMLoc &EndLoc) { -- return Error(getLoc(), "invalid register number"); --} -+ void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -+ } - --OperandMatchResultTy LoongArchAsmParser::tryParseRegister(unsigned &RegNo, -- SMLoc &StartLoc, -- SMLoc &EndLoc) { -- llvm_unreachable("Unimplemented function."); --} -+ void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -+ } - --OperandMatchResultTy --LoongArchAsmParser::parseRegister(OperandVector &Operands) { -- if (getLexer().getTok().isNot(AsmToken::Dollar)) -- return MatchOperand_NoMatch; -+ void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst, -+ unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -+ } - -- // Eat the $ prefix. -- getLexer().Lex(); -- if (getLexer().getKind() != AsmToken::Identifier) -- return MatchOperand_NoMatch; -+ /// Render the operand to an MCInst as a GPR64 -+ /// Asserts if the wrong number of operands are requested, or the operand -+ /// is not a k_RegisterIndex compatible with RegKind_GPR -+ void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getGPR64Reg())); -+ } - -- StringRef Name = getLexer().getTok().getIdentifier(); -- MCRegister RegNo; -- matchRegisterNameHelper(RegNo, Name); -- if (RegNo == LoongArch::NoRegister) -- return MatchOperand_NoMatch; -+ void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFGR64Reg())); -+ } - -- SMLoc S = getLoc(); -- SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); -- getLexer().Lex(); -- Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); -+ void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFGR64Reg())); -+ } - -- return MatchOperand_Success; --} -+ void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFGR32Reg())); -+ } - --OperandMatchResultTy --LoongArchAsmParser::parseImmediate(OperandVector &Operands) { -- SMLoc S = getLoc(); -- SMLoc E; -- const MCExpr *Res; -+ void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFGR32Reg())); -+ } - -- if (getParser().parseExpression(Res, E)) -- return MatchOperand_ParseFail; -+ void addFCFRAsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFCFRReg())); -+ } - -- Operands.push_back(LoongArchOperand::createImm(Res, S, E)); -- return MatchOperand_Success; --} -+ void addLSX128AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getLSX128Reg())); -+ } - --/// Looks at a token type and creates the relevant operand from this --/// information, adding to Operands. Return true upon an error. --bool LoongArchAsmParser::parseOperand(OperandVector &Operands, -- StringRef Mnemonic) { -- if (parseRegister(Operands) == MatchOperand_Success || -- parseImmediate(Operands) == MatchOperand_Success) -- return false; -+ void addLASX256AsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getLASX256Reg())); -+ } - -- // Finally we have exhausted all options and must declare defeat. -- Error(getLoc(), "unknown operand"); -- return true; --} -+ void addFCSRAsmRegOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ Inst.addOperand(MCOperand::createReg(getFCSRReg())); -+ } - --bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, -- StringRef Name, SMLoc NameLoc, -- OperandVector &Operands) { -- // First operand in MCInst is instruction mnemonic. -- Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); -+ template -+ void addConstantUImmOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ uint64_t Imm = getConstantImm() - Offset; -+ Imm &= (1ULL << Bits) - 1; -+ Imm += Offset; -+ Imm += AdjustOffset; -+ Inst.addOperand(MCOperand::createImm(Imm)); -+ } - -- // If there are no more operands, then finish. -- if (parseOptionalToken(AsmToken::EndOfStatement)) -- return false; -+ template -+ void addSImmOperands(MCInst &Inst, unsigned N) const { -+ if (isImm() && !isConstantImm()) { -+ addExpr(Inst, getImm()); -+ return; -+ } -+ addConstantSImmOperands(Inst, N); -+ } - -- // Parse first operand. -- if (parseOperand(Operands, Name)) -- return true; -+ template -+ void addUImmOperands(MCInst &Inst, unsigned N) const { -+ if (isImm() && !isConstantImm()) { -+ addExpr(Inst, getImm()); -+ return; -+ } -+ addConstantUImmOperands(Inst, N); -+ } - -- // Parse until end of statement, consuming commas between operands. -- while (parseOptionalToken(AsmToken::Comma)) -- if (parseOperand(Operands, Name)) -- return true; -+ template -+ void addConstantSImmOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ int64_t Imm = getConstantImm() - Offset; -+ Imm = SignExtend64(Imm); -+ Imm += Offset; -+ Imm += AdjustOffset; -+ Inst.addOperand(MCOperand::createImm(Imm)); -+ } - -- // Parse end of statement and return successfully. -- if (parseOptionalToken(AsmToken::EndOfStatement)) -- return false; -+ void addImmOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ const MCExpr *Expr = getImm(); -+ addExpr(Inst, Expr); -+ } - -- SMLoc Loc = getLexer().getLoc(); -- getParser().eatToEndOfStatement(); -- return Error(Loc, "unexpected token"); --} -+ void addMemOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 2 && "Invalid number of operands!"); - --bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, -- OperandVector &Operands, -- MCStreamer &Out) { -- Inst.setLoc(IDLoc); -- Out.emitInstruction(Inst, getSTI()); -- return false; --} -+ Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit() -+ ? getMemBase()->getGPR64Reg() -+ : getMemBase()->getGPR32Reg())); - --unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { -- switch (Inst.getOpcode()) { -- default: -- break; -- case LoongArch::CSRXCHG: { -- unsigned Rj = Inst.getOperand(2).getReg(); -- if (Rj == LoongArch::R0 || Rj == LoongArch::R1) -- return Match_RequiresOpnd2NotR0R1; -- return Match_Success; -+ const MCExpr *Expr = getMemOff(); -+ addExpr(Inst, Expr); - } -- case LoongArch::BSTRINS_W: -- case LoongArch::BSTRINS_D: -- case LoongArch::BSTRPICK_W: -- case LoongArch::BSTRPICK_D: { -- unsigned Opc = Inst.getOpcode(); -- const signed Msb = -- (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) -- ? Inst.getOperand(3).getImm() -- : Inst.getOperand(2).getImm(); -- const signed Lsb = -- (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) -- ? Inst.getOperand(4).getImm() -- : Inst.getOperand(3).getImm(); -- if (Msb < Lsb) -- return Match_RequiresMsbNotLessThanLsb; -- return Match_Success; -+ -+ void addRegListOperands(MCInst &Inst, unsigned N) const { -+ assert(N == 1 && "Invalid number of operands!"); -+ -+ for (auto RegNo : getRegList()) -+ Inst.addOperand(MCOperand::createReg(RegNo)); - } -+ -+ bool isReg() const override { -+ // As a special case until we sort out the definition of div/divu, accept -+ // $0/$zero here so that MCK_ZERO works correctly. -+ return isGPRAsmReg() && RegIdx.Index == 0; - } - -- return Match_Success; --} -+ bool isRegIdx() const { return Kind == k_RegisterIndex; } -+ bool isImm() const override { return Kind == k_Immediate; } - --unsigned --LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, -- unsigned Kind) { -- LoongArchOperand &Op = static_cast(AsmOp); -- if (!Op.isReg()) -- return Match_InvalidOperand; -+ bool isConstantImm() const { -+ int64_t Res; -+ return isImm() && getImm()->evaluateAsAbsolute(Res); -+ } - -- MCRegister Reg = Op.getReg(); -- // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the -- // register from FPR32 to FPR64 if necessary. -- if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && -- Kind == MCK_FPR64) { -- Op.setReg(convertFPR32ToFPR64(Reg)); -- return Match_Success; -+ bool isConstantImmz() const { -+ return isConstantImm() && getConstantImm() == 0; - } - -- return Match_InvalidOperand; --} -+ template bool isConstantUImm() const { -+ return isConstantImm() && isUInt(getConstantImm() - Offset); -+ } - --bool LoongArchAsmParser::generateImmOutOfRangeError( -- OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, -- Twine Msg = "immediate must be an integer in the range") { -- SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); -- return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); --} -+ template bool isSImm() const { -+ return isConstantImm() ? isInt(getConstantImm()) : isImm(); -+ } - --bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, -- OperandVector &Operands, -- MCStreamer &Out, -- uint64_t &ErrorInfo, -- bool MatchingInlineAsm) { -- MCInst Inst; -- FeatureBitset MissingFeatures; -+ template bool isUImm() const { -+ return isConstantImm() ? isUInt(getConstantImm()) : isImm(); -+ } - -- auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, -- MatchingInlineAsm); -- switch (Result) { -- default: -- break; -- case Match_Success: -- return processInstruction(Inst, IDLoc, Operands, Out); -- case Match_MissingFeature: { -- assert(MissingFeatures.any() && "Unknown missing features!"); -- bool FirstFeature = true; -- std::string Msg = "instruction requires the following:"; -- for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { -- if (MissingFeatures[i]) { -- Msg += FirstFeature ? " " : ", "; -- Msg += getSubtargetFeatureName(i); -- FirstFeature = false; -- } -- } -- return Error(IDLoc, Msg); -+ template bool isAnyImm() const { -+ return isConstantImm() ? (isInt(getConstantImm()) || -+ isUInt(getConstantImm())) -+ : isImm(); - } -- case Match_MnemonicFail: { -- FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); -- std::string Suggestion = LoongArchMnemonicSpellCheck( -- ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); -- return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); -+ -+ template bool isConstantSImm() const { -+ return isConstantImm() && isInt(getConstantImm() - Offset); -+ } -+ -+ template bool isConstantUImmRange() const { -+ return isConstantImm() && getConstantImm() >= Bottom && -+ getConstantImm() <= Top; -+ } -+ -+ bool isToken() const override { -+ // Note: It's not possible to pretend that other operand kinds are tokens. -+ // The matcher emitter checks tokens first. -+ return Kind == k_Token; -+ } -+ -+ bool isMem() const override { return Kind == k_Memory; } -+ -+ bool isConstantMemOff() const { -+ return isMem() && isa(getMemOff()); -+ } -+ -+ bool isZeroMemOff() const { -+ return isMem() && isa(getMemOff()) && -+ getConstantMemOff() == 0; -+ } -+ -+ // Allow relocation operators. -+ // FIXME: This predicate and others need to look through binary expressions -+ // and determine whether a Value is a constant or not. -+ template -+ bool isMemWithSimmOffset() const { -+ if (!isMem()) -+ return false; -+ if (!getMemBase()->isGPRAsmReg()) -+ return false; -+ if (isa(getMemOff()) || -+ (isConstantMemOff() && -+ isShiftedInt(getConstantMemOff()))) -+ return true; -+ MCValue Res; -+ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); -+ return IsReloc && isShiftedInt(Res.getConstant()); -+ } -+ -+ bool isMemWithPtrSizeOffset() const { -+ if (!isMem()) -+ return false; -+ if (!getMemBase()->isGPRAsmReg()) -+ return false; -+ const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32; -+ if (isa(getMemOff()) || -+ (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff()))) -+ return true; -+ MCValue Res; -+ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); -+ return IsReloc && isIntN(PtrBits, Res.getConstant()); -+ } -+ -+ bool isMemWithGRPMM16Base() const { -+ return isMem() && getMemBase()->isMM16AsmReg(); -+ } -+ -+ template bool isMemWithUimmOffsetSP() const { -+ return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) -+ && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == LoongArch::SP); -+ } -+ -+ template bool isMemWithUimmWordAlignedOffsetSP() const { -+ return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) -+ && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() -+ && (getMemBase()->getGPR32Reg() == LoongArch::SP); -+ } -+ -+ template -+ bool isScaledUImm() const { -+ return isConstantImm() && -+ isShiftedUInt(getConstantImm()); -+ } -+ -+ template -+ bool isScaledSImm() const { -+ if (isConstantImm() && -+ isShiftedInt(getConstantImm())) -+ return true; -+ // Operand can also be a symbol or symbol plus -+ // offset in case of relocations. -+ if (Kind != k_Immediate) -+ return false; -+ MCValue Res; -+ bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr); -+ return Success && isShiftedInt(Res.getConstant()); -+ } -+ -+ bool isRegList16() const { -+ if (!isRegList()) -+ return false; -+ -+ int Size = RegList.List->size(); -+ if (Size < 2 || Size > 5) -+ return false; -+ -+ unsigned R0 = RegList.List->front(); -+ unsigned R1 = RegList.List->back(); -+ if (!((R0 == LoongArch::S0 && R1 == LoongArch::RA) || -+ (R0 == LoongArch::S0_64 && R1 == LoongArch::RA_64))) -+ return false; -+ -+ int PrevReg = *RegList.List->begin(); -+ for (int i = 1; i < Size - 1; i++) { -+ int Reg = (*(RegList.List))[i]; -+ if ( Reg != PrevReg + 1) -+ return false; -+ PrevReg = Reg; -+ } -+ -+ return true; -+ } -+ -+ bool isInvNum() const { return Kind == k_Immediate; } -+ -+ bool isLSAImm() const { -+ if (!isConstantImm()) -+ return false; -+ int64_t Val = getConstantImm(); -+ return 1 <= Val && Val <= 4; -+ } -+ -+ bool isRegList() const { return Kind == k_RegList; } -+ -+ StringRef getToken() const { -+ assert(Kind == k_Token && "Invalid access!"); -+ return StringRef(Tok.Data, Tok.Length); -+ } -+ -+ unsigned getReg() const override { -+ // As a special case until we sort out the definition of div/divu, accept -+ // $0/$zero here so that MCK_ZERO works correctly. -+ if (Kind == k_RegisterIndex && RegIdx.Index == 0 && -+ RegIdx.Kind & RegKind_GPR) -+ return getGPR32Reg(); // FIXME: GPR64 too -+ -+ llvm_unreachable("Invalid access!"); -+ return 0; -+ } -+ -+ const MCExpr *getImm() const { -+ assert((Kind == k_Immediate) && "Invalid access!"); -+ return Imm.Val; -+ } -+ -+ int64_t getConstantImm() const { -+ const MCExpr *Val = getImm(); -+ int64_t Value = 0; -+ (void)Val->evaluateAsAbsolute(Value); -+ return Value; -+ } -+ -+ LoongArchOperand *getMemBase() const { -+ assert((Kind == k_Memory) && "Invalid access!"); -+ return Mem.Base; -+ } -+ -+ const MCExpr *getMemOff() const { -+ assert((Kind == k_Memory) && "Invalid access!"); -+ return Mem.Off; -+ } -+ -+ int64_t getConstantMemOff() const { -+ return static_cast(getMemOff())->getValue(); -+ } -+ -+ const SmallVectorImpl &getRegList() const { -+ assert((Kind == k_RegList) && "Invalid access!"); -+ return *(RegList.List); -+ } -+ -+ static std::unique_ptr CreateToken(StringRef Str, SMLoc S, -+ LoongArchAsmParser &Parser) { -+ auto Op = std::make_unique(k_Token, Parser); -+ Op->Tok.Data = Str.data(); -+ Op->Tok.Length = Str.size(); -+ Op->StartLoc = S; -+ Op->EndLoc = S; -+ return Op; -+ } -+ -+ /// Create a numeric register (e.g. $1). The exact register remains -+ /// unresolved until an instruction successfully matches -+ static std::unique_ptr -+ createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); -+ return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser); -+ } -+ -+ /// Create a register that is definitely a GPR. -+ /// This is typically only used for named registers such as $gp. -+ static std::unique_ptr -+ createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser); -+ } -+ -+ /// Create a register that is definitely a FGR. -+ /// This is typically only used for named registers such as $f0. -+ static std::unique_ptr -+ createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser); -+ } -+ -+ /// Create a register that is definitely an FCFR. -+ /// This is typically only used for named registers such as $fcc0. -+ static std::unique_ptr -+ createFCFRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_FCFR, RegInfo, S, E, Parser); -+ } -+ -+ /// Create a register that is definitely an FCSR. -+ /// This is typically only used for named registers such as $fcsr0. -+ static std::unique_ptr -+ createFCSRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_FCSR, RegInfo, S, E, Parser); -+ } -+ -+ /// Create a register that is definitely an LSX128. -+ /// This is typically only used for named registers such as $v0. -+ static std::unique_ptr -+ createLSX128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_LSX128, RegInfo, S, E, Parser); -+ } -+ -+ static std::unique_ptr -+ createLASX256Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, -+ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ return CreateReg(Index, Str, RegKind_LASX256, RegInfo, S, E, Parser); -+ } -+ -+ static std::unique_ptr -+ CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { -+ auto Op = std::make_unique(k_Immediate, Parser); -+ Op->Imm.Val = Val; -+ Op->StartLoc = S; -+ Op->EndLoc = E; -+ return Op; -+ } -+ -+ static std::unique_ptr -+ CreateMem(std::unique_ptr Base, const MCExpr *Off, SMLoc S, -+ SMLoc E, LoongArchAsmParser &Parser) { -+ auto Op = std::make_unique(k_Memory, Parser); -+ Op->Mem.Base = Base.release(); -+ Op->Mem.Off = Off; -+ Op->StartLoc = S; -+ Op->EndLoc = E; -+ return Op; -+ } -+ -+ static std::unique_ptr -+ CreateRegList(SmallVectorImpl &Regs, SMLoc StartLoc, SMLoc EndLoc, -+ LoongArchAsmParser &Parser) { -+ assert(Regs.size() > 0 && "Empty list not allowed"); -+ -+ auto Op = std::make_unique(k_RegList, Parser); -+ Op->RegList.List = new SmallVector(Regs.begin(), Regs.end()); -+ Op->StartLoc = StartLoc; -+ Op->EndLoc = EndLoc; -+ return Op; -+ } -+ -+ bool isGPRZeroAsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0; -+ } -+ -+ bool isGPRNonZeroAsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 && -+ RegIdx.Index <= 31; -+ } -+ -+ bool isGPRAsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; -+ } -+ -+ bool isMM16AsmReg() const { -+ if (!(isRegIdx() && RegIdx.Kind)) -+ return false; -+ return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) -+ || RegIdx.Index == 16 || RegIdx.Index == 17); -+ -+ } -+ bool isMM16AsmRegZero() const { -+ if (!(isRegIdx() && RegIdx.Kind)) -+ return false; -+ return (RegIdx.Index == 0 || -+ (RegIdx.Index >= 2 && RegIdx.Index <= 7) || -+ RegIdx.Index == 17); -+ } -+ -+ bool isMM16AsmRegMoveP() const { -+ if (!(isRegIdx() && RegIdx.Kind)) -+ return false; -+ return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || -+ (RegIdx.Index >= 16 && RegIdx.Index <= 20)); -+ } -+ -+ bool isMM16AsmRegMovePPairFirst() const { -+ if (!(isRegIdx() && RegIdx.Kind)) -+ return false; -+ return RegIdx.Index >= 4 && RegIdx.Index <= 6; -+ } -+ -+ bool isMM16AsmRegMovePPairSecond() const { -+ if (!(isRegIdx() && RegIdx.Kind)) -+ return false; -+ return (RegIdx.Index == 21 || RegIdx.Index == 22 || -+ (RegIdx.Index >= 5 && RegIdx.Index <= 7)); -+ } -+ -+ bool isFGRAsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; -+ } -+ -+ bool isStrictlyFGRAsmReg() const { -+ return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31; -+ } -+ -+ bool isFCSRAsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_FCSR && RegIdx.Index <= 3; -+ } -+ -+ bool isFCFRAsmReg() const { -+ if (!(isRegIdx() && RegIdx.Kind & RegKind_FCFR)) -+ return false; -+ return RegIdx.Index <= 7; -+ } -+ -+ bool isLSX128AsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_LSX128 && RegIdx.Index <= 31; -+ } -+ -+ bool isLASX256AsmReg() const { -+ return isRegIdx() && RegIdx.Kind & RegKind_LASX256 && RegIdx.Index <= 31; -+ } -+ -+ /// getStartLoc - Get the location of the first token of this operand. -+ SMLoc getStartLoc() const override { return StartLoc; } -+ /// getEndLoc - Get the location of the last token of this operand. -+ SMLoc getEndLoc() const override { return EndLoc; } -+ -+ void print(raw_ostream &OS) const override { -+ switch (Kind) { -+ case k_Immediate: -+ OS << "Imm<"; -+ OS << *Imm.Val; -+ OS << ">"; -+ break; -+ case k_Memory: -+ OS << "Mem<"; -+ Mem.Base->print(OS); -+ OS << ", "; -+ OS << *Mem.Off; -+ OS << ">"; -+ break; -+ case k_RegisterIndex: -+ OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", " -+ << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">"; -+ break; -+ case k_Token: -+ OS << getToken(); -+ break; -+ case k_RegList: -+ OS << "RegList< "; -+ for (auto Reg : (*RegList.List)) -+ OS << Reg << " "; -+ OS << ">"; -+ break; -+ } -+ } -+ -+ bool isValidForTie(const LoongArchOperand &Other) const { -+ if (Kind != Other.Kind) -+ return false; -+ -+ switch (Kind) { -+ default: -+ llvm_unreachable("Unexpected kind"); -+ return false; -+ case k_RegisterIndex: { -+ StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length); -+ StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length); -+ return Token == OtherToken; -+ } -+ } -+ } -+}; // class LoongArchOperand -+ -+} // end anonymous namespace -+ -+namespace llvm { -+ -+extern const MCInstrDesc LoongArchInsts[]; -+ -+} // end namespace llvm -+ -+static const MCInstrDesc &getInstDesc(unsigned Opcode) { -+ return LoongArchInsts[Opcode]; -+} -+ -+static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) { -+ if (const MCSymbolRefExpr *SRExpr = dyn_cast(Expr)) { -+ return &SRExpr->getSymbol(); -+ } -+ -+ if (const MCBinaryExpr *BExpr = dyn_cast(Expr)) { -+ const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS()); -+ const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS()); -+ -+ if (LHSSym) -+ return LHSSym; -+ -+ if (RHSSym) -+ return RHSSym; -+ -+ return nullptr; -+ } -+ -+ if (const MCUnaryExpr *UExpr = dyn_cast(Expr)) -+ return getSingleMCSymbol(UExpr->getSubExpr()); -+ -+ return nullptr; -+} -+ -+static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { -+ if (isa(Expr)) -+ return 1; -+ -+ if (const MCBinaryExpr *BExpr = dyn_cast(Expr)) -+ return countMCSymbolRefExpr(BExpr->getLHS()) + -+ countMCSymbolRefExpr(BExpr->getRHS()); -+ -+ if (const MCUnaryExpr *UExpr = dyn_cast(Expr)) -+ return countMCSymbolRefExpr(UExpr->getSubExpr()); -+ -+ return 0; -+} -+ -+bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, -+ MCStreamer &Out, -+ const MCSubtargetInfo *STI) { -+ const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); -+ -+ Inst.setLoc(IDLoc); -+ -+ // Check branch instructions. -+ if (MCID.isBranch() || MCID.isCall()) { -+ const unsigned Opcode = Inst.getOpcode(); -+ MCOperand Offset; -+ bool check = true; -+ unsigned OffsetOpndIdx, OffsetOpndWidth; -+ switch (Opcode) { -+ default: -+ check = false; -+ break; -+ case LoongArch::BEQ: -+ case LoongArch::BNE: -+ case LoongArch::BLT: -+ case LoongArch::BGE: -+ case LoongArch::BLTU: -+ case LoongArch::BGEU: -+ OffsetOpndIdx = 2; -+ OffsetOpndWidth = 16; -+ break; -+ case LoongArch::BEQZ: -+ case LoongArch::BNEZ: -+ case LoongArch::BCEQZ: -+ case LoongArch::BCNEZ: -+ OffsetOpndIdx = 1; -+ OffsetOpndWidth = 21; -+ break; -+ case LoongArch::B: -+ case LoongArch::BL: -+ OffsetOpndIdx = 0; -+ OffsetOpndWidth = 26; -+ break; -+ } -+ if (check) { -+ assert(MCID.getNumOperands() == OffsetOpndIdx + 1 && -+ "unexpected number of operands"); -+ Offset = Inst.getOperand(OffsetOpndIdx); -+ // Non-Imm situation will be dealed with later on when applying fixups. -+ if (Offset.isImm()) { -+ if (!isIntN(OffsetOpndWidth + 2, Offset.getImm())) -+ return Error(IDLoc, "branch target out of range"); -+ if (offsetToAlignment(Offset.getImm(), Align(1LL << 2))) -+ return Error(IDLoc, "branch to misaligned address"); -+ } -+ } -+ } -+ -+ bool IsPCRelativeLoad = (MCID.TSFlags & LoongArchII::IsPCRelativeLoad) != 0; -+ if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { -+ // Check the offset of memory operand, if it is a symbol -+ // reference or immediate we may have to expand instructions. -+ for (unsigned i = 0; i < MCID.getNumOperands(); i++) { -+ const MCOperandInfo &OpInfo = MCID.OpInfo[i]; -+ if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || -+ (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { -+ MCOperand &Op = Inst.getOperand(i); -+ if (Op.isImm()) { -+ int64_t MemOffset = Op.getImm(); -+ if (MemOffset < -32768 || MemOffset > 32767) { -+ return getParser().hasPendingError(); -+ } -+ } else if (Op.isExpr()) { -+ const MCExpr *Expr = Op.getExpr(); -+ if (Expr->getKind() == MCExpr::SymbolRef) { -+ const MCSymbolRefExpr *SR = -+ static_cast(Expr); -+ if (SR->getKind() == MCSymbolRefExpr::VK_None) { -+ return getParser().hasPendingError(); -+ } -+ } else if (!isEvaluated(Expr)) { -+ return getParser().hasPendingError(); -+ } -+ } -+ } -+ } // for -+ } // if load/store -+ -+ MacroExpanderResultTy ExpandResult = -+ tryExpandInstruction(Inst, IDLoc, Out, STI); -+ switch (ExpandResult) { -+ case MER_NotAMacro: -+ Out.emitInstruction(Inst, *STI); -+ break; -+ case MER_Success: -+ break; -+ case MER_Fail: -+ return true; - } -+ -+ return false; -+} -+ -+LoongArchAsmParser::MacroExpanderResultTy -+LoongArchAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -+ const MCSubtargetInfo *STI) { -+ switch (Inst.getOpcode()) { -+ default: -+ return MER_NotAMacro; -+ case LoongArch::LoadImm32: // li.w $rd, $imm32 -+ case LoongArch::LoadImm64: // li.d $rd, $imm64 -+ return expandLoadImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -+ case LoongArch::LoadAddrLocal: // la.local $rd, symbol -+ case LoongArch::LoadAddrGlobal: // la.global $rd, symbol -+ case LoongArch::LoadAddrGlobal_Alias: // la $rd, symbol -+ case LoongArch::LoadAddrTLS_LE: // la.tls.le $rd, symbol -+ case LoongArch::LoadAddrTLS_IE: // la.tls.ie $rd, symbol -+ case LoongArch::LoadAddrTLS_LD: // la.tls.ld $rd, symbol -+ case LoongArch::LoadAddrTLS_GD: // la.tls.gd $rd, symbol -+ return expandLoadAddress(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -+ } -+} -+ -+/// Can the value be represented by a unsigned N-bit value and a shift left? -+template static bool isShiftedUIntAtAnyPosition(uint64_t x) { -+ unsigned BitNum = findFirstSet(x); -+ -+ return (x == x >> BitNum << BitNum) && isUInt(x >> BitNum); -+} -+ -+bool LoongArchAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, -+ MCStreamer &Out, -+ const MCSubtargetInfo *STI) { -+ const int64_t Imm = Inst.getOperand(1).getImm(); -+ const unsigned DstReg = Inst.getOperand(0).getReg(); -+ LoongArchTargetStreamer &TOut = getTargetStreamer(); -+ bool Is64Bit = Inst.getOpcode() == LoongArch::LoadImm64; -+ unsigned SrcReg = Is64Bit ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ LoongArchAnalyzeImmediate::InstSeq Seq = -+ LoongArchAnalyzeImmediate::generateInstSeq( -+ Is64Bit ? Imm : SignExtend64<32>(Imm), Is64Bit); -+ -+ for (auto &Inst : Seq) { -+ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) -+ TOut.emitRI(Inst.Opc, DstReg, Inst.Imm, IDLoc, STI); -+ else -+ TOut.emitRRI(Inst.Opc, DstReg, SrcReg, Inst.Imm, IDLoc, STI); -+ SrcReg = DstReg; -+ } -+ -+ return false; -+} -+ -+bool LoongArchAsmParser::expandLoadAddress(MCInst &Inst, SMLoc IDLoc, -+ MCStreamer &Out, -+ const MCSubtargetInfo *STI) { -+ LoongArchTargetStreamer &TOut = getTargetStreamer(); -+ const MCExpr *SymExpr = Inst.getOperand(1).getExpr(); -+ const LoongArchMCExpr *HiExpr = nullptr; -+ const LoongArchMCExpr *LoExpr = nullptr; -+ const LoongArchMCExpr *HigherExpr = nullptr; -+ const LoongArchMCExpr *HighestExpr = nullptr; -+ const MCExpr *GotExpr = MCSymbolRefExpr::create( -+ "_GLOBAL_OFFSET_TABLE_", MCSymbolRefExpr::VK_None, getContext()); -+ unsigned DstReg = Inst.getOperand(0).getReg(); -+ -+ MCValue Res; -+ if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { -+ Error(IDLoc, "expected relocatable expression"); -+ return true; -+ } -+ if (Res.getSymB() != nullptr) { -+ Error(IDLoc, "expected relocatable expression with only one symbol"); -+ return true; -+ } -+ -+ switch (Inst.getOpcode()) { -+ case LoongArch::LoadAddrLocal: -+ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_PCREL_HI, SymExpr, -+ getContext()); -+ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_PCREL_LO, SymExpr, -+ getContext()); -+ -+ TOut.emitRX(LoongArch::PCADDU12I_ri, DstReg, MCOperand::createExpr(HiExpr), -+ IDLoc, STI); -+ TOut.emitRRX(LoongArch::ADDI_D_rri, DstReg, DstReg, -+ MCOperand::createExpr(LoExpr), IDLoc, STI); -+ return false; -+ case LoongArch::LoadAddrGlobal: -+ case LoongArch::LoadAddrGlobal_Alias: -+ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_GOT_HI, SymExpr, -+ getContext()); -+ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_GOT_LO, SymExpr, -+ getContext()); -+ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, -+ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ TOut.emitRRXX(LoongArch::LD_D_rrii, DstReg, DstReg, -+ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ return false; -+ case LoongArch::LoadAddrTLS_LE: -+ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HI, SymExpr, -+ getContext()); -+ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_LO, SymExpr, -+ getContext()); -+ HigherExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HIGHER, -+ SymExpr, getContext()); -+ HighestExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HIGHEST, -+ SymExpr, getContext()); -+ TOut.emitRX(LoongArch::LU12I_W_ri, DstReg, MCOperand::createExpr(HiExpr), -+ IDLoc, STI); -+ TOut.emitRRX(LoongArch::ORI_rri, DstReg, DstReg, -+ MCOperand::createExpr(LoExpr), IDLoc, STI); -+ TOut.emitRX(LoongArch::LU32I_D_ri, DstReg, -+ MCOperand::createExpr(HigherExpr), IDLoc, STI); -+ TOut.emitRRX(LoongArch::LU52I_D_rri, DstReg, DstReg, -+ MCOperand::createExpr(HighestExpr), IDLoc, STI); -+ return false; -+ case LoongArch::LoadAddrTLS_IE: -+ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSIE_HI, SymExpr, -+ getContext()); -+ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSIE_LO, SymExpr, -+ getContext()); -+ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, -+ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ TOut.emitRRXX(LoongArch::LD_D_rrii, DstReg, DstReg, -+ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ return false; -+ case LoongArch::LoadAddrTLS_LD: -+ case LoongArch::LoadAddrTLS_GD: -+ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSGD_HI, SymExpr, -+ getContext()); -+ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSGD_LO, SymExpr, -+ getContext()); -+ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, -+ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ TOut.emitRRXX(LoongArch::ADDI_D_rrii, DstReg, DstReg, -+ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), -+ IDLoc, STI); -+ return false; -+ default: -+ llvm_unreachable(""); -+ } -+} -+ -+unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { -+ switch (Inst.getOpcode()) { -+ case LoongArch::BSTRINS_W: -+ case LoongArch::BSTRPICK_W: { -+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && -+ "Operands must be immediates for bstrins.w/bstrpick.w!"); -+ const signed Msbw = Inst.getOperand(2).getImm(); -+ const signed Lsbw = Inst.getOperand(3).getImm(); -+ if (Msbw < Lsbw) -+ return Match_MsbHigherThanLsb; -+ if ((Lsbw < 0) || (Msbw > 31)) -+ return Match_RequiresRange0_31; -+ return Match_Success; -+ } -+ case LoongArch::BSTRINS_D: -+ case LoongArch::BSTRPICK_D: { -+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && -+ "Operands must be immediates for bstrins.d/bstrpick.d!"); -+ const signed Msbd = Inst.getOperand(2).getImm(); -+ const signed Lsbd = Inst.getOperand(3).getImm(); -+ if (Msbd < Lsbd) -+ return Match_MsbHigherThanLsb; -+ if ((Lsbd < 0) || (Msbd > 63)) -+ return Match_RequiresRange0_63; -+ return Match_Success; -+ } -+ case LoongArch::CSRXCHG32: -+ case LoongArch::CSRXCHG: -+ if (Inst.getOperand(2).getReg() == LoongArch::ZERO || -+ Inst.getOperand(2).getReg() == LoongArch::ZERO_64) -+ return Match_RequiresNoZeroRegister; -+ if (Inst.getOperand(2).getReg() == LoongArch::RA || -+ Inst.getOperand(2).getReg() == LoongArch::RA_64) -+ return Match_RequiresNoRaRegister; -+ return Match_Success; -+ } -+ -+ return Match_Success; -+} -+ -+static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, -+ uint64_t ErrorInfo) { -+ if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { -+ SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); -+ if (ErrorLoc == SMLoc()) -+ return Loc; -+ return ErrorLoc; -+ } -+ return Loc; -+} -+ -+bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, -+ OperandVector &Operands, -+ MCStreamer &Out, -+ uint64_t &ErrorInfo, -+ bool MatchingInlineAsm) { -+ MCInst Inst; -+ unsigned MatchResult = -+ MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); -+ switch (MatchResult) { -+ case Match_Success: -+ if (processInstruction(Inst, IDLoc, Out, STI)) -+ return true; -+ return false; -+ case Match_MissingFeature: -+ Error(IDLoc, "instruction requires a CPU feature not currently enabled"); -+ return true; - case Match_InvalidOperand: { - SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0ULL) { - if (ErrorInfo >= Operands.size()) -- return Error(ErrorLoc, "too few operands for instruction"); -+ return Error(IDLoc, "too few operands for instruction"); - -- ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); -+ ErrorLoc = Operands[ErrorInfo]->getStartLoc(); - if (ErrorLoc == SMLoc()) - ErrorLoc = IDLoc; - } -+ - return Error(ErrorLoc, "invalid operand for instruction"); - } -+ case Match_MnemonicFail: -+ return Error(IDLoc, "invalid instruction"); -+ case Match_RequiresNoZeroRegister: -+ return Error(IDLoc, "invalid operand ($zero) for instruction"); -+ case Match_RequiresNoRaRegister: -+ return Error(IDLoc, "invalid operand ($r1) for instruction"); -+ case Match_InvalidImm0_3: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 3]."); -+ case Match_InvalidImm0_7: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 7]."); -+ case Match_InvalidImm0_31: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 31]."); -+ case Match_InvalidImm0_63: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 63]."); -+ case Match_InvalidImm0_4095: -+ case Match_UImm12_Relaxed: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 4095]."); -+ case Match_InvalidImm0_32767: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "immediate must be an integer in range [0, 32767]."); -+ case Match_UImm16_Relaxed: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 16-bit unsigned immediate"); -+ case Match_UImm20_0: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 20-bit unsigned immediate"); -+ case Match_UImm26_0: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 26-bit unsigned immediate"); -+ case Match_UImm32_Coerced: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 32-bit immediate"); -+ case Match_InvalidSImm2: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 2-bit signed immediate"); -+ case Match_InvalidSImm3: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 3-bit signed immediate"); -+ case Match_InvalidSImm5: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 5-bit signed immediate"); -+ case Match_InvalidSImm8: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 8-bit signed immediate"); -+ case Match_InvalidSImm12: -+ case Match_SImm12_Relaxed: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 12-bit signed immediate"); -+ case Match_InvalidSImm14: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 14-bit signed immediate"); -+ case Match_InvalidSImm15: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 15-bit signed immediate"); -+ case Match_InvalidSImm16: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 16-bit signed immediate"); -+ case Match_InvalidSImm20: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 20-bit signed immediate"); -+ case Match_InvalidSImm21: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 21-bit signed immediate"); -+ case Match_InvalidSImm26: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 26-bit signed immediate"); -+ case Match_SImm32: -+ case Match_SImm32_Relaxed: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected 32-bit signed immediate"); -+ case Match_MemSImm14: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected memory with 14-bit signed offset"); -+ case Match_MemSImmPtr: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected memory with 32-bit signed offset"); -+ case Match_UImm2_1: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected immediate in range 1 .. 4"); -+ case Match_MemSImm14Lsl2: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected memory with 16-bit signed offset and multiple of 4"); -+ case Match_RequiresRange0_31: { -+ SMLoc ErrorStart = Operands[3]->getStartLoc(); -+ SMLoc ErrorEnd = Operands[4]->getEndLoc(); -+ return Error(ErrorStart, "from lsbw to msbw are not in the range 0 .. 31", -+ SMRange(ErrorStart, ErrorEnd)); -+ } -+ case Match_RequiresPosSizeUImm6: { -+ SMLoc ErrorStart = Operands[3]->getStartLoc(); -+ SMLoc ErrorEnd = Operands[4]->getEndLoc(); -+ return Error(ErrorStart, "size plus position are not in the range 1 .. 63", -+ SMRange(ErrorStart, ErrorEnd)); -+ } -+ case Match_RequiresRange0_63: { -+ SMLoc ErrorStart = Operands[3]->getStartLoc(); -+ SMLoc ErrorEnd = Operands[4]->getEndLoc(); -+ return Error(ErrorStart, "from lsbd to msbd are not in the range 0 .. 63", -+ SMRange(ErrorStart, ErrorEnd)); -+ } -+ case Match_MsbHigherThanLsb: { -+ SMLoc ErrorStart = Operands[3]->getStartLoc(); -+ SMLoc ErrorEnd = Operands[4]->getEndLoc(); -+ return Error(ErrorStart, "msb are not higher than lsb", SMRange(ErrorStart, ErrorEnd)); -+ } -+ case Match_MemZeroOff: -+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -+ "expected memory with constant 0 offset"); - } - -- // Handle the case when the error message is of specific type -- // other than the generic Match_InvalidOperand, and the -- // corresponding operand is missing. -- if (Result > FIRST_TARGET_MATCH_RESULT_TY) { -- SMLoc ErrorLoc = IDLoc; -- if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) -- return Error(ErrorLoc, "too few operands for instruction"); -+ llvm_unreachable("Implement any new match types added!"); -+} -+ -+/* -+ * Note: The implementation of this function must be sync with the definition -+ * of GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td -+ */ -+int LoongArchAsmParser::matchCPURegisterName(StringRef Name) { -+ int CC; -+ -+ CC = StringSwitch(Name) -+ .Cases("zero", "r0", 0) -+ .Cases("a0", "v0", "r4", 1) -+ .Cases("a1", "v1", "r5", 2) -+ .Cases("a2", "r6", 3) -+ .Cases("a3", "r7", 4) -+ .Cases("a4", "r8", 5) -+ .Cases("a5", "r9", 6) -+ .Cases("a6", "r10", 7) -+ .Cases("a7", "r11", 8) -+ .Cases("t0", "r12", 9) -+ .Cases("t1", "r13", 10) -+ .Cases("t2", "r14", 11) -+ .Cases("t3", "r15", 12) -+ .Cases("t4", "r16", 13) -+ .Cases("t5", "r17", 14) -+ .Cases("t6", "r18", 15) -+ .Cases("t7", "r19", 16) -+ .Cases("t8", "r20", 17) -+ .Cases("s0", "r23", 18) -+ .Cases("s1", "r24", 19) -+ .Cases("s2", "r25", 20) -+ .Cases("s3", "r26", 21) -+ .Cases("s4", "r27", 22) -+ .Cases("s5", "r28", 23) -+ .Cases("s6", "r29", 24) -+ .Cases("s7", "r30", 25) -+ .Cases("s8", "r31", 26) -+ .Cases("ra", "r1", 27) -+ .Cases("tp", "r2", 28) -+ .Cases("sp", "r3", 29) -+ .Case("r21", 30) -+ .Cases("fp", "r22", 31) -+ .Default(-1); -+ -+ return CC; -+} -+ -+int LoongArchAsmParser::matchFPURegisterName(StringRef Name) { -+ if (Name[0] == 'f') { -+ int CC; -+ -+ CC = StringSwitch(Name) -+ .Cases("f0", "fa0", "fv0", 0) -+ .Cases("f1", "fa1", "fv1", 1) -+ .Cases("f2", "fa2", 2) -+ .Cases("f3", "fa3", 3) -+ .Cases("f4", "fa4", 4) -+ .Cases("f5", "fa5", 5) -+ .Cases("f6", "fa6", 6) -+ .Cases("f7", "fa7", 7) -+ .Cases("f8", "ft0", 8) -+ .Cases("f9", "ft1", 9) -+ .Cases("f10", "ft2", 10) -+ .Cases("f11", "ft3", 11) -+ .Cases("f12", "ft4", 12) -+ .Cases("f13", "ft5", 13) -+ .Cases("f14", "ft6", 14) -+ .Cases("f15", "ft7", 15) -+ .Cases("f16", "ft8", 16) -+ .Cases("f17", "ft9", 17) -+ .Cases("f18", "ft10", 18) -+ .Cases("f19", "ft11", 19) -+ .Cases("f20", "ft12", 20) -+ .Cases("f21", "ft13", 21) -+ .Cases("f22", "ft14", 22) -+ .Cases("f23", "ft15", 23) -+ .Cases("f24", "fs0", 24) -+ .Cases("f25", "fs1", 25) -+ .Cases("f26", "fs2", 26) -+ .Cases("f27", "fs3", 27) -+ .Cases("f28", "fs4", 28) -+ .Cases("f29", "fs5", 29) -+ .Cases("f30", "fs6", 30) -+ .Cases("f31", "fs7", 31) -+ .Default(-1); -+ -+ return CC; - } -+ return -1; -+} - -- switch (Result) { -- default: -- break; -- case Match_RequiresMsbNotLessThanLsb: { -- SMLoc ErrorStart = Operands[3]->getStartLoc(); -- return Error(ErrorStart, "msb is less than lsb", -- SMRange(ErrorStart, Operands[4]->getEndLoc())); -- } -- case Match_RequiresOpnd2NotR0R1: -- return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); -- case Match_InvalidUImm2: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 2) - 1); -- case Match_InvalidUImm2plus1: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, -- /*Upper=*/(1 << 2)); -- case Match_InvalidUImm3: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 3) - 1); -- case Match_InvalidUImm5: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 5) - 1); -- case Match_InvalidUImm6: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 6) - 1); -- case Match_InvalidUImm12: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 12) - 1); -- case Match_InvalidUImm15: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, -- /*Upper=*/(1 << 15) - 1); -- case Match_InvalidSImm12: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), -- /*Upper=*/(1 << 11) - 1); -- case Match_InvalidSImm14lsl2: -- return generateImmOutOfRangeError( -- Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, -- "immediate must be a multiple of 4 in the range"); -- case Match_InvalidSImm16: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), -- /*Upper=*/(1 << 15) - 1); -- case Match_InvalidSImm16lsl2: -- return generateImmOutOfRangeError( -- Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, -- "immediate must be a multiple of 4 in the range"); -- case Match_InvalidSImm20: -- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), -- /*Upper=*/(1 << 19) - 1); -- case Match_InvalidSImm21lsl2: -- return generateImmOutOfRangeError( -- Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, -- "immediate must be a multiple of 4 in the range"); -- case Match_InvalidSImm26lsl2: -- return generateImmOutOfRangeError( -- Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, -- "immediate must be a multiple of 4 in the range"); -+int LoongArchAsmParser::matchFCFRRegisterName(StringRef Name) { -+ if (Name.startswith("fcc")) { -+ StringRef NumString = Name.substr(3); -+ unsigned IntVal; -+ if (NumString.getAsInteger(10, IntVal)) -+ return -1; // This is not an integer. -+ if (IntVal > 7) // There are only 8 fcc registers. -+ return -1; -+ return IntVal; -+ } -+ return -1; -+} -+ -+int LoongArchAsmParser::matchFCSRRegisterName(StringRef Name) { -+ if (Name.startswith("fcsr")) { -+ StringRef NumString = Name.substr(4); -+ unsigned IntVal; -+ if (NumString.getAsInteger(10, IntVal)) -+ return -1; // This is not an integer. -+ if (IntVal > 3) // There are only 4 fcsr registers. -+ return -1; -+ return IntVal; -+ } -+ return -1; -+} -+ -+int LoongArchAsmParser::matchLSX128RegisterName(StringRef Name) { -+ unsigned IntVal; -+ -+ if (Name.front() != 'v' || Name.drop_front(2).getAsInteger(10, IntVal)) -+ return -1; -+ -+ if (IntVal > 31) -+ return -1; -+ -+ return IntVal; -+} -+ -+int LoongArchAsmParser::matchLASX256RegisterName(StringRef Name) { -+ unsigned IntVal; -+ -+ if (Name.front() != 'x' || Name.drop_front(2).getAsInteger(10, IntVal)) -+ return -1; -+ -+ if (IntVal > 31) -+ return -1; -+ -+ return IntVal; -+} -+ -+bool LoongArchAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "parseOperand\n"); -+ -+ // Check if the current operand has a custom associated parser, if so, try to -+ // custom parse the operand, or fallback to the general approach. -+ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); -+ if (ResTy == MatchOperand_Success) -+ return false; -+ // If there wasn't a custom match, try the generic matcher below. Otherwise, -+ // there was a match, but an error occurred, in which case, just return that -+ // the operand parsing failed. -+ if (ResTy == MatchOperand_ParseFail) -+ return true; -+ -+ LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); -+ -+ switch (getLexer().getKind()) { -+ case AsmToken::Dollar: { -+ // Parse the register. -+ SMLoc S = Parser.getTok().getLoc(); -+ -+ // Almost all registers have been parsed by custom parsers. There is only -+ // one exception to this. $zero (and it's alias $0) will reach this point -+ // for div, divu, and similar instructions because it is not an operand -+ // to the instruction definition but an explicit register. Special case -+ // this situation for now. -+ if (parseAnyRegister(Operands) != MatchOperand_NoMatch) -+ return false; -+ -+ // Maybe it is a symbol reference. -+ StringRef Identifier; -+ if (Parser.parseIdentifier(Identifier)) -+ return true; -+ -+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -+ MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); -+ // Otherwise create a symbol reference. -+ const MCExpr *Res = -+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); -+ -+ Operands.push_back(LoongArchOperand::CreateImm(Res, S, E, *this)); -+ return false; -+ } -+ default: { -+ LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); -+ -+ const MCExpr *Expr; -+ SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. -+ if (getParser().parseExpression(Expr)) -+ return true; -+ -+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -+ -+ Operands.push_back(LoongArchOperand::CreateImm(Expr, S, E, *this)); -+ return false; - } -- llvm_unreachable("Unknown match type detected!"); -+ } // switch(getLexer().getKind()) -+ return true; -+} -+ -+bool LoongArchAsmParser::isEvaluated(const MCExpr *Expr) { -+ switch (Expr->getKind()) { -+ case MCExpr::Constant: -+ return true; -+ case MCExpr::SymbolRef: -+ return (cast(Expr)->getKind() != MCSymbolRefExpr::VK_None); -+ case MCExpr::Binary: { -+ const MCBinaryExpr *BE = cast(Expr); -+ if (!isEvaluated(BE->getLHS())) -+ return false; -+ return isEvaluated(BE->getRHS()); -+ } -+ case MCExpr::Unary: -+ return isEvaluated(cast(Expr)->getSubExpr()); -+ case MCExpr::Target: -+ return true; -+ } -+ return false; -+} -+ -+bool LoongArchAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, -+ SMLoc &EndLoc) { -+ return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success; -+} -+ -+OperandMatchResultTy LoongArchAsmParser::tryParseRegister(unsigned &RegNo, -+ SMLoc &StartLoc, -+ SMLoc &EndLoc) { -+ SmallVector, 1> Operands; -+ OperandMatchResultTy ResTy = parseAnyRegister(Operands); -+ if (ResTy == MatchOperand_Success) { -+ assert(Operands.size() == 1); -+ LoongArchOperand &Operand = static_cast(*Operands.front()); -+ StartLoc = Operand.getStartLoc(); -+ EndLoc = Operand.getEndLoc(); -+ -+ // AFAIK, we only support numeric registers and named GPR's in CFI -+ // directives. -+ // Don't worry about eating tokens before failing. Using an unrecognised -+ // register is a parse error. -+ if (Operand.isGPRAsmReg()) { -+ // Resolve to GPR32 or GPR64 appropriately. -+ RegNo = is64Bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); -+ } -+ -+ return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch -+ : MatchOperand_Success; -+ } -+ -+ assert(Operands.size() == 0); -+ return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch : MatchOperand_Success; -+} -+ -+bool LoongArchAsmParser::parseMemOffset(const MCExpr *&Res) { -+ return getParser().parseExpression(Res); -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::parseMemOperand(OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "parseMemOperand\n"); -+ const MCExpr *IdVal = nullptr; -+ SMLoc S; -+ OperandMatchResultTy Res = MatchOperand_NoMatch; -+ // First operand is the base. -+ S = Parser.getTok().getLoc(); -+ -+ Res = parseAnyRegister(Operands); -+ if (Res != MatchOperand_Success) -+ return Res; -+ -+ if (Parser.getTok().isNot(AsmToken::Comma)) { -+ Error(Parser.getTok().getLoc(), "',' expected"); -+ return MatchOperand_ParseFail; -+ } -+ -+ Parser.Lex(); // Eat the ',' token. -+ -+ if (parseMemOffset(IdVal)) -+ return MatchOperand_ParseFail; -+ -+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -+ -+ // Replace the register operand with the memory operand. -+ std::unique_ptr op( -+ static_cast(Operands.back().release())); -+ // Remove the register from the operands. -+ // "op" will be managed by k_Memory. -+ Operands.pop_back(); -+ -+ // when symbol not defined, error report. -+ if (dyn_cast(IdVal)) { -+ return MatchOperand_ParseFail; -+ } -+ -+ // Add the memory operand. -+ if (dyn_cast(IdVal)) { -+ int64_t Imm; -+ if (IdVal->evaluateAsAbsolute(Imm)) -+ IdVal = MCConstantExpr::create(Imm, getContext()); -+ else -+ return MatchOperand_ParseFail; -+ } -+ -+ Operands.push_back(LoongArchOperand::CreateMem(std::move(op), IdVal, S, E, *this)); -+ return MatchOperand_Success; -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::parseAMemOperand(OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "parseAMemOperand\n"); -+ const MCExpr *IdVal = nullptr; -+ SMLoc S; -+ OperandMatchResultTy Res = MatchOperand_NoMatch; -+ // First operand is the base. -+ S = Parser.getTok().getLoc(); -+ -+ Res = parseAnyRegister(Operands); -+ if (Res != MatchOperand_Success) -+ return Res; -+ -+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -+ -+ // AM* instructions allow an optional '0' memory offset. -+ if (Parser.getTok().is(AsmToken::Comma)) { -+ Parser.Lex(); // Eat the ',' token. -+ -+ if (parseMemOffset(IdVal)) -+ return MatchOperand_ParseFail; -+ -+ // when symbol not defined, error report. -+ if (dyn_cast(IdVal)) -+ return MatchOperand_ParseFail; -+ -+ if (dyn_cast(IdVal)) { -+ int64_t Imm; -+ if (IdVal->evaluateAsAbsolute(Imm)) { -+ assert(Imm == 0 && "imm must be 0"); -+ IdVal = MCConstantExpr::create(Imm, getContext()); -+ } else { -+ return MatchOperand_ParseFail; -+ } -+ } -+ } else { -+ // Offset defaults to 0. -+ IdVal = MCConstantExpr::create(0, getContext()); -+ } -+ -+ // Replace the register operand with the memory operand. -+ std::unique_ptr op( -+ static_cast(Operands.back().release())); -+ // Remove the register from the operands. -+ // "op" will be managed by k_Memory. -+ Operands.pop_back(); -+ // Add the memory operand. -+ Operands.push_back( -+ LoongArchOperand::CreateMem(std::move(op), IdVal, S, E, *this)); -+ return MatchOperand_Success; -+} -+ -+bool LoongArchAsmParser::searchSymbolAlias(OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); -+ if (!Sym) -+ return false; -+ -+ SMLoc S = Parser.getTok().getLoc(); -+ if (Sym->isVariable()) { -+ const MCExpr *Expr = Sym->getVariableValue(); -+ if (Expr->getKind() == MCExpr::SymbolRef) { -+ const MCSymbolRefExpr *Ref = static_cast(Expr); -+ StringRef DefSymbol = Ref->getSymbol().getName(); -+ if (DefSymbol.startswith("$")) { -+ OperandMatchResultTy ResTy = -+ matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); -+ if (ResTy == MatchOperand_Success) { -+ Parser.Lex(); -+ return true; -+ } -+ if (ResTy == MatchOperand_ParseFail) -+ llvm_unreachable("Should never ParseFail"); -+ } -+ } -+ } else if (Sym->isUnset()) { -+ // If symbol is unset, it might be created in the `parseSetAssignment` -+ // routine as an alias for a numeric register name. -+ // Lookup in the aliases list. -+ auto Entry = RegisterSets.find(Sym->getName()); -+ if (Entry != RegisterSets.end()) { -+ OperandMatchResultTy ResTy = -+ matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S); -+ if (ResTy == MatchOperand_Success) { -+ Parser.Lex(); -+ return true; -+ } -+ } -+ } -+ -+ return false; -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, -+ StringRef Identifier, -+ SMLoc S) { -+ int Index = matchCPURegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createGPRReg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ Index = matchFPURegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createFGRReg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ Index = matchFCFRRegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createFCFRReg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ Index = matchFCSRRegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createFCSRReg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ Index = matchLSX128RegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createLSX128Reg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ Index = matchLASX256RegisterName(Identifier); -+ if (Index != -1) { -+ Operands.push_back(LoongArchOperand::createLASX256Reg( -+ Index, Identifier, getContext().getRegisterInfo(), S, -+ getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ return MatchOperand_NoMatch; -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, -+ const AsmToken &Token, SMLoc S) { -+ if (Token.is(AsmToken::Identifier)) { -+ LLVM_DEBUG(dbgs() << ".. identifier\n"); -+ StringRef Identifier = Token.getIdentifier(); -+ OperandMatchResultTy ResTy = -+ matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); -+ return ResTy; -+ } else if (Token.is(AsmToken::Integer)) { -+ LLVM_DEBUG(dbgs() << ".. integer\n"); -+ int64_t RegNum = Token.getIntVal(); -+ if (RegNum < 0 || RegNum > 31) { -+ // Show the error, but treat invalid register -+ // number as a normal one to continue parsing -+ // and catch other possible errors. -+ Error(getLexer().getLoc(), "invalid register number"); -+ } -+ Operands.push_back(LoongArchOperand::createNumericReg( -+ RegNum, Token.getString(), getContext().getRegisterInfo(), S, -+ Token.getLoc(), *this)); -+ return MatchOperand_Success; -+ } -+ -+ LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); -+ -+ return MatchOperand_NoMatch; -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { -+ auto Token = getLexer().peekTok(false); -+ return matchAnyRegisterWithoutDollar(Operands, Token, S); -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::parseAnyRegister(OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); -+ -+ auto Token = Parser.getTok(); -+ -+ SMLoc S = Token.getLoc(); -+ -+ if (Token.isNot(AsmToken::Dollar)) { -+ LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); -+ if (Token.is(AsmToken::Identifier)) { -+ if (searchSymbolAlias(Operands)) -+ return MatchOperand_Success; -+ } -+ LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); -+ return MatchOperand_NoMatch; -+ } -+ LLVM_DEBUG(dbgs() << ".. $\n"); -+ -+ OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); -+ if (ResTy == MatchOperand_Success) { -+ Parser.Lex(); // $ -+ Parser.Lex(); // identifier -+ } -+ return ResTy; -+} -+ -+OperandMatchResultTy -+LoongArchAsmParser::parseJumpTarget(OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); -+ -+ SMLoc S = getLexer().getLoc(); -+ -+ // Registers are a valid target and have priority over symbols. -+ OperandMatchResultTy ResTy = parseAnyRegister(Operands); -+ if (ResTy != MatchOperand_NoMatch) -+ return ResTy; -+ -+ // Integers and expressions are acceptable -+ const MCExpr *Expr = nullptr; -+ if (Parser.parseExpression(Expr)) { -+ // We have no way of knowing if a symbol was consumed so we must ParseFail -+ return MatchOperand_ParseFail; -+ } -+ Operands.push_back( -+ LoongArchOperand::CreateImm(Expr, S, getLexer().getLoc(), *this)); -+ return MatchOperand_Success; -+} -+ -+static std::string LoongArchMnemonicSpellCheck(StringRef S, -+ const FeatureBitset &FBS, -+ unsigned VariantID = 0); -+ -+bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, -+ StringRef Name, SMLoc NameLoc, -+ OperandVector &Operands) { -+ MCAsmParser &Parser = getParser(); -+ LLVM_DEBUG(dbgs() << "ParseInstruction\n"); -+ -+ // We have reached first instruction, module directive are now forbidden. -+ getTargetStreamer().forbidModuleDirective(); -+ -+ // Check if we have valid mnemonic -+ if (!mnemonicIsValid(Name)) { -+ FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); -+ std::string Suggestion = LoongArchMnemonicSpellCheck(Name, FBS); -+ return Error(NameLoc, "unknown instruction" + Suggestion); -+ } -+ -+ // First operand in MCInst is instruction mnemonic. -+ Operands.push_back(LoongArchOperand::CreateToken(Name, NameLoc, *this)); -+ -+ // Read the remaining operands. -+ if (getLexer().isNot(AsmToken::EndOfStatement)) { -+ // Read the first operand. -+ if (parseOperand(Operands, Name)) { -+ SMLoc Loc = getLexer().getLoc(); -+ return Error(Loc, "unexpected token in argument list"); -+ } -+ -+ while (getLexer().is(AsmToken::Comma)) { -+ Parser.Lex(); // Eat the comma. -+ // Parse and remember the operand. -+ if (parseOperand(Operands, Name)) { -+ SMLoc Loc = getLexer().getLoc(); -+ return Error(Loc, "unexpected token in argument list"); -+ } -+ } -+ } -+ if (getLexer().isNot(AsmToken::EndOfStatement)) { -+ SMLoc Loc = getLexer().getLoc(); -+ return Error(Loc, "unexpected token in argument list"); -+ } -+ Parser.Lex(); // Consume the EndOfStatement. -+ return false; -+} -+ -+// FIXME: Given that these have the same name, these should both be -+// consistent on affecting the Parser. -+bool LoongArchAsmParser::reportParseError(Twine ErrorMsg) { -+ SMLoc Loc = getLexer().getLoc(); -+ return Error(Loc, ErrorMsg); -+} -+ -+bool LoongArchAsmParser::parseSetAssignment() { -+ StringRef Name; -+ const MCExpr *Value; -+ MCAsmParser &Parser = getParser(); -+ -+ if (Parser.parseIdentifier(Name)) -+ return reportParseError("expected identifier after .set"); -+ -+ if (getLexer().isNot(AsmToken::Comma)) -+ return reportParseError("unexpected token, expected comma"); -+ Lex(); // Eat comma -+ -+ if (!Parser.parseExpression(Value)) { -+ // Parse assignment of an expression including -+ // symbolic registers: -+ // .set $tmp, $BB0-$BB1 -+ // .set r2, $f2 -+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name); -+ Sym->setVariableValue(Value); -+ } else { -+ return reportParseError("expected valid expression after comma"); -+ } -+ -+ return false; -+} -+ -+bool LoongArchAsmParser::parseDirectiveSet() { -+ const AsmToken &Tok = getParser().getTok(); -+ StringRef IdVal = Tok.getString(); -+ SMLoc Loc = Tok.getLoc(); -+ -+ if (IdVal == "bopt") { -+ Warning(Loc, "'bopt' feature is unsupported"); -+ getParser().Lex(); -+ return false; -+ } -+ if (IdVal == "nobopt") { -+ // We're already running in nobopt mode, so nothing to do. -+ getParser().Lex(); -+ return false; -+ } -+ -+ // It is just an identifier, look for an assignment. -+ return parseSetAssignment(); -+} -+ -+bool LoongArchAsmParser::ParseDirective(AsmToken DirectiveID) { -+ // This returns false if this function recognizes the directive -+ // regardless of whether it is successfully handles or reports an -+ // error. Otherwise it returns true to give the generic parser a -+ // chance at recognizing it. -+ -+ MCAsmParser &Parser = getParser(); -+ StringRef IDVal = DirectiveID.getString(); -+ -+ if (IDVal == ".end") { -+ while (getLexer().isNot(AsmToken::Eof)) -+ Parser.Lex(); -+ return false; -+ } -+ -+ if (IDVal == ".set") { -+ parseDirectiveSet(); -+ return false; -+ } -+ -+ if (IDVal == ".llvm_internal_loongarch_reallow_module_directive") { -+ parseInternalDirectiveReallowModule(); -+ return false; -+ } -+ -+ return true; -+} -+ -+bool LoongArchAsmParser::parseInternalDirectiveReallowModule() { -+ // If this is not the end of the statement, report an error. -+ if (getLexer().isNot(AsmToken::EndOfStatement)) { -+ reportParseError("unexpected token, expected end of statement"); -+ return false; -+ } -+ -+ getTargetStreamer().reallowModuleDirective(); -+ -+ getParser().Lex(); // Eat EndOfStatement token. -+ return false; - } - - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { - RegisterMCAsmParser X(getTheLoongArch32Target()); -- RegisterMCAsmParser Y(getTheLoongArch64Target()); -+ RegisterMCAsmParser A(getTheLoongArch64Target()); -+} -+ -+#define GET_REGISTER_MATCHER -+#define GET_MATCHER_IMPLEMENTATION -+#define GET_MNEMONIC_SPELL_CHECKER -+#include "LoongArchGenAsmMatcher.inc" -+ -+bool LoongArchAsmParser::mnemonicIsValid(StringRef Mnemonic) { -+ // Find the appropriate table for this asm variant. -+ const MatchEntry *Start, *End; -+ Start = std::begin(MatchTable0); -+ End = std::end(MatchTable0); -+ -+ // Search the table. -+ auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode()); -+ return MnemonicRange.first != MnemonicRange.second; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt -index 4d8e81aea..8540b97ff 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt -@@ -1,14 +1,15 @@ --add_llvm_component_group(LoongArch) -+add_llvm_component_group(LoongArch HAS_JIT) - - set(LLVM_TARGET_DEFINITIONS LoongArch.td) - - tablegen(LLVM LoongArchGenAsmMatcher.inc -gen-asm-matcher) - tablegen(LLVM LoongArchGenAsmWriter.inc -gen-asm-writer) -+tablegen(LLVM LoongArchGenCallingConv.inc -gen-callingconv) - tablegen(LLVM LoongArchGenDAGISel.inc -gen-dag-isel) - tablegen(LLVM LoongArchGenDisassemblerTables.inc -gen-disassembler) - tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info) --tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering) - tablegen(LLVM LoongArchGenMCCodeEmitter.inc -gen-emitter) -+tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering) - tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info) - tablegen(LLVM LoongArchGenSubtargetInfo.inc -gen-subtarget) - -@@ -16,14 +17,20 @@ add_public_tablegen_target(LoongArchCommonTableGen) - - add_llvm_target(LoongArchCodeGen - LoongArchAsmPrinter.cpp -- LoongArchFrameLowering.cpp -+ LoongArchCCState.cpp -+ LoongArchExpandPseudo.cpp - LoongArchInstrInfo.cpp - LoongArchISelDAGToDAG.cpp - LoongArchISelLowering.cpp -+ LoongArchFrameLowering.cpp - LoongArchMCInstLower.cpp -+ LoongArchMachineFunction.cpp -+ LoongArchModuleISelDAGToDAG.cpp - LoongArchRegisterInfo.cpp - LoongArchSubtarget.cpp - LoongArchTargetMachine.cpp -+ LoongArchTargetObjectFile.cpp -+ LoongArchTargetTransformInfo.cpp - - LINK_COMPONENTS - Analysis -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt -index 1cce676cf..864be6313 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt -@@ -2,10 +2,8 @@ add_llvm_component_library(LLVMLoongArchDisassembler - LoongArchDisassembler.cpp - - LINK_COMPONENTS -- LoongArchDesc -- LoongArchInfo -- MC - MCDisassembler -+ LoongArchInfo - Support - - ADD_TO_COMPONENT -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp -index beb757c78..6468a0fc8 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===// -+//===- LoongArchDisassembler.cpp - Disassembler for LoongArch -----------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,140 +6,935 @@ - // - //===----------------------------------------------------------------------===// - // --// This file implements the LoongArchDisassembler class. -+// This file is part of the LoongArch Disassembler. - // - //===----------------------------------------------------------------------===// - --#include "MCTargetDesc/LoongArchBaseInfo.h" - #include "MCTargetDesc/LoongArchMCTargetDesc.h" --#include "TargetInfo/LoongArchTargetInfo.h" -+#include "LoongArch.h" -+#include "llvm/ADT/ArrayRef.h" - #include "llvm/MC/MCContext.h" - #include "llvm/MC/MCDecoderOps.h" - #include "llvm/MC/MCDisassembler/MCDisassembler.h" - #include "llvm/MC/MCInst.h" --#include "llvm/MC/MCInstrInfo.h" - #include "llvm/MC/MCRegisterInfo.h" - #include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/Support/Compiler.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MathExtras.h" - #include "llvm/MC/TargetRegistry.h" --#include "llvm/Support/Endian.h" -+#include "llvm/Support/raw_ostream.h" -+#include -+#include - - using namespace llvm; - - #define DEBUG_TYPE "loongarch-disassembler" - --typedef MCDisassembler::DecodeStatus DecodeStatus; -+using DecodeStatus = MCDisassembler::DecodeStatus; - - namespace { -+ - class LoongArchDisassembler : public MCDisassembler { -+ - public: - LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) - : MCDisassembler(STI, Ctx) {} - -+ bool isFP64() const { return STI.getFeatureBits()[LoongArch::FeatureFP64Bit]; } -+ -+ bool is64Bit() const { return STI.getFeatureBits()[LoongArch::Feature64Bit]; } -+ - DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef Bytes, uint64_t Address, - raw_ostream &CStream) const override; - }; --} // end namespace - --static MCDisassembler *createLoongArchDisassembler(const Target &T, -- const MCSubtargetInfo &STI, -- MCContext &Ctx) { -+} // end anonymous namespace -+ -+// Forward declare these because the autogenerated code will reference them. -+// Definitions are further down. -+static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeFCFRRegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLSX128BRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLSX128HRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLSX128WRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLSX128DRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLASX256BRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLASX256HRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLASX256WRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLASX256DRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeBranchTarget(MCInst &Inst, -+ unsigned Offset, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeJumpTarget(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeMem(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeAMem(MCInst &Inst, unsigned Insn, uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeMemSimm14(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder); -+ -+static DecodeStatus DecodeLSX128Mem(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLSX128Mem13(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLSX128Mem10(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLASX256Mem13(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLASX256Mem10(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLSX128memlsl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLSX128memstl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLASX256memlsl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLASX256memstl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeLASX256Mem(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder); -+ -+static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, -+ uint64_t Address, -+ const void *Decoder); -+ -+template -+static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, -+ uint64_t Address, -+ const void *Decoder); -+ -+template -+static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value, -+ uint64_t Address, -+ const void *Decoder) { -+ return DecodeUImmWithOffsetAndScale(Inst, Value, Address, -+ Decoder); -+} -+ -+template -+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, -+ uint64_t Address, -+ const void *Decoder); -+ -+/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't -+/// handle. -+template -+static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, -+ const void *Decoder); -+ -+namespace llvm { -+ -+Target &getTheLoongArch32Target(); -+Target &getTheLoongArch64Target(); -+ -+} // end namespace llvm -+ -+static MCDisassembler *createLoongArchDisassembler( -+ const Target &T, -+ const MCSubtargetInfo &STI, -+ MCContext &Ctx) { - return new LoongArchDisassembler(STI, Ctx); - } - - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() { -- // Register the disassembler for each target. -+ // Register the disassembler. - TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(), - createLoongArchDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(), - createLoongArchDisassembler); - } - --static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, -- uint64_t Address, -- const MCDisassembler *Decoder) { -- if (RegNo >= 32) -+#include "LoongArchGenDisassemblerTables.inc" -+ -+static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { -+ const LoongArchDisassembler *Dis = static_cast(D); -+ const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); -+ if (RC == LoongArch::GPR64RegClassID || RC == LoongArch::GPR32RegClassID) { -+ // sync with the GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td -+ // that just like LoongArchAsmParser.cpp and LoongArchISelLowering.cpp -+ unsigned char indexes[] = { 0, 27, 28, 29, 1, 2, 3, 4, -+ 5, 6, 7, 8, 9, 10, 11, 12, -+ 13, 14, 15, 16, 17, 30, 31, 18, -+ 19, 20, 21, 22, 23, 24, 25, 26 -+ }; -+ assert(RegNo < sizeof(indexes)); -+ return *(RegInfo->getRegClass(RC).begin() + indexes[RegNo]); -+ } -+ return *(RegInfo->getRegClass(RC).begin() + RegNo); -+} -+ -+template -+static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, -+ const void *Decoder) { -+ using DecodeFN = DecodeStatus (*)(MCInst &, unsigned, uint64_t, const void *); -+ -+ // The size of the n field depends on the element size -+ // The register class also depends on this. -+ InsnType tmp = fieldFromInstruction(insn, 17, 5); -+ unsigned NSize = 0; -+ DecodeFN RegDecoder = nullptr; -+ if ((tmp & 0x18) == 0x00) { -+ NSize = 4; -+ RegDecoder = DecodeLSX128BRegisterClass; -+ } else if ((tmp & 0x1c) == 0x10) { -+ NSize = 3; -+ RegDecoder = DecodeLSX128HRegisterClass; -+ } else if ((tmp & 0x1e) == 0x18) { -+ NSize = 2; -+ RegDecoder = DecodeLSX128WRegisterClass; -+ } else if ((tmp & 0x1f) == 0x1c) { -+ NSize = 1; -+ RegDecoder = DecodeLSX128DRegisterClass; -+ } else -+ llvm_unreachable("Invalid encoding"); -+ -+ assert(NSize != 0 && RegDecoder != nullptr); -+ -+ // $vd -+ tmp = fieldFromInstruction(insn, 6, 5); -+ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) -+ return MCDisassembler::Fail; -+ // $vd_in -+ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) -+ return MCDisassembler::Fail; -+ // $n -+ tmp = fieldFromInstruction(insn, 16, NSize); -+ MI.addOperand(MCOperand::createImm(tmp)); -+ // $vs -+ tmp = fieldFromInstruction(insn, 11, 5); -+ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) -+ return MCDisassembler::Fail; -+ // $n2 -+ MI.addOperand(MCOperand::createImm(0)); -+ -+ return MCDisassembler::Success; -+} -+ -+/// Read four bytes from the ArrayRef and return 32 bit word. -+static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, -+ uint64_t &Size, uint32_t &Insn) { -+ // We want to read exactly 4 Bytes of data. -+ if (Bytes.size() < 4) { -+ Size = 0; - return MCDisassembler::Fail; -- Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo)); -+ } -+ -+ Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | -+ (Bytes[3] << 24); -+ - return MCDisassembler::Success; - } - --static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, -+DecodeStatus LoongArchDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, -+ ArrayRef Bytes, -+ uint64_t Address, -+ raw_ostream &CStream) const { -+ uint32_t Insn; -+ DecodeStatus Result; -+ Size = 0; -+ -+ // Attempt to read the instruction so that we can attempt to decode it. If -+ // the buffer is not 4 bytes long, let the higher level logic figure out -+ // what to do with a size of zero and MCDisassembler::Fail. -+ Result = readInstruction32(Bytes, Address, Size, Insn); -+ if (Result == MCDisassembler::Fail) -+ return MCDisassembler::Fail; -+ -+ // The only instruction size for standard encoded LoongArch. -+ Size = 4; -+ -+ if (is64Bit()) { -+ LLVM_DEBUG(dbgs() << "Trying LoongArch (GPR64) table (32-bit opcodes):\n"); -+ Result = decodeInstruction(DecoderTableLoongArch32, Instr, Insn, -+ Address, this, STI); -+ if (Result != MCDisassembler::Fail) -+ return Result; -+ } -+ -+ LLVM_DEBUG(dbgs() << "Trying LoongArch32 (GPR32) table (32-bit opcodes):\n"); -+ Result = decodeInstruction(DecoderTableLoongArch3232, Instr, Insn, -+ Address, this, STI); -+ if (Result != MCDisassembler::Fail) -+ return Result; -+ -+ return MCDisassembler::Fail; -+} -+ -+static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, -+ unsigned RegNo, - uint64_t Address, -- const MCDisassembler *Decoder) { -- if (RegNo >= 32) -+ const void *Decoder) { -+ if (RegNo > 31) - return MCDisassembler::Fail; -- Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo)); -+ -+ unsigned Reg = getReg(Decoder, LoongArch::GPR64RegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; - } - --static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, -+static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, -+ unsigned RegNo, - uint64_t Address, -- const MCDisassembler *Decoder) { -- if (RegNo >= 32) -+ const void *Decoder) { -+ if (RegNo > 31) - return MCDisassembler::Fail; -- Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo)); -+ unsigned Reg = getReg(Decoder, LoongArch::GPR32RegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; - } - --static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo, -+static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, -+ unsigned RegNo, - uint64_t Address, -- const MCDisassembler *Decoder) { -- if (RegNo >= 8) -+ const void *Decoder) { -+ if (static_cast(Decoder)->is64Bit()) -+ return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); -+ -+ return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); -+} -+ -+static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) - return MCDisassembler::Fail; -- Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo)); -+ unsigned Reg = getReg(Decoder, LoongArch::FGR64RegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; - } - --static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo, -+static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ -+ unsigned Reg = getReg(Decoder, LoongArch::FGR32RegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, -+ unsigned RegNo, - uint64_t Address, -- const MCDisassembler *Decoder) { -- if (RegNo >= 4) -+ const void *Decoder) { -+ if (RegNo > 31) - return MCDisassembler::Fail; -- Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo)); -+ -+ unsigned Reg = getReg(Decoder, LoongArch::FCSRRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; - } - --template --static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, -- int64_t Address, -- const MCDisassembler *Decoder) { -- assert(isUInt(Imm) && "Invalid immediate"); -- Inst.addOperand(MCOperand::createImm(Imm + P)); -+static DecodeStatus DecodeFCFRRegisterClass(MCInst &Inst, -+ unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 7) -+ return MCDisassembler::Fail; -+ -+ unsigned Reg = getReg(Decoder, LoongArch::FCFRRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ - return MCDisassembler::Success; - } - --template --static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, -- int64_t Address, -- const MCDisassembler *Decoder) { -- assert(isUInt(Imm) && "Invalid immediate"); -- // Sign-extend the number in the bottom bits of Imm, then shift left -- // bits. -- Inst.addOperand(MCOperand::createImm(SignExtend64(Imm) << S)); -+static DecodeStatus DecodeMem(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder) { -+ int Offset = SignExtend32<12>((Insn >> 10) & 0xfff); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ -+ Reg = getReg(Decoder, LoongArch::GPR32RegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ if (Inst.getOpcode() == LoongArch::SC_W || -+ Inst.getOpcode() == LoongArch::SC_D) -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ - return MCDisassembler::Success; - } - --#include "LoongArchGenDisassemblerTables.inc" -+static DecodeStatus DecodeAMem(MCInst &Inst, unsigned Insn, uint64_t Address, -+ const void *Decoder) { -+ unsigned Rd = fieldFromInstruction(Insn, 0, 5); -+ unsigned Rj = fieldFromInstruction(Insn, 5, 5); -+ unsigned Rk = fieldFromInstruction(Insn, 10, 5); - --DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size, -- ArrayRef Bytes, -- uint64_t Address, -- raw_ostream &CS) const { -- uint32_t Insn; -- DecodeStatus Result; -+ Rd = getReg(Decoder, LoongArch::GPR32RegClassID, Rd); -+ Rj = getReg(Decoder, LoongArch::GPR32RegClassID, Rj); -+ Rk = getReg(Decoder, LoongArch::GPR32RegClassID, Rk); - -- // We want to read exactly 4 bytes of data because all LoongArch instructions -- // are fixed 32 bits. -- if (Bytes.size() < 4) { -- Size = 0; -+ // Note the operands sequence is "rd,rk,rj". -+ Inst.addOperand(MCOperand::createReg(Rd)); -+ Inst.addOperand(MCOperand::createReg(Rk)); -+ Inst.addOperand(MCOperand::createReg(Rj)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeMemSimm14(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder) { -+ int Offset = SignExtend32<12>((Insn >> 10) & 0x3fff); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ -+ Reg = getReg(Decoder, LoongArch::GPR32RegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ if (Inst.getOpcode() == LoongArch::SC_W || -+ Inst.getOpcode() == LoongArch::SC_D) -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128Mem(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128Mem13(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<13>(fieldFromInstruction(Insn, 5, 13)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128Mem10(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 5, 10)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256Mem13(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<13>(fieldFromInstruction(Insn, 5, 13)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256Mem10(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 5, 10)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128memstl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<8>(fieldFromInstruction(Insn, 10, 8)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ unsigned idx; -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ switch (Inst.getOpcode()) { -+ default: -+ assert(false && "Unexpected instruction"); - return MCDisassembler::Fail; -+ break; -+ case LoongArch::VSTELM_B: -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ idx = fieldFromInstruction(Insn, 18, 4); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::VSTELM_H: -+ Inst.addOperand(MCOperand::createImm(Offset * 2)); -+ idx = fieldFromInstruction(Insn, 18, 3); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::VSTELM_W: -+ Inst.addOperand(MCOperand::createImm(Offset * 4)); -+ idx = fieldFromInstruction(Insn, 18, 2); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::VSTELM_D: -+ Inst.addOperand(MCOperand::createImm(Offset * 8)); -+ idx = fieldFromInstruction(Insn, 18, 1); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; - } - -- Insn = support::endian::read32le(Bytes.data()); -- // Calling the auto-generated decoder function. -- Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); -- Size = 4; -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128memlsl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ -+ int Offset; -+ unsigned Reg, Base; -+ switch (Inst.getOpcode()) { -+ default: -+ assert(false && "Unexpected instruction"); -+ return MCDisassembler::Fail; -+ break; -+ case LoongArch::VLDREPL_B: -+ -+ Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ break; -+ case LoongArch::VLDREPL_H: -+ -+ Offset = SignExtend32<11>(fieldFromInstruction(Insn, 10, 11)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128HRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 2)); -+ break; -+ case LoongArch::VLDREPL_W: -+ -+ Offset = SignExtend32<10>(fieldFromInstruction(Insn, 10, 10)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 4)); -+ break; -+ case LoongArch::VLDREPL_D: -+ -+ Offset = SignExtend32<9>(fieldFromInstruction(Insn, 10, 9)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 8)); -+ break; -+ } -+ -+ return MCDisassembler::Success; -+} -+static DecodeStatus DecodeLASX256Mem(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256memstl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { -+ int Offset = SignExtend32<8>(fieldFromInstruction(Insn, 10, 8)); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ unsigned idx; -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ switch (Inst.getOpcode()) { -+ default: -+ assert(false && "Unexpected instruction"); -+ return MCDisassembler::Fail; -+ break; -+ case LoongArch::XVSTELM_B: -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ idx = fieldFromInstruction(Insn, 18, 5); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::XVSTELM_H: -+ Inst.addOperand(MCOperand::createImm(Offset * 2)); -+ idx = fieldFromInstruction(Insn, 18, 4); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::XVSTELM_W: -+ Inst.addOperand(MCOperand::createImm(Offset * 4)); -+ idx = fieldFromInstruction(Insn, 18, 3); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ case LoongArch::XVSTELM_D: -+ Inst.addOperand(MCOperand::createImm(Offset * 8)); -+ idx = fieldFromInstruction(Insn, 18, 2); -+ Inst.addOperand(MCOperand::createImm(idx)); -+ break; -+ } -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256memlsl(MCInst &Inst, unsigned Insn, -+ uint64_t Address, const void *Decoder) { - -- return Result; -+ int Offset; -+ unsigned Reg, Base; -+ switch (Inst.getOpcode()) { -+ default: -+ assert(false && "Unexpected instruction"); -+ return MCDisassembler::Fail; -+ break; -+ case LoongArch::XVLDREPL_B: -+ -+ Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ break; -+ case LoongArch::XVLDREPL_H: -+ -+ Offset = SignExtend32<11>(fieldFromInstruction(Insn, 10, 11)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256HRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 2)); -+ break; -+ case LoongArch::XVLDREPL_W: -+ -+ Offset = SignExtend32<10>(fieldFromInstruction(Insn, 10, 10)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 4)); -+ break; -+ case LoongArch::XVLDREPL_D: -+ -+ Offset = SignExtend32<9>(fieldFromInstruction(Insn, 10, 9)); -+ Reg = fieldFromInstruction(Insn, 0, 5); -+ Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset * 8)); -+ break; -+ } -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeFMem(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder) { -+ int Offset = SignExtend32<12>((Insn >> 10) & 0xffff); -+ unsigned Reg = fieldFromInstruction(Insn, 0, 5); -+ unsigned Base = fieldFromInstruction(Insn, 5, 5); -+ Reg = getReg(Decoder, LoongArch::FGR64RegClassID, Reg); -+ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); -+ -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ Inst.addOperand(MCOperand::createReg(Base)); -+ Inst.addOperand(MCOperand::createImm(Offset)); -+ -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128BRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128HRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LSX128HRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128WRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLSX128DRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LSX128DRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256BRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256HRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LASX256HRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256WRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeLASX256DRegisterClass(MCInst &Inst, unsigned RegNo, -+ uint64_t Address, -+ const void *Decoder) { -+ if (RegNo > 31) -+ return MCDisassembler::Fail; -+ unsigned Reg = getReg(Decoder, LoongArch::LASX256DRegClassID, RegNo); -+ Inst.addOperand(MCOperand::createReg(Reg)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeBranchTarget(MCInst &Inst, -+ unsigned Offset, -+ uint64_t Address, -+ const void *Decoder) { -+ int32_t BranchOffset; -+ // Similar to LoongArchAsmParser::processInstruction, decode the branch target -+ // for different instructions. -+ switch (Inst.getOpcode()) { -+ default: -+ llvm_unreachable(""); -+ case LoongArch::BEQ: -+ case LoongArch::BNE: -+ case LoongArch::BLT: -+ case LoongArch::BGE: -+ case LoongArch::BLTU: -+ case LoongArch::BGEU: -+ BranchOffset = (SignExtend32<16>(Offset) * 4); -+ break; -+ case LoongArch::BEQZ: -+ case LoongArch::BNEZ: -+ case LoongArch::BCEQZ: -+ case LoongArch::BCNEZ: -+ BranchOffset = (SignExtend32<21>(Offset) * 4); -+ break; -+ case LoongArch::B: -+ case LoongArch::BL: -+ BranchOffset = (SignExtend32<26>(Offset) * 4); -+ break; -+ } -+ Inst.addOperand(MCOperand::createImm(BranchOffset)); -+ return MCDisassembler::Success; -+} -+ -+static DecodeStatus DecodeJumpTarget(MCInst &Inst, -+ unsigned Insn, -+ uint64_t Address, -+ const void *Decoder) { -+ unsigned hi10 = fieldFromInstruction(Insn, 0, 10); -+ unsigned lo16 = fieldFromInstruction(Insn, 10, 16); -+ int32_t JumpOffset = SignExtend32<28>((hi10 << 16 | lo16) << 2); -+ Inst.addOperand(MCOperand::createImm(JumpOffset)); -+ return MCDisassembler::Success; -+} -+ -+template -+static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, -+ uint64_t Address, -+ const void *Decoder) { -+ Value &= ((1 << Bits) - 1); -+ Value *= Scale; -+ Inst.addOperand(MCOperand::createImm(Value + Offset)); -+ return MCDisassembler::Success; -+} -+ -+template -+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, -+ uint64_t Address, -+ const void *Decoder) { -+ int32_t Imm = SignExtend32(Value) * ScaleBy; -+ Inst.addOperand(MCOperand::createImm(Imm + Offset)); -+ return MCDisassembler::Success; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h -index e6c9c24dd..73fd4a628 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h -@@ -1,4 +1,4 @@ --//===-- LoongArch.h - Top-level interface for LoongArch ---------*- C++ -*-===// -+//===-- LoongArch.h - Top-level interface for LoongArch representation ----*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,33 +6,32 @@ - // - //===----------------------------------------------------------------------===// - // --// This file contains the entry points for global functions defined in the LLVM --// LoongArch back-end. -+// This file contains the entry points for global functions defined in -+// the LLVM LoongArch back-end. - // - //===----------------------------------------------------------------------===// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H - --#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" - #include "llvm/Target/TargetMachine.h" - - namespace llvm { --class LoongArchTargetMachine; --class AsmPrinter; --class FunctionPass; --class MCInst; --class MCOperand; --class MachineInstr; --class MachineOperand; -+ class LoongArchTargetMachine; -+ class ModulePass; -+ class FunctionPass; -+ class LoongArchSubtarget; -+ class LoongArchTargetMachine; -+ class InstructionSelector; -+ class PassRegistry; - --bool lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, -- AsmPrinter &AP); --bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, -- MCOperand &MCOp, -- const AsmPrinter &AP); -+ FunctionPass *createLoongArchModuleISelDagPass(); -+ FunctionPass *createLoongArchOptimizePICCallPass(); -+ FunctionPass *createLoongArchBranchExpansion(); -+ FunctionPass *createLoongArchExpandPseudoPass(); - --FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM); --} // end namespace llvm -+ void initializeLoongArchBranchExpansionPass(PassRegistry &); -+} // end namespace llvm; - --#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td -index bf465c27e..703c1ba50 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td -@@ -1,139 +1,107 @@ --//===-- LoongArch.td - Describe the LoongArch Target -------*- tablegen -*-===// -+//===-- LoongArch.td - Describe the LoongArch Target Machine ---------*- tablegen -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. - // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - // - //===----------------------------------------------------------------------===// -+// This is the top level entry point for the LoongArch target. -+//===----------------------------------------------------------------------===// -+ -+//===----------------------------------------------------------------------===// -+// Target-independent interfaces -+//===----------------------------------------------------------------------===// - - include "llvm/Target/Target.td" - -+// The overall idea of the PredicateControl class is to chop the Predicates list -+// into subsets that are usually overridden independently. This allows -+// subclasses to partially override the predicates of their superclasses without -+// having to re-add all the existing predicates. -+class PredicateControl { -+ // Predicates for the encoding scheme in use such as HasStdEnc -+ list EncodingPredicates = []; -+ // Predicates for the GPR size such as is64Bit -+ list GPRPredicates = []; -+ // Predicates for the FGR size and layout such as IsFP64bit -+ list FGRPredicates = []; -+ // Predicates for the instruction group membership such as ISA's. -+ list InsnPredicates = []; -+ // Predicate for the ISA extension that an instruction belongs to. -+ list ExtPredicate = []; -+ // Predicate for marking the instruction as usable in hard-float mode only. -+ list HardFloatPredicate = []; -+ // Predicates for anything else -+ list AdditionalPredicates = []; -+ list Predicates = !listconcat(EncodingPredicates, -+ GPRPredicates, -+ FGRPredicates, -+ InsnPredicates, -+ HardFloatPredicate, -+ ExtPredicate, -+ AdditionalPredicates); -+} -+ -+// Like Requires<> but for the AdditionalPredicates list -+class AdditionalRequires preds> { -+ list AdditionalPredicates = preds; -+} -+ - //===----------------------------------------------------------------------===// --// LoongArch subtarget features and instruction predicates. -+// LoongArch Subtarget features // - //===----------------------------------------------------------------------===// - --// LoongArch is divided into two versions, the 32-bit version (LA32) and the --// 64-bit version (LA64). --def Feature64Bit -- : SubtargetFeature<"64bit", "HasLA64", "true", -- "LA64 Basic Integer and Privilege Instruction Set">; --def IsLA64 -- : Predicate<"Subtarget->is64Bit()">, -- AssemblerPredicate<(all_of Feature64Bit), -- "LA64 Basic Integer and Privilege Instruction Set">; --def IsLA32 -- : Predicate<"!Subtarget->is64Bit()">, -- AssemblerPredicate<(all_of(not Feature64Bit)), -- "LA32 Basic Integer and Privilege Instruction Set">; -- --defvar LA32 = DefaultMode; --def LA64 : HwMode<"+64bit">; -- --// Single Precision floating point --def FeatureBasicF -- : SubtargetFeature<"f", "HasBasicF", "true", -- "'F' (Single-Precision Floating-Point)">; --def HasBasicF -- : Predicate<"Subtarget->hasBasicF()">, -- AssemblerPredicate<(all_of FeatureBasicF), -- "'F' (Single-Precision Floating-Point)">; -- --// Double Precision floating point --def FeatureBasicD -- : SubtargetFeature<"d", "HasBasicD", "true", -- "'D' (Double-Precision Floating-Point)", -- [FeatureBasicF]>; --def HasBasicD -- : Predicate<"Subtarget->hasBasicD()">, -- AssemblerPredicate<(all_of FeatureBasicD), -- "'D' (Double-Precision Floating-Point)">; -- --// Loongson SIMD eXtension (LSX) --def FeatureExtLSX -- : SubtargetFeature<"lsx", "HasExtLSX", "true", -- "'LSX' (Loongson SIMD Extension)", [FeatureBasicD]>; --def HasExtLSX -- : Predicate<"Subtarget->hasExtLSX()">, -- AssemblerPredicate<(all_of FeatureExtLSX), -- "'LSX' (Loongson SIMD Extension)">; -- --// Loongson Advanced SIMD eXtension (LASX) --def FeatureExtLASX -- : SubtargetFeature<"lasx", "HasExtLASX", "true", -- "'LASX' (Loongson Advanced SIMD Extension)", -- [FeatureExtLSX]>; --def HasExtLASX -- : Predicate<"Subtarget->hasExtLASX()">, -- AssemblerPredicate<(all_of FeatureExtLASX), -- "'LASX' (Loongson Advanced SIMD Extension)">; -- --// Loongson VirtualiZation (LVZ) --def FeatureExtLVZ -- : SubtargetFeature<"lvz", "HasExtLVZ", "true", -- "'LVZ' (Loongson Virtualization Extension)">; --def HasExtLVZ -- : Predicate<"Subtarget->hasExtLVZ()">, -- AssemblerPredicate<(all_of FeatureExtLVZ), -- "'LVZ' (Loongson Virtualization Extension)">; -- --// Loongson Binary Translation (LBT) --def FeatureExtLBT -- : SubtargetFeature<"lbt", "HasExtLBT", "true", -- "'LBT' (Loongson Binary Translation Extension)">; --def HasExtLBT -- : Predicate<"Subtarget->hasExtLBT()">, -- AssemblerPredicate<(all_of FeatureExtLBT), -- "'LBT' (Loongson Binary Translation Extension)">; -- -+def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", -+ "Support 64-bit FP registers">; -+def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", -+ "true", "Only supports single precision float">; -+def FeatureSoftFloat : SubtargetFeature<"soft-float", "IsSoftFloat", "true", -+ "Does not support floating point instructions">; -+def Feature64Bit : SubtargetFeature<"64bit", "HasLA64", "true", -+ "Support LA64 ISA", -+ [FeatureFP64Bit]>; -+def FeatureLSX : SubtargetFeature<"lsx", "HasLSX", "true", "Support LSX">; -+ -+def FeatureLASX : SubtargetFeature<"lasx", "HasLASX", "true", "Support LASX", [FeatureLSX]>; -+ -+def FeatureUnalignedAccess -+ : SubtargetFeature<"unaligned-access", "UnalignedAccess", "true", -+ "Allow all unaligned memory access">; - //===----------------------------------------------------------------------===// --// Registers, instruction descriptions ... -+// Register File, Calling Conv, Instruction Descriptions - //===----------------------------------------------------------------------===// - - include "LoongArchRegisterInfo.td" --include "LoongArchCallingConv.td" - include "LoongArchInstrInfo.td" -+include "LoongArchCallingConv.td" -+ -+def LoongArchInstrInfo : InstrInfo; - - //===----------------------------------------------------------------------===// - // LoongArch processors supported. - //===----------------------------------------------------------------------===// - --def : ProcessorModel<"generic-la32", NoSchedModel, []>; --def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit]>; -+def : ProcessorModel<"la264", NoSchedModel, [Feature64Bit]>; - --def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit, -- FeatureExtLASX, -- FeatureExtLVZ, -- FeatureExtLBT]>; -+def : ProcessorModel<"la364", NoSchedModel, [Feature64Bit]>; - --//===----------------------------------------------------------------------===// --// Define the LoongArch target. --//===----------------------------------------------------------------------===// -- --def LoongArchInstrInfo : InstrInfo { -- // guess mayLoad, mayStore, and hasSideEffects -- // This option is a temporary migration help. It will go away. -- let guessInstructionProperties = 1; --} -+def : ProcessorModel<"la464", NoSchedModel, -+ [Feature64Bit, FeatureUnalignedAccess]>; - - def LoongArchAsmParser : AsmParser { -- let ShouldEmitMatchRegisterAltName = 1; -- let AllowDuplicateRegisterNames = 1; -+ let ShouldEmitMatchRegisterName = 0; - } - - def LoongArchAsmParserVariant : AsmParserVariant { - int Variant = 0; -+ - // Recognize hard coded registers. - string RegisterPrefix = "$"; - } - --def LoongArchAsmWriter : AsmWriter { -- int PassSubtarget = 1; --} -- - def LoongArch : Target { - let InstructionSet = LoongArchInstrInfo; - let AssemblyParsers = [LoongArchAsmParser]; - let AssemblyParserVariants = [LoongArchAsmParserVariant]; -- let AssemblyWriters = [LoongArchAsmWriter]; - let AllowRegisterRenaming = 1; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td -new file mode 100644 -index 000000000..f53471995 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td -@@ -0,0 +1,717 @@ -+//===- LoongArch32InstrInfo.td - Target Description for LoongArch Target -*- tablegen -*-=// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file describes LoongArch32 instructions. -+// -+//===----------------------------------------------------------------------===// -+ -+//===---------------------------------------------------------------------===/ -+// Instruction Definitions. -+//===---------------------------------------------------------------------===/ -+ -+let DecoderNamespace = "LoongArch32" in { -+ /// -+ /// R2 -+ /// -+ def CLO_W : Count1<"clo.w", GPR32Opnd, ctlz>, R2I<0b00100>; -+ def CLZ_W : Int_Reg2<"clz.w", GPR32Opnd, ctlz>, R2I<0b00101>; -+ def CTO_W : Count1<"cto.w", GPR32Opnd, cttz>, R2I<0b00110>; -+ def CTZ_W : Int_Reg2<"ctz.w", GPR32Opnd, cttz>, R2I<0b00111>; -+ -+ def REVB_2H : Int_Reg2<"revb.2h", GPR32Opnd>, R2I<0b01100>;//see below bswap pattern -+ -+ def BITREV_4B : Int_Reg2<"bitrev.4b", GPR32Opnd>, R2I<0b10010>; -+ def BITREV_W : Int_Reg2<"bitrev.w", GPR32Opnd, bitreverse>, R2I<0b10100>; -+ -+ let isCodeGenOnly = 1 in { -+ def EXT_W_H32 : SignExtInReg<"ext.w.h", GPR32Opnd, i16>, R2I<0b10110>; -+ def EXT_W_B32 : SignExtInReg<"ext.w.b", GPR32Opnd, i8>, R2I<0b10111>; -+ -+ } -+ -+ def CPUCFG : Int_Reg2<"cpucfg", GPR32Opnd, int_loongarch_cpucfg>, R2I<0b11011>; -+ def RDTIMEL_W32 : Int_Reg2_Rdtime<"rdtimel.w", GPR32Opnd>, R2I<0b11000>; -+ def RDTIMEH_W32 : Int_Reg2_Rdtime<"rdtimeh.w", GPR32Opnd>, R2I<0b11001>; -+ -+ /// -+ /// R3 -+ /// -+ def ADD_W : Int_Reg3<"add.w", GPR32Opnd, add>, R3I<0b0100000>; -+ def SUB_W : Int_Reg3<"sub.w", GPR32Opnd, sub>, R3I<0b0100010>; -+ -+ let isCodeGenOnly = 1 in { -+ def SLT32 : SetCC_R<"slt", GPR32Opnd, setlt>, R3I<0b0100100>; -+ def SLTU32 : SetCC_R<"sltu", GPR32Opnd, setult>, R3I<0b0100101>; -+ def MASKEQZ32 : Int_Reg3<"maskeqz", GPR32Opnd>, R3I<0b0100110>;//see below patterns -+ def MASKNEZ32 : Int_Reg3<"masknez", GPR32Opnd>, R3I<0b0100111>;//see below patterns -+ -+ def NOR32 : Nor<"nor", GPR32Opnd>, R3I<0b0101000>; -+ def AND32 : Int_Reg3<"and", GPR32Opnd, and>, R3I<0b0101001>; -+ def OR32 : Int_Reg3<"or", GPR32Opnd, or>, R3I<0b0101010>; -+ def XOR32 : Int_Reg3<"xor", GPR32Opnd, xor>, R3I<0b0101011>; -+ def ANDN32 : Int_Reg3<"andn", GPR32Opnd>, R3I<0b0101101>; -+ def ORN32 : Int_Reg3<"orn", GPR32Opnd>, R3I<0b0101100>; -+ } -+ -+ def SLL_W : Shift_Var<"sll.w", GPR32Opnd, shl>, R3I<0b0101110>; -+ def SRL_W : Shift_Var<"srl.w", GPR32Opnd, srl>, R3I<0b0101111>; -+ def SRA_W : Shift_Var<"sra.w", GPR32Opnd, sra>, R3I<0b0110000>; -+ def ROTR_W: Shift_Var<"rotr.w", GPR32Opnd, rotr>, R3I<0b0110110>; -+ -+ def MUL_W : Int_Reg3<"mul.w", GPR32Opnd, mul>, R3I<0b0111000>; -+ def MULH_W : Int_Reg3<"mulh.w", GPR32Opnd, mulhs>, R3I<0b0111001>; -+ def MULH_WU : Int_Reg3<"mulh.wu", GPR32Opnd, mulhu>, R3I<0b0111010>; -+ -+let usesCustomInserter = 1 in { -+ def DIV_W : Int_Reg3<"div.w", GPR32Opnd, sdiv>, R3I<0b1000000>; -+ def MOD_W : Int_Reg3<"mod.w", GPR32Opnd, srem>, R3I<0b1000001>; -+ def DIV_WU : Int_Reg3<"div.wu", GPR32Opnd, udiv>, R3I<0b1000010>; -+ def MOD_WU : Int_Reg3<"mod.wu", GPR32Opnd, urem>, R3I<0b1000011>; -+} -+ -+ def CRC_W_B_W : Int_Reg3<"crc.w.b.w", GPR32Opnd, int_loongarch_crc_w_b_w>, R3I<0b1001000>; -+ def CRC_W_H_W : Int_Reg3<"crc.w.h.w", GPR32Opnd, int_loongarch_crc_w_h_w>, R3I<0b1001001>; -+ def CRC_W_W_W : Int_Reg3<"crc.w.w.w", GPR32Opnd, int_loongarch_crc_w_w_w>, R3I<0b1001010>; -+ def CRCC_W_B_W : Int_Reg3<"crcc.w.b.w", GPR32Opnd, int_loongarch_crcc_w_b_w>, R3I<0b1001100>; -+ def CRCC_W_H_W : Int_Reg3<"crcc.w.h.w", GPR32Opnd, int_loongarch_crcc_w_h_w>, R3I<0b1001101>; -+ def CRCC_W_W_W : Int_Reg3<"crcc.w.w.w", GPR32Opnd, int_loongarch_crcc_w_w_w>, R3I<0b1001110>; -+ /// -+ /// SLLI -+ /// -+ def SLLI_W : Shift_Imm32<"slli.w", GPR32Opnd, shl>, R2_IMM5<0b00>; -+ def SRLI_W : Shift_Imm32<"srli.w", GPR32Opnd, srl>, R2_IMM5<0b01>; -+ def SRAI_W : Shift_Imm32<"srai.w", GPR32Opnd, sra>, R2_IMM5<0b10>; -+ def ROTRI_W : Shift_Imm32<"rotri.w", GPR32Opnd, rotr>, R2_IMM5<0b11>; -+ /// -+ /// Misc -+ /// -+ def ALSL_W : Reg3_Sa<"alsl.w", GPR32Opnd, uimm2_plus1>, R3_SA2<0b00010> { -+ let Pattern = [(set GPR32Opnd:$rd, -+ (add GPR32Opnd:$rk, (shl GPR32Opnd:$rj, immZExt2Alsl:$sa)))]; -+ } -+ def BYTEPICK_W : Reg3_Sa<"bytepick.w", GPR32Opnd, uimm2>, R3_SA2<0b00100>;//pattern:[] -+ -+ def BREAK : Code15<"break", int_loongarch_break>, CODE15<0b1010100>; -+ def SYSCALL : Code15<"syscall", int_loongarch_syscall>, CODE15<0b1010110>; -+ def TRAP : TrapBase; -+ -+ def BSTRINS_W : InsBase_32<"bstrins.w", GPR32Opnd, uimm5, LoongArchBstrins>, -+ INSERT_BIT32<0>; -+ def BSTRPICK_W : PickBase_32<"bstrpick.w", GPR32Opnd, uimm5, LoongArchBstrpick>, -+ INSERT_BIT32<1>; -+ -+ /// -+ /// R2_IMM12 -+ /// -+ let isCodeGenOnly = 1 in { -+ def SLTI32 : SetCC_I<"slti", GPR32Opnd, simm12_32>, R2_IMM12<0b000>; //PatFrag -+ def SLTUI32 : SetCC_I<"sltui", GPR32Opnd, simm12_32>, R2_IMM12<0b001>; //PatFrag -+ } -+ def ADDI_W : Int_Reg2_Imm12<"addi.w", GPR32Opnd, simm12_32, add>, R2_IMM12<0b010>; -+ -+ let isCodeGenOnly = 1 in { -+ def ANDI32 : Int_Reg2_Imm12<"andi", GPR32Opnd, uimm12_32, and>, R2_IMM12<0b101>; -+ def ORI32 : Int_Reg2_Imm12<"ori", GPR32Opnd, uimm12_32, or>, R2_IMM12<0b110>; -+ def XORI32 : Int_Reg2_Imm12<"xori", GPR32Opnd, uimm12_32, xor>, R2_IMM12<0b111>; -+ } -+ -+ /// -+ /// Privilege Instructions -+ /// -+ def CSRRD32 : CSR<"csrrd", GPR32Opnd, uimm14_32, int_loongarch_csrrd_w>, R1_CSR<0b0000000000100>; -+ def CSRWR32 : CSRW<"csrwr", GPR32Opnd, uimm14_32, int_loongarch_csrwr_w>, R1_CSR<0b0000100000100>; -+ def CSRXCHG32 : CSRX<"csrxchg", GPR32Opnd, uimm14_32, int_loongarch_csrxchg_w>, R2_CSR<0b00000100>; -+ def IOCSRRD_B32 : Int_Reg2<"iocsrrd.b", GPR32Opnd, int_loongarch_iocsrrd_b>, R2P<0b000>; -+ def IOCSRRD_H32 : Int_Reg2<"iocsrrd.h", GPR32Opnd, int_loongarch_iocsrrd_h>, R2P<0b001>; -+ def IOCSRRD_W32 : Int_Reg2<"iocsrrd.w", GPR32Opnd, int_loongarch_iocsrrd_w>, R2P<0b010>; -+ def IOCSRWR_B32 : Int_Reg2_Iocsrwr<"iocsrwr.b", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_b>, R2P<0b100>; -+ def IOCSRWR_H32 : Int_Reg2_Iocsrwr<"iocsrwr.h", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_h>, R2P<0b101>; -+ def IOCSRWR_W32 : Int_Reg2_Iocsrwr<"iocsrwr.w", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_w>, R2P<0b110>; -+ def CACOP32 : CAC<"cacop", GPR32Opnd, simm12_32, int_loongarch_cacop_w>, R1_CACHE; -+ def LDDIR32 : LEVEL<"lddir", GPR32Opnd>, R2_LEVEL<0b00000110010000>; -+ def LDPTE32 : SEQ<"ldpte", GPR32Opnd>, R1_SEQ<0b00000110010001>; -+ -+ //def WAIT : Wait<"wait">; -+ // -+ //def IOCSRRD_D : R2P<0b011>, Int_Reg2<"iocsrrd.d", GPR32Opnd>; -+ //def IOCSRWR_D : R2P<0b111>, Int_Reg2<"iocsrwr.d", GPR32Opnd>; -+ // -+ //def TLBINV : IMM32<0b001000>, OP32<"tlbinv">; -+ //def TLBFLUSH : IMM32<0b001001>, OP32<"tlbflush">; -+ //def TLBP : IMM32<0b001010>, OP32<"tlbp">; -+ //def TLBR : IMM32<0b001011>, OP32<"tlbr">; -+ //def TLBWI : IMM32<0b001100>, OP32<"tlbwi">; -+ //def TLBWR : IMM32<0b001101>, OP32<"tlbwr">; -+ -+ /// -+ /// R1_IMM20 -+ /// -+ let isCodeGenOnly = 1 in { -+ def LU12I_W32 : SI20<"lu12i.w", GPR32Opnd, simm20_32>, R1_SI20<0b0001010>; -+ def PCADDI32 : SI20<"pcaddi", GPR32Opnd, simm20_32>, R1_SI20<0b0001100>; -+ def PCALAU12I32 : SI20<"pcalau12i", GPR32Opnd, simm20_32>, R1_SI20<0b0001101>; -+ def PCADDU12I32 : SI20<"pcaddu12i", GPR32Opnd, simm20_32>, R1_SI20<0b0001110>; -+ } -+ -+ let isCodeGenOnly = 1 in { -+ def BEQZ32 : Beqz<"beqz", brtarget, seteq, GPR32Opnd>, R1_IMM21BEQZ<0b010000>; -+ def BNEZ32 : Beqz<"bnez", brtarget, setne, GPR32Opnd>, R1_IMM21BEQZ<0b010001>; -+ -+ def JIRL32 : FJirl<"jirl", calltarget, GPR32Opnd>, R2_IMM16JIRL; -+ -+ def B32 : JumpFB, IMM26B<0b010100>; -+ -+ def BEQ32 : Beq<"beq", brtarget, seteq, GPR32Opnd>, R2_IMM16BEQ<0b010110>; -+ def BNE32 : Beq<"bne", brtarget, setne, GPR32Opnd>, R2_IMM16BEQ<0b010111>; -+ def BLT32 : Beq<"blt", brtarget, setlt, GPR32Opnd>, R2_IMM16BEQ<0b011000>; -+ def BGE32 : Beq<"bge", brtarget, setge, GPR32Opnd>, R2_IMM16BEQ<0b011001>; -+ def BLTU32 : Beq<"bltu", brtarget, setult, GPR32Opnd>, R2_IMM16BEQ<0b011010>; -+ def BGEU32 : Beq<"bgeu", brtarget, setuge, GPR32Opnd>, R2_IMM16BEQ<0b011011>; -+ } -+ -+ /// -+ /// Mem access -+ /// -+ def LL_W : LLBase<"ll.w", GPR32Opnd, mem_simm14_lsl2>, LL_SC<0b000>; -+ def SC_W : SCBase<"sc.w", GPR32Opnd, mem_simm14_lsl2>, LL_SC<0b001>; -+ -+ def PRELD_Raw32 : Preld_Raw<"preld", GPR32Opnd>, PRELD_FM; -+ -+ let isCodeGenOnly = 1 in { -+ def LD_B32 : Ld<"ld.b", GPR32Opnd, mem_simmptr, sextloadi8>, LOAD_STORE<0b0000>; -+ def LD_H32 : Ld<"ld.h", GPR32Opnd, mem_simmptr, sextloadi16, addrDefault>, LOAD_STORE<0b0001>; -+ def LD_W32 : Ld<"ld.w", GPR32Opnd, mem, load, addrDefault>, LOAD_STORE<0b0010>; -+ def ST_B32 : St<"st.b", GPR32Opnd, mem, truncstorei8>, LOAD_STORE<0b0100>; -+ def ST_H32 : St<"st.h", GPR32Opnd, mem, truncstorei16>, LOAD_STORE<0b0101>; -+ def ST_W32 : St<"st.w", GPR32Opnd, mem, store>, LOAD_STORE<0b0110>; -+ def LD_BU32 : Ld<"ld.bu", GPR32Opnd, mem_simmptr, zextloadi8, addrDefault>, LOAD_STORE<0b1000>; -+ def LD_HU32 : Ld<"ld.hu", GPR32Opnd, mem_simmptr, zextloadi16>, LOAD_STORE<0b1001>; -+ -+ def PRELD32 : Preld<"preld", mem, GPR32Opnd>, PRELD_FM; -+ -+ def LDPTR_W32 : LdPtr<"ldptr.w", GPR32Opnd>, LL_SC<0b100>; -+ def STPTR_W32 : StPtr<"stptr.w", GPR32Opnd>, LL_SC<0b101>; -+ } -+ -+ def IBAR : Bar<"ibar", int_loongarch_ibar>, BAR_FM<1>; -+ def DBAR : Bar<"dbar", int_loongarch_dbar>, BAR_FM<0>; -+ -+ def LONG_BRANCH_ADDIW : LoongArchPseudo<(outs GPR32Opnd:$dst), -+ (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; -+ -+ def LONG_BRANCH_ADDIW2Op : LoongArchPseudo<(outs GPR32Opnd:$dst), -+ (ins GPR32Opnd:$src, brtarget:$tgt), []>; -+ -+ def PseudoReturn : PseudoReturnBase; -+ -+ let isCodeGenOnly = 1 in { -+ def LDX_W32 : LDX_FT_LA<"ldx.w", GPR32Opnd, load>, -+ R3MI<0b00010000>; -+ def LDX_HU32 : LDX_FT_LA<"ldx.hu", GPR32Opnd, extloadi16>, -+ R3MI<0b01001000>; -+ def LDX_BU32 : LDX_FT_LA<"ldx.bu", GPR32Opnd, extloadi8>, -+ R3MI<0b01000000>; -+ def STX_W32 : STX_FT_LA<"stx.w", GPR32Opnd, store>, -+ R3MI<0b00110000>; -+ def LDX_H32 : LDX_FT_LA<"ldx.h", GPR32Opnd, sextloadi16>, -+ R3MI<0b00001000>; -+ def LDX_B32 : LDX_FT_LA<"ldx.b", GPR32Opnd, sextloadi8>, -+ R3MI<0b00000000>; -+ def STX_B32 : STX_FT_LA<"stx.b", GPR32Opnd, truncstorei8>, -+ R3MI<0b00100000>; -+ def STX_H32 : STX_FT_LA<"stx.h", GPR32Opnd, truncstorei16>, -+ R3MI<0b00101000>; -+ } -+} -+ -+def LEA_ADDI_W: EffectiveAddress<"addi.w", GPR32Opnd>, LEA_ADDI_FM<0b010>; -+ -+def : LoongArchPat<(LoongArchAddress (i32 tglobaladdr:$in)), -+ (ADDI_W (PCADDU12I32 tglobaladdr:$in) ,0)>,GPR_32; -+def : LoongArchPat<(LoongArchAddress (i32 tblockaddress:$in)), -+ (ADDI_W (PCADDU12I32 tblockaddress:$in),0)>, GPR_32; -+def : LoongArchPat<(LoongArchAddress (i32 tjumptable:$in)), -+ (ADDI_W (PCADDU12I32 tjumptable:$in),0)>, GPR_32; -+def : LoongArchPat<(LoongArchAddress (i32 texternalsym:$in)), -+ (ADDI_W (PCADDU12I32 texternalsym:$in),0)>, GPR_32; -+ -+//===----------------------------------------------------------------------===// -+// Arbitrary patterns that map to one or more instructions -+//===----------------------------------------------------------------------===// -+ -+let isCodeGenOnly = 1 in { -+ def REVB_2W_32 : Int_Reg2<"revb.2w", GPR32Opnd>, R2I<0b01110>; -+ def REVH_2W_32 : Int_Reg2<"revh.2w", GPR32Opnd>, R2I<0b10000>; -+} -+ -+// bswap pattern -+def : LoongArchPat<(bswap GPR32:$rj), (ROTRI_W (REVB_2H GPR32:$rj), 16)>; -+//def : LoongArchPat<(bswap GPR32:$rj), (REVB_2W_32 GPR32:$rj)>; -+//def : LoongArchPat<(bswap GPR32:$rj), (REVH_2W_32 (REVB_2H GPR32:$rj))>; -+ -+// i32 selects -+multiclass SelectInt_Pats { -+ -+// reg, immz -+def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, RC:$f), -+ (OROp (MASKNEZOp RC:$t, RC:$cond), (MASKEQZOp RC:$f, RC:$cond))>; -+def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), RC:$t, RC:$f), -+ (OROp (MASKEQZOp RC:$t, RC:$cond), (MASKNEZOp RC:$f, RC:$cond))>; -+ -+//def : LoongArchPat<(select (Opg (seteq RC:$cond, imm_type:$imm)), RC:$t, RC:$f), -+// (OROp (MASKNEZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), -+// (MASKEQZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; -+//def : LoongArchPat<(select (Opg (setne RC:$cond, imm_type:$imm)), RC:$t, RC:$f), -+// (OROp (MASKEQZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), -+// (MASKNEZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; -+ -+// reg, immSExt12Plus1 -+//def : LoongArchPat<(select (Opg (setgt RC:$cond, immSExt12Plus1:$imm)), RC:$t, RC:$f), -+// (OROp (MASKNEZOp RC:$t, (SLTiOp RC:$cond, (Plus1 imm:$imm))), -+// (MASKEQZOp RC:$f, (SLTiOp RC:$cond, (Plus1 imm:$imm))))>; -+//def : LoongArchPat<(select (Opg (setugt RC:$cond, immSExt16Plus1:$imm)), RC:$t, RC:$f), -+// (OROp (MASKNEZOp RC:$t, (SLTiuOp RC:$cond, (Plus1 imm:$imm))), -+// (MASKEQZOp RC:$f, (SLTiuOp RC:$cond, (Plus1 imm:$imm))))>; -+ -+def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, immz), -+ (MASKNEZOp RC:$t, RC:$cond)>; -+def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), RC:$t, immz), -+ (MASKEQZOp RC:$t, RC:$cond)>; -+def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), immz, RC:$f), -+ (MASKEQZOp RC:$f, RC:$cond)>; -+def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), immz, RC:$f), -+ (MASKNEZOp RC:$f, RC:$cond)>; -+} -+ -+defm : SelectInt_Pats; -+ -+def : LoongArchPat<(select i32:$cond, i32:$t, i32:$f), -+ (OR32 (MASKEQZ32 i32:$t, i32:$cond), -+ (MASKNEZ32 i32:$f, i32:$cond))>; -+def : LoongArchPat<(select i32:$cond, i32:$t, immz), -+ (MASKEQZ32 i32:$t, i32:$cond)>; -+def : LoongArchPat<(select i32:$cond, immz, i32:$f), -+ (MASKNEZ32 i32:$f, i32:$cond)>; -+ -+// truncate -+def : LoongArchPat<(i32 (trunc (assertzext_lt_i32 GPR64:$src))), -+ (EXTRACT_SUBREG GPR64:$src, sub_32)>, GPR_64; -+def : LoongArchPat<(i32 (trunc GPR64:$src)), -+ (SLLI_W (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, GPR_64; -+ -+// Patterns used for matching away redundant sign extensions. -+// LA32 arithmetic instructions sign extend their result implicitly. -+def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ADD_W GPR32:$src, GPR32:$src2), sub_32)>; -+def : LoongArchPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SUB_W GPR32:$src, GPR32:$src2), sub_32)>; -+def : LoongArchPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (MUL_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(store (i32 0), addr:$dst), (ST_W32 ZERO, addr:$dst)>; -+ -+def : InstAlias<"break", (BREAK 0), 1>; -+def : InstAlias<"break $imm", (BREAK uimm15:$imm), 1>; -+def : LoongArchInstAlias<"move $dst, $src", -+ (OR32 GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, GPR_32; -+ -+def immSExt12Plus1 : PatLeaf<(imm), [{ -+ return isInt<13>(N->getSExtValue()) && isInt<12>(N->getSExtValue() + 1); -+}]>; -+ -+def Plus1 : SDNodeXFormgetSExtValue() + 1); }]>; -+ -+multiclass BrcondPats { -+ -+def : LoongArchPat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), -+ (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), -+ (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), -+ (BEQOp1 (SLTOp RC:$lhs, RC:$rhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), -+ (BEQOp1 (SLTUOp RC:$lhs, RC:$rhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setge RC:$lhs, immSExt12:$rhs)), bb:$dst), -+ (BEQOp1 (SLTIOp RC:$lhs, immSExt12:$rhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setuge RC:$lhs, immSExt12:$rhs)), bb:$dst), -+ (BEQOp1 (SLTUIOp RC:$lhs, immSExt12:$rhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setgt RC:$lhs, immSExt12Plus1:$rhs)), bb:$dst), -+ (BEQOp1 (SLTIOp RC:$lhs, (Plus1 imm:$rhs)), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setugt RC:$lhs, immSExt12Plus1:$rhs)), bb:$dst), -+ (BEQOp1 (SLTUIOp RC:$lhs, (Plus1 imm:$rhs)), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), -+ (BEQOp1 (SLTOp RC:$rhs, RC:$lhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), -+ (BEQOp1 (SLTUOp RC:$rhs, RC:$lhs), ZEROReg, bb:$dst)>; -+def : LoongArchPat<(brcond RC:$cond, bb:$dst), -+ (BNEOp RC:$cond, ZEROReg, bb:$dst)>; -+} -+ -+defm : BrcondPats, GPR_64; -+ -+let usesCustomInserter = 1 in { -+ def ATOMIC_LOAD_ADD_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_ADD_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_ADD_I32 : Atomic2Ops; -+ def ATOMIC_LOAD_SUB_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_SUB_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_SUB_I32 : Atomic2Ops; -+ def ATOMIC_LOAD_AND_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_AND_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_AND_I32 : Atomic2Ops; -+ def ATOMIC_LOAD_OR_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_OR_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_OR_I32 : Atomic2Ops; -+ def ATOMIC_LOAD_XOR_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_XOR_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_XOR_I32 : Atomic2Ops; -+ def ATOMIC_LOAD_NAND_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_NAND_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_NAND_I32 : Atomic2Ops; -+ -+ def ATOMIC_SWAP_I8 : Atomic2Ops; -+ def ATOMIC_SWAP_I16 : Atomic2Ops; -+ def ATOMIC_SWAP_I32 : Atomic2Ops; -+ -+ def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap; -+ def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap; -+ def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap; -+ -+ def ATOMIC_LOAD_MAX_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_MAX_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_MAX_I32 : Atomic2Ops; -+ -+ def ATOMIC_LOAD_MIN_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_MIN_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_MIN_I32 : Atomic2Ops; -+ -+ def ATOMIC_LOAD_UMAX_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_UMAX_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_UMAX_I32 : Atomic2Ops; -+ -+ def ATOMIC_LOAD_UMIN_I8 : Atomic2Ops; -+ def ATOMIC_LOAD_UMIN_I16 : Atomic2Ops; -+ def ATOMIC_LOAD_UMIN_I32 : Atomic2Ops; -+} -+ -+def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_ADD_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_ADD_I32_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_SUB_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_SUB_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_SUB_I32_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_AND_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_AND_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_AND_I32_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_OR_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_OR_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_OR_I32_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_XOR_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_XOR_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_XOR_I32_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_NAND_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_NAND_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_NAND_I32_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_SWAP_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_SWAP_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_SWAP_I32_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA; -+def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA; -+def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA; -+ -+def ATOMIC_LOAD_MAX_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_MAX_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_MAX_I32_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_MIN_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_MIN_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_MIN_I32_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_UMAX_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_UMAX_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_UMAX_I32_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_UMIN_I8_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_UMIN_I16_POSTRA : Atomic2OpsSubwordPostRA; -+def ATOMIC_LOAD_UMIN_I32_POSTRA : Atomic2OpsPostRA; -+ -+def : LoongArchPat<(atomic_load_8 addr:$a), (LD_B32 addr:$a)>; -+def : LoongArchPat<(atomic_load_16 addr:$a), (LD_H32 addr:$a)>; -+def : LoongArchPat<(atomic_load_32 addrimm14lsl2:$a), (LDPTR_W32 addrimm14lsl2:$a)>; -+def : LoongArchPat<(atomic_load_32 addr:$a), (LD_W32 addr:$a)>; -+ -+def : LoongArchPat<(atomic_store_8 addr:$a, GPR32:$v), -+ (ST_B32 GPR32:$v, addr:$a)>; -+def : LoongArchPat<(atomic_store_16 addr:$a, GPR32:$v), -+ (ST_H32 GPR32:$v, addr:$a)>; -+def : LoongArchPat<(atomic_store_32 addrimm14lsl2:$a, GPR32:$v), -+ (STPTR_W32 GPR32:$v, addrimm14lsl2:$a)>; -+def : LoongArchPat<(atomic_store_32 addr:$a, GPR32:$v), -+ (ST_W32 GPR32:$v, addr:$a)>; -+ -+def : LoongArchPat<(LoongArchDBAR (i32 immz)), -+ (DBAR 0)>; -+ -+def : LoongArchPat<(i32 (extloadi1 addr:$src)), (LD_BU32 addr:$src)>; -+def : LoongArchPat<(i32 (extloadi8 addr:$src)), (LD_BU32 addr:$src)>; -+def : LoongArchPat<(i32 (extloadi16 addr:$src)), (LD_HU32 addr:$src)>; -+ -+def : LoongArchPat<(store (i32 0), addr:$dst), (ST_W32 ZERO, addr:$dst)>; -+ -+// Patterns for loads/stores with a reg+imm operand. -+let AddedComplexity = 40 in { -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : StoreRegImmPat; -+ def : StoreRegImmPat; -+ def : StoreRegImmPat; -+ -+ def : LoadRegImm14Lsl2Pat; -+ def : StoreRegImm14Lsl2Pat; -+} -+ -+let isCall=1, isCTI=1, Defs = [RA] in { -+ -+ class JumpLinkRegPseudo: -+ LoongArchPseudo<(outs), (ins RO:$rj), [(LoongArchJmpLink RO:$rj)]>, -+ PseudoInstExpansion<(JIRLRInst RetReg, ResRO:$rj)> { -+ let hasPostISelHook = 1; -+ } -+ -+ class JumpLinkReg: -+ InstForm<(outs RO:$rd), (ins RO:$rj), !strconcat(opstr, "\t$rd, $rj, 0"), -+ [], FrmR, opstr> { -+ let hasPostISelHook = 1; -+ } -+ -+} -+ -+def JIRLR : JumpLinkReg<"jirl", GPR32Opnd>, R2_IMM16JIRL { -+ let offs16 = 0; -+} -+def JIRLRPseudo : JumpLinkRegPseudo; -+ -+class BrindRegPseudo: -+ LoongArchPseudo<(outs), (ins RO:$rj), [(brind RO:$rj)]>, -+ PseudoInstExpansion<(JIRLRInst RetReg, ResRO:$rj)> { -+ let isTerminator=1; -+ let isBarrier=1; -+ let isBranch = 1; -+ let isIndirectBranch = 1; -+ bit isCTI = 1; -+} -+ -+def JIRLRBRIND : BrindRegPseudo; -+ -+def : LoongArchPat<(addc GPR32:$src, immSExt12:$imm), -+ (ADDI_W GPR32:$src, imm:$imm)>; -+ -+defm : SeteqPats; -+defm : SetlePats; -+defm : SetgtPats; -+defm : SetgePats; -+defm : SetgeImmPats; -+ -+def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (immZExt12:$imm12))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (XORI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (immZExt12:$imm12)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (add (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ADD_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (add (i32 (trunc (i64 (assertsext GPR64:$rj)))), (immSExt12:$imm12))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ADDI_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (immSExt12:$imm12)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (sra (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRA_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (srl (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (mul (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (MUL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (XOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 GPR32:$rk))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (XOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), GPR32:$rk), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), (uimm12_32:$imm12))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ORI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (uimm12_32:$imm12)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 GPR32:$rk))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (OR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), GPR32:$rk), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (select i32:$cond, (i32 (trunc (i64 (assertsext GPR64:$t)))), (i32 (trunc (i64 (assertsext GPR64:$f))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (OR32 (MASKEQZ32 (EXTRACT_SUBREG GPR64:$t, sub_32), i32:$cond), -+ (MASKNEZ32 (EXTRACT_SUBREG GPR64:$f, sub_32), i32:$cond)), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (shl (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SLL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (srem (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (MOD_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(atomic_store_32 addr:$a, (i32 (trunc (i64 (assertsext GPR64:$rj))))), -+ (ST_W32 (EXTRACT_SUBREG GPR64:$rj, sub_32), addr:$a)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (sub (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SUB_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (udiv (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (DIV_WU (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(i64 (sext (i32 (urem (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (MOD_WU (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; -+ -+def : LoongArchPat<(brcond (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$rj)))), 0)), bb:$offs21), -+ (BEQZ32 (EXTRACT_SUBREG GPR64:$rj, sub_32), brtarget:$offs21)>; -+ -+def : LoongArchPat<(setne (i32 (trunc (i64 (assertsext GPR64:$rj)))), 0), -+ (SLTU32 ZERO, (EXTRACT_SUBREG GPR64:$rj, sub_32))>; -+ -+def : LoongArchPat<(select i32:$cond, (i32 (trunc (i64 (assertsext GPR64:$t)))), (i32 (trunc (i64 (assertsext GPR64:$f))))), -+ (OR32 (MASKEQZ32 (EXTRACT_SUBREG GPR64:$t, sub_32), i32:$cond), -+ (MASKNEZ32 (EXTRACT_SUBREG GPR64:$f, sub_32), i32:$cond))>; -+ -+def : LoongArchPat<(select (i32 (setne (i32 (trunc (i64 (assertsext GPR64:$cond)))), immz)), immz, i32:$f), -+ (MASKNEZ32 i32:$f, (EXTRACT_SUBREG GPR64:$cond, sub_32))>; -+ -+def : LoongArchPat<(select (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$cond)))), immz)), immz, i32:$f), -+ (MASKEQZ32 i32:$f, (EXTRACT_SUBREG GPR64:$cond, sub_32))>; -+ -+ def : LoongArchPat<(store (i32 (trunc (i64 (assertsext GPR64:$v)))), addr:$a), -+ (ST_W32 (EXTRACT_SUBREG GPR64:$v, sub_32), addr:$a)>; -+ -+ -+def : LoongArchPat<(i32 (xor GPR32:$rj, (i32 -1))), -+ (NOR32 ZERO, GPR32:$rj)>; -+ -+def : LoongArchPat<(and GPR32:$rj, (i32 (xor GPR32:$rk, (i32 -1)))), -+ (ANDN32 GPR32:$rj, GPR32:$rk)>; -+ -+def : LoongArchPat< -+ (i64 -+ (sext -+ (i32 (and (i32 (trunc (i64 (assertsext GPR64:$rj)))), -+ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rk)))), -+ (i32 -1)))) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (ANDN32 (EXTRACT_SUBREG GPR64:$rj, sub_32), -+ (EXTRACT_SUBREG GPR64:$rk, sub_32)), -+ sub_32 -+ )>; -+ -+def : LoongArchPat< -+ (i64 -+ (sext -+ (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), -+ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rk)))), -+ (i32 -1)))) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (ORN32 (EXTRACT_SUBREG GPR64:$rj, sub_32), -+ (EXTRACT_SUBREG GPR64:$rk, sub_32)), -+ sub_32 -+ )>; -+ -+def : LoongArchPat<(i64 -+ (sext -+ (i32 (xor (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), -+ (i32 (trunc (i64 (assertsext GPR64:$rk)))))), -+ (i32 -1)) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (NOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), -+ (EXTRACT_SUBREG GPR64:$rk, sub_32)), -+ sub_32 -+ )>; -+ -+def : LoongArchPat<(i64 -+ (sext -+ (i32 (xor (i32 (trunc (i64 (or (i64 (assertsext GPR64:$rj)), -+ (i64 (assertsext GPR64:$rk)))))), -+ (i32 -1)) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (NOR32 (EXTRACT_SUBREG GPR64:$rk, sub_32), -+ (EXTRACT_SUBREG GPR64:$rj, sub_32)), -+ sub_32 -+ )>; -+ -+def : LoongArchPat<(i64 -+ (sext -+ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), -+ (i32 -1)) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (NOR32 ZERO, (EXTRACT_SUBREG GPR64:$rj, sub_32)), -+ sub_32 -+ )>; -+ -+def : LoongArchPat<(i64 -+ (zext -+ (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$rj)))), -+ (i32 0)) -+ ) -+ ) -+ ), -+ (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), -+ (SLTUI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (i32 1)), -+ sub_32 -+ )>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp -index 1467d1757..afa38dbf2 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp -@@ -1,4 +1,4 @@ --//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- C++ -*--=// -+//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer --------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -12,40 +12,622 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchAsmPrinter.h" -+#include "MCTargetDesc/LoongArchInstPrinter.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" - #include "LoongArch.h" -+#include "LoongArchMCInstLower.h" -+#include "LoongArchMachineFunction.h" -+#include "LoongArchSubtarget.h" - #include "LoongArchTargetMachine.h" --#include "TargetInfo/LoongArchTargetInfo.h" --#include "llvm/CodeGen/AsmPrinter.h" -+#include "LoongArchTargetStreamer.h" -+#include "llvm/ADT/SmallString.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/ADT/Triple.h" -+#include "llvm/ADT/Twine.h" -+#include "llvm/BinaryFormat/ELF.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" -+#include "llvm/CodeGen/MachineConstantPool.h" -+#include "llvm/CodeGen/MachineFrameInfo.h" -+#include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineInstr.h" -+#include "llvm/CodeGen/MachineJumpTableInfo.h" -+#include "llvm/CodeGen/MachineOperand.h" -+#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "llvm/CodeGen/TargetSubtargetInfo.h" -+#include "llvm/IR/Attributes.h" -+#include "llvm/IR/BasicBlock.h" -+#include "llvm/IR/DataLayout.h" -+#include "llvm/IR/Function.h" -+#include "llvm/IR/InlineAsm.h" -+#include "llvm/IR/Instructions.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/MC/MCInst.h" -+#include "llvm/MC/MCInstBuilder.h" -+#include "llvm/MC/MCObjectFileInfo.h" -+#include "llvm/MC/MCSectionELF.h" -+#include "llvm/MC/MCSymbol.h" -+#include "llvm/MC/MCSymbolELF.h" - #include "llvm/MC/TargetRegistry.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/raw_ostream.h" -+#include "llvm/Target/TargetMachine.h" -+#include -+#include -+#include -+#include -+#include -+#include - - using namespace llvm; - - #define DEBUG_TYPE "loongarch-asm-printer" - --// Simple pseudo-instructions have their lowering (with expansion to real --// instructions) auto-generated. -+LoongArchTargetStreamer &LoongArchAsmPrinter::getTargetStreamer() const { -+ return static_cast(*OutStreamer->getTargetStreamer()); -+} -+ -+bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { -+ Subtarget = &MF.getSubtarget(); -+ -+ LoongArchFI = MF.getInfo(); -+ MCP = MF.getConstantPool(); -+ -+ AsmPrinter::runOnMachineFunction(MF); -+ -+ emitXRayTable(); -+ -+ return true; -+} -+ -+bool LoongArchAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { -+ MCOp = MCInstLowering.LowerOperand(MO); -+ return MCOp.isValid(); -+} -+ - #include "LoongArchGenMCPseudoLowering.inc" - -+// Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to -+// JIRL as appropriate for the target. -+void LoongArchAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, -+ const MachineInstr *MI) { -+ bool HasLinkReg = false; -+ MCInst TmpInst0; -+ TmpInst0.setOpcode(LoongArch::JIRL); -+ HasLinkReg = true; -+ -+ MCOperand MCOp; -+ -+ if (HasLinkReg) { -+ unsigned ZeroReg = Subtarget->is64Bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); -+ } -+ -+ lowerOperand(MI->getOperand(0), MCOp); -+ TmpInst0.addOperand(MCOp); -+ -+ TmpInst0.addOperand(MCOperand::createImm(0)); -+ -+ EmitToStreamer(OutStreamer, TmpInst0); -+} -+ -+void LoongArchAsmPrinter::emitPseudoTailBranch(MCStreamer &OutStreamer, -+ const MachineInstr *MI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(LoongArch::B); -+ -+ MCOperand MCOp; -+ -+ lowerOperand(MI->getOperand(0), MCOp); -+ TmpInst.addOperand(MCOp); -+ -+ EmitToStreamer(OutStreamer, TmpInst); -+} -+ - void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) { -- LoongArch_MC::verifyInstructionPredicates( -- MI->getOpcode(), getSubtargetInfo().getFeatureBits()); -+ LoongArchTargetStreamer &TS = getTargetStreamer(); -+ unsigned Opc = MI->getOpcode(); -+ TS.forbidModuleDirective(); - -- // Do any auto-generated pseudo lowerings. -- if (emitPseudoExpansionLowering(*OutStreamer, MI)) -+ if (MI->isDebugValue()) { -+ SmallString<128> Str; -+ raw_svector_ostream OS(Str); -+ -+ PrintDebugValueComment(MI, OS); -+ return; -+ } -+ if (MI->isDebugLabel()) - return; -+ // If we just ended a constant pool, mark it as such. -+ OutStreamer->emitDataRegion(MCDR_DataRegionEnd); -+ InConstantPool = false; - -- MCInst TmpInst; -- if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this)) -- EmitToStreamer(*OutStreamer, TmpInst); -+ switch (Opc) { -+ case LoongArch::PATCHABLE_FUNCTION_ENTER: -+ LowerPATCHABLE_FUNCTION_ENTER(*MI); -+ return; -+ case LoongArch::PATCHABLE_FUNCTION_EXIT: -+ LowerPATCHABLE_FUNCTION_EXIT(*MI); -+ return; -+ case LoongArch::PATCHABLE_TAIL_CALL: -+ LowerPATCHABLE_TAIL_CALL(*MI); -+ return; -+ } -+ MachineBasicBlock::const_instr_iterator I = MI->getIterator(); -+ MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); -+ -+ do { -+ // Do any auto-generated pseudo lowerings. -+ if (emitPseudoExpansionLowering(*OutStreamer, &*I)) -+ continue; -+ if (I->getOpcode() == LoongArch::PseudoReturn || -+ I->getOpcode() == LoongArch::PseudoReturn64){ -+ emitPseudoIndirectBranch(*OutStreamer, &*I); -+ continue; -+ } -+ if (I->getOpcode() == LoongArch::PseudoTailReturn){ -+ emitPseudoTailBranch(*OutStreamer, &*I); -+ continue; -+ } -+ -+ // Some instructions are marked as pseudo right now which -+ // would make the test fail for the wrong reason but -+ // that will be fixed soon. We need this here because we are -+ // removing another test for this situation downstream in the -+ // callchain. -+ // -+ if (I->isPseudo() -+ && !isLongBranchPseudo(I->getOpcode())) -+ llvm_unreachable("Pseudo opcode found in EmitInstruction()"); -+ -+ MCInst TmpInst0; -+ MCInstLowering.Lower(&*I, TmpInst0); -+ EmitToStreamer(*OutStreamer, TmpInst0); -+ } while ((++I != E) && I->isInsideBundle()); - } - --bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { -- AsmPrinter::runOnMachineFunction(MF); -- return true; -+//===----------------------------------------------------------------------===// -+// -+// LoongArch Asm Directives -+// -+// -+//===----------------------------------------------------------------------===// -+ -+//===----------------------------------------------------------------------===// -+// Set directives -+//===----------------------------------------------------------------------===// -+ -+/// Emit Set directives. -+const char *LoongArchAsmPrinter::getCurrentABIString() const { -+ switch (static_cast(TM).getABI().GetEnumValue()) { -+ case LoongArchABIInfo::ABI::LP32: return "abilp32"; -+ case LoongArchABIInfo::ABI::LPX32: return "abilpx32"; -+ case LoongArchABIInfo::ABI::LP64: return "abilp64"; -+ default: llvm_unreachable("Unknown LoongArch ABI"); -+ } -+} -+ -+void LoongArchAsmPrinter::emitFunctionEntryLabel() { -+ -+ OutStreamer->emitLabel(CurrentFnSym); -+ -+} -+ -+/// EmitFunctionBodyStart - Targets can override this to emit stuff before -+/// the first basic block in the function. -+void LoongArchAsmPrinter::emitFunctionBodyStart() { -+ -+ MCInstLowering.Initialize(&MF->getContext()); -+} -+ -+/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -+/// the last basic block in the function. -+void LoongArchAsmPrinter::emitFunctionBodyEnd() { -+ -+ // Make sure to terminate any constant pools that were at the end -+ // of the function. -+ if (!InConstantPool) -+ return; -+ InConstantPool = false; -+ OutStreamer->emitDataRegion(MCDR_DataRegionEnd); -+} -+ -+void LoongArchAsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) { -+ AsmPrinter::emitBasicBlockEnd(MBB); -+} -+ -+/// isBlockOnlyReachableByFallthough - Return true if the basic block has -+/// exactly one predecessor and the control transfer mechanism between -+/// the predecessor and this block is a fall-through. -+bool LoongArchAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* -+ MBB) const { -+ // The predecessor has to be immediately before this block. -+ const MachineBasicBlock *Pred = *MBB->pred_begin(); -+ -+ // If the predecessor is a switch statement, assume a jump table -+ // implementation, so it is not a fall through. -+ if (const BasicBlock *bb = Pred->getBasicBlock()) -+ if (isa(bb->getTerminator())) -+ return false; -+ -+ // Check default implementation -+ return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); -+} -+ -+// Print out an operand for an inline asm expression. -+bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, -+ unsigned OpNum, const char *ExtraCode, raw_ostream &O) { -+ // Does this asm operand have a single letter operand modifier? -+ if (ExtraCode && ExtraCode[0]) { -+ if (ExtraCode[1] != 0) return true; // Unknown modifier. -+ -+ const MachineOperand &MO = MI->getOperand(OpNum); -+ switch (ExtraCode[0]) { -+ default: -+ // See if this is a generic print operand -+ return AsmPrinter::PrintAsmOperand(MI,OpNum,ExtraCode,O); -+ case 'X': // hex const int -+ if ((MO.getType()) != MachineOperand::MO_Immediate) -+ return true; -+ O << "0x" << Twine::utohexstr(MO.getImm()); -+ return false; -+ case 'x': // hex const int (low 16 bits) -+ if ((MO.getType()) != MachineOperand::MO_Immediate) -+ return true; -+ O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); -+ return false; -+ case 'd': // decimal const int -+ if ((MO.getType()) != MachineOperand::MO_Immediate) -+ return true; -+ O << MO.getImm(); -+ return false; -+ case 'm': // decimal const int minus 1 -+ if ((MO.getType()) != MachineOperand::MO_Immediate) -+ return true; -+ O << MO.getImm() - 1; -+ return false; -+ case 'y': // exact log2 -+ if ((MO.getType()) != MachineOperand::MO_Immediate) -+ return true; -+ if (!isPowerOf2_64(MO.getImm())) -+ return true; -+ O << Log2_64(MO.getImm()); -+ return false; -+ case 'z': -+ // $r0 if zero, regular printing otherwise -+ if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) { -+ O << "$r0"; -+ return false; -+ } -+ // If not, call printOperand as normal. -+ break; -+ case 'D': // Second part of a double word register operand -+ case 'L': // Low order register of a double word register operand -+ case 'M': // High order register of a double word register operand -+ { -+ if (OpNum == 0) -+ return true; -+ const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); -+ if (!FlagsOP.isImm()) -+ return true; -+ unsigned Flags = FlagsOP.getImm(); -+ unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); -+ // Number of registers represented by this operand. We are looking -+ // for 2 for 32 bit mode and 1 for 64 bit mode. -+ if (NumVals != 2) { -+ if (Subtarget->is64Bit() && NumVals == 1 && MO.isReg()) { -+ unsigned Reg = MO.getReg(); -+ O << '$' << LoongArchInstPrinter::getRegisterName(Reg); -+ return false; -+ } -+ return true; -+ } -+ -+ unsigned RegOp = OpNum; -+ if (!Subtarget->is64Bit()){ -+ // Endianness reverses which register holds the high or low value -+ // between M and L. -+ switch(ExtraCode[0]) { -+ case 'M': -+ RegOp = OpNum + 1; -+ break; -+ case 'L': -+ RegOp = OpNum; -+ break; -+ case 'D': // Always the second part -+ RegOp = OpNum + 1; -+ } -+ if (RegOp >= MI->getNumOperands()) -+ return true; -+ const MachineOperand &MO = MI->getOperand(RegOp); -+ if (!MO.isReg()) -+ return true; -+ unsigned Reg = MO.getReg(); -+ O << '$' << LoongArchInstPrinter::getRegisterName(Reg); -+ return false; -+ } -+ break; -+ } -+ case 'w': -+ // Print LSX registers for the 'f' constraint -+ // In LLVM, the 'w' modifier doesn't need to do anything. -+ // We can just call printOperand as normal. -+ break; -+ case 'u': -+ // Print LASX registers for the 'f' constraint -+ // In LLVM, the 'u' modifier doesn't need to do anything. -+ // We can just call printOperand as normal. -+ break; -+ } -+ } -+ -+ printOperand(MI, OpNum, O); -+ return false; -+} -+ -+bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, -+ unsigned OpNum, -+ const char *ExtraCode, -+ raw_ostream &O) { -+ assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); -+ const MachineOperand &BaseMO = MI->getOperand(OpNum); -+ const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); -+ assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); -+ assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); -+ int Offset = OffsetMO.getImm(); -+ -+ // Currently we are expecting either no ExtraCode or 'D','M','L'. -+ if (ExtraCode) { -+ switch (ExtraCode[0]) { -+ case 'D': -+ case 'M': -+ Offset += 4; -+ break; -+ case 'L': -+ break; -+ default: -+ return true; // Unknown modifier. -+ } -+ } -+ -+ O << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg()) << ", " << Offset; -+ -+ return false; -+} -+ -+void LoongArchAsmPrinter::printOperand(const MachineInstr *MI, int opNum, -+ raw_ostream &O) { -+ const MachineOperand &MO = MI->getOperand(opNum); -+ -+ switch (MO.getType()) { -+ case MachineOperand::MO_Register: -+ O << '$' -+ << StringRef(LoongArchInstPrinter::getRegisterName(MO.getReg())).lower(); -+ break; -+ -+ case MachineOperand::MO_Immediate: -+ O << MO.getImm(); -+ break; -+ -+ case MachineOperand::MO_MachineBasicBlock: -+ MO.getMBB()->getSymbol()->print(O, MAI); -+ return; -+ -+ case MachineOperand::MO_GlobalAddress: -+ getSymbol(MO.getGlobal())->print(O, MAI); -+ break; -+ -+ case MachineOperand::MO_BlockAddress: { -+ MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); -+ O << BA->getName(); -+ break; -+ } -+ -+ case MachineOperand::MO_ConstantPoolIndex: -+ O << getDataLayout().getPrivateGlobalPrefix() << "CPI" -+ << getFunctionNumber() << "_" << MO.getIndex(); -+ if (MO.getOffset()) -+ O << "+" << MO.getOffset(); -+ break; -+ -+ default: -+ llvm_unreachable(""); -+ } -+} -+ -+void LoongArchAsmPrinter:: -+printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { -+ // Load/Store memory operands -- imm($reg) -+ // If PIC target the target is loaded as the -+ // pattern lw $25,%call16($28) -+ -+ printOperand(MI, opNum+1, O); -+ O << "("; -+ printOperand(MI, opNum, O); -+ O << ")"; -+} -+ -+void LoongArchAsmPrinter:: -+printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { -+ // when using stack locations for not load/store instructions -+ // print the same way as all normal 3 operand instructions. -+ printOperand(MI, opNum, O); -+ O << ", "; -+ printOperand(MI, opNum+1, O); -+} -+ -+void LoongArchAsmPrinter:: -+printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { -+ for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { -+ if (i != opNum) O << ", "; -+ printOperand(MI, i, O); -+ } -+} -+ -+void LoongArchAsmPrinter::emitStartOfAsmFile(Module &M) { -+ LoongArchTargetStreamer &TS = getTargetStreamer(); -+ -+ // LoongArchTargetStreamer has an initialization order problem when emitting an -+ // object file directly (see LoongArchTargetELFStreamer for full details). Work -+ // around it by re-initializing the PIC state here. -+ TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent()); -+ -+ // Compute LoongArch architecture attributes based on the default subtarget -+ // that we'd have constructed. Module level directives aren't LTO -+ // clean anyhow. -+ // FIXME: For ifunc related functions we could iterate over and look -+ // for a feature string that doesn't match the default one. -+ const Triple &TT = TM.getTargetTriple(); -+ StringRef CPU = LoongArch_MC::selectLoongArchCPU(TT, TM.getTargetCPU()); -+ StringRef FS = TM.getTargetFeatureString(); -+ const LoongArchTargetMachine &MTM = static_cast(TM); -+ const LoongArchSubtarget STI(TT, CPU, FS, MTM, None); -+ -+ TS.updateABIInfo(STI); -+} -+ -+void LoongArchAsmPrinter::emitInlineAsmStart() const { -+ -+ OutStreamer->addBlankLine(); -+} -+ -+void LoongArchAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, -+ const MCSubtargetInfo *EndInfo) const { -+ OutStreamer->addBlankLine(); -+} -+ -+void LoongArchAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, -+ unsigned Reg) { -+ MCInst I; -+ I.setOpcode(Opcode); -+ I.addOperand(MCOperand::createReg(Reg)); -+ OutStreamer->emitInstruction(I, STI); -+} -+ -+void LoongArchAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, -+ unsigned Opcode, unsigned Reg1, -+ unsigned Reg2) { -+ MCInst I; -+ // -+ // Because of the current td files for LoongArch32, the operands for MTC1 -+ // appear backwards from their normal assembly order. It's not a trivial -+ // change to fix this in the td file so we adjust for it here. -+ // -+ if (Opcode == LoongArch::MOVGR2FR_W) { -+ unsigned Temp = Reg1; -+ Reg1 = Reg2; -+ Reg2 = Temp; -+ } -+ I.setOpcode(Opcode); -+ I.addOperand(MCOperand::createReg(Reg1)); -+ I.addOperand(MCOperand::createReg(Reg2)); -+ OutStreamer->emitInstruction(I, STI); -+} -+ -+void LoongArchAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, -+ unsigned Opcode, unsigned Reg1, -+ unsigned Reg2, unsigned Reg3) { -+ MCInst I; -+ I.setOpcode(Opcode); -+ I.addOperand(MCOperand::createReg(Reg1)); -+ I.addOperand(MCOperand::createReg(Reg2)); -+ I.addOperand(MCOperand::createReg(Reg3)); -+ OutStreamer->emitInstruction(I, STI); -+} -+ -+void LoongArchAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, -+ unsigned MovOpc, unsigned Reg1, -+ unsigned Reg2, unsigned FPReg1, -+ unsigned FPReg2, bool LE) { -+ if (!LE) { -+ unsigned temp = Reg1; -+ Reg1 = Reg2; -+ Reg2 = temp; -+ } -+ EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); -+ EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); -+} -+ -+void LoongArchAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { -+ const uint8_t NoopsInSledCount = 11; -+ // For loongarch64 we want to emit the following pattern: -+ // -+ // .Lxray_sled_N: -+ // ALIGN -+ // B .tmpN -+ // 11 NOP instructions (44 bytes) -+ // .tmpN -+ // -+ // We need the 44 bytes (11 instructions) because at runtime, we'd -+ // be patching over the full 48 bytes (12 instructions) with the following -+ // pattern: -+ // -+ // addi.d sp,sp, -16 ;create stack frame -+ // st.d ra, sp, 8 ;save return address -+ // lu12i.w t0,%%abs_hi20(__xray_FunctionEntry/Exit) -+ // ori t0,t0,%%abs_lo12(__xray_FunctionEntry/Exit) -+ // lu32i.d t0,%%abs64_lo20(__xray_FunctionEntry/Exit) -+ // lu52i.d t0,t0,%%abs64_hi12(__xray_FunctionEntry/Exit) -+ // lu12i.w t1,%%abs_hi20(function_id) -+ // ori t1,t1,%%abs_lo12(function_id) ;pass function id -+ // jirl ra, t0, 0 ;call Tracing hook -+ // ld.d ra, sp, 8 ;restore return address -+ // addi.d sp, sp, 16 ;delete stack frame -+ -+ OutStreamer->emitCodeAlignment(4, &getSubtargetInfo()); -+ auto CurSled = OutContext.createTempSymbol("xray_sled_", true); -+ OutStreamer->emitLabel(CurSled); -+ auto Target = OutContext.createTempSymbol(); -+ -+ // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual -+ // start of function -+ const MCExpr *TargetExpr = MCSymbolRefExpr::create( -+ Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); -+ EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::BEQ) -+ .addReg(LoongArch::ZERO) -+ .addReg(LoongArch::ZERO) -+ .addExpr(TargetExpr)); -+ -+ for (int8_t I = 0; I < NoopsInSledCount; I++) -+ EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::ANDI) -+ .addReg(LoongArch::ZERO) -+ .addReg(LoongArch::ZERO) -+ .addImm(0)); -+ -+ OutStreamer->emitLabel(Target); -+ recordSled(CurSled, MI, Kind, 2); -+} -+ -+void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { -+ EmitSled(MI, SledKind::FUNCTION_ENTER); -+} -+ -+void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { -+ EmitSled(MI, SledKind::FUNCTION_EXIT); -+} -+ -+void LoongArchAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { -+ EmitSled(MI, SledKind::TAIL_CALL); -+} -+ -+void LoongArchAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, -+ raw_ostream &OS) { -+ // TODO: implement -+} -+ -+bool LoongArchAsmPrinter::isLongBranchPseudo(int Opcode) const { -+ return (Opcode == LoongArch::LONG_BRANCH_ADDIW -+ || Opcode == LoongArch::LONG_BRANCH_ADDIW2Op -+ || Opcode == LoongArch::LONG_BRANCH_ADDID -+ || Opcode == LoongArch::LONG_BRANCH_ADDID2Op -+ || Opcode == LoongArch::LONG_BRANCH_PCADDU12I); - } - - // Force static initialization. - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() { - RegisterAsmPrinter X(getTheLoongArch32Target()); -- RegisterAsmPrinter Y(getTheLoongArch64Target()); -+ RegisterAsmPrinter A(getTheLoongArch64Target()); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h -index b51c19188..3e4ca8ed1 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h -@@ -1,4 +1,4 @@ --//===- LoongArchAsmPrinter.h - LoongArch LLVM Assembly Printer -*- C++ -*--===// -+//===- LoongArchAsmPrinter.h - LoongArch LLVM Assembly Printer -----------*- C++ -*--===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -13,36 +13,123 @@ - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H - -+#include "LoongArchMCInstLower.h" - #include "LoongArchSubtarget.h" - #include "llvm/CodeGen/AsmPrinter.h" - #include "llvm/MC/MCStreamer.h" - #include "llvm/Support/Compiler.h" -+#include -+#include -+#include - - namespace llvm { - -+class MCOperand; -+class MCSubtargetInfo; -+class MCSymbol; -+class MachineBasicBlock; -+class MachineConstantPool; -+class MachineFunction; -+class MachineInstr; -+class MachineOperand; -+class LoongArchFunctionInfo; -+class LoongArchTargetStreamer; -+class Module; -+class raw_ostream; -+class TargetMachine; -+ - class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter { -- const MCSubtargetInfo *STI; -+ LoongArchTargetStreamer &getTargetStreamer() const; -+ -+ void EmitInstrWithMacroNoAT(const MachineInstr *MI); -+ -+ //===------------------------------------------------------------------===// -+ // XRay implementation -+ //===------------------------------------------------------------------===// - - public: -- explicit LoongArchAsmPrinter(TargetMachine &TM, -- std::unique_ptr Streamer) -- : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {} -+ // XRay-specific lowering for LoongArch. -+ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); -+ void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); -+ void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); - -- StringRef getPassName() const override { -- return "LoongArch Assembly Printer"; -- } -+private: -+ /// MCP - Keep a pointer to constantpool entries of the current -+ /// MachineFunction. -+ const MachineConstantPool *MCP = nullptr; - -- bool runOnMachineFunction(MachineFunction &MF) override; -+ /// InConstantPool - Maintain state when emitting a sequence of constant -+ /// pool entries so we can properly mark them as data regions. -+ bool InConstantPool = false; - -- void emitInstruction(const MachineInstr *MI) override; -+ void EmitSled(const MachineInstr &MI, SledKind Kind); - - // tblgen'erated function. - bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, - const MachineInstr *MI); -- // Wrapper needed for tblgenned pseudo lowering. -- bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const { -- return lowerLoongArchMachineOperandToMCOperand(MO, MCOp, *this); -- } -+ -+ // Emit PseudoReturn, PseudoReturn64, PseudoIndirectBranch, -+ // and PseudoIndirectBranch64 as a JIRL as appropriate -+ // for the target. -+ void emitPseudoIndirectBranch(MCStreamer &OutStreamer, -+ const MachineInstr *MI); -+ -+ void emitPseudoTailBranch(MCStreamer &OutStreamer, -+ const MachineInstr *MI); -+ -+ // lowerOperand - Convert a MachineOperand into the equivalent MCOperand. -+ bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); -+ -+ void emitInlineAsmStart() const override; -+ -+ void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, -+ const MCSubtargetInfo *EndInfo) const override; -+ -+ void EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, unsigned Reg); -+ -+ void EmitInstrRegReg(const MCSubtargetInfo &STI, unsigned Opcode, -+ unsigned Reg1, unsigned Reg2); -+ -+ void EmitInstrRegRegReg(const MCSubtargetInfo &STI, unsigned Opcode, -+ unsigned Reg1, unsigned Reg2, unsigned Reg3); -+ -+ void EmitMovFPIntPair(const MCSubtargetInfo &STI, unsigned MovOpc, -+ unsigned Reg1, unsigned Reg2, unsigned FPReg1, -+ unsigned FPReg2, bool LE); -+ -+ bool isLongBranchPseudo(int Opcode) const; -+ -+public: -+ const LoongArchSubtarget *Subtarget; -+ const LoongArchFunctionInfo *LoongArchFI; -+ LoongArchMCInstLower MCInstLowering; -+ -+ explicit LoongArchAsmPrinter(TargetMachine &TM, -+ std::unique_ptr Streamer) -+ : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {} -+ -+ StringRef getPassName() const override { return "LoongArch Assembly Printer"; } -+ -+ bool runOnMachineFunction(MachineFunction &MF) override; -+ -+ void emitInstruction(const MachineInstr *MI) override; -+ const char *getCurrentABIString() const; -+ void emitFunctionEntryLabel() override; -+ void emitFunctionBodyStart() override; -+ void emitFunctionBodyEnd() override; -+ void emitBasicBlockEnd(const MachineBasicBlock &MBB) override; -+ bool isBlockOnlyReachableByFallthrough( -+ const MachineBasicBlock* MBB) const override; -+ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, -+ const char *ExtraCode, raw_ostream &O) override; -+ bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, -+ const char *ExtraCode, raw_ostream &O) override; -+ void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); -+ void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); -+ void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); -+ void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O); -+ void emitStartOfAsmFile(Module &M) override; -+ void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); - }; - - } // end namespace llvm -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp -new file mode 100644 -index 000000000..6630ca759 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp -@@ -0,0 +1,165 @@ -+//===---- LoongArchCCState.cpp - CCState with LoongArch specific extensions ---------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchCCState.h" -+#include "LoongArchSubtarget.h" -+#include "llvm/IR/Module.h" -+ -+using namespace llvm; -+ -+/// This function returns true if CallSym is a long double emulation routine. -+static bool isF128SoftLibCall(const char *CallSym) { -+ const char *const LibCalls[] = { -+ "__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", -+ "__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti", -+ "__fixunstfdi", "__fixunstfsi", "__fixunstfti", "__floatditf", -+ "__floatsitf", "__floattitf", "__floatunditf", "__floatunsitf", -+ "__floatuntitf", "__getf2", "__gttf2", "__letf2", -+ "__lttf2", "__multf3", "__netf2", "__powitf2", -+ "__subtf3", "__trunctfdf2", "__trunctfsf2", "__unordtf2", -+ "ceill", "copysignl", "cosl", "exp2l", -+ "expl", "floorl", "fmal", "fmaxl", -+ "fmodl", "log10l", "log2l", "logl", -+ "nearbyintl", "powl", "rintl", "roundl", -+ "sinl", "sqrtl", "truncl"}; -+ -+ // Check that LibCalls is sorted alphabetically. -+ auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; }; -+ assert(std::is_sorted(std::begin(LibCalls), std::end(LibCalls), Comp)); -+ return std::binary_search(std::begin(LibCalls), std::end(LibCalls), -+ CallSym, Comp); -+} -+ -+/// This function returns true if Ty is fp128, {f128} or i128 which was -+/// originally a fp128. -+static bool originalTypeIsF128(const Type *Ty, const char *Func) { -+ if (Ty->isFP128Ty()) -+ return true; -+ -+ if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && -+ Ty->getStructElementType(0)->isFP128Ty()) -+ return true; -+ -+ // If the Ty is i128 and the function being called is a long double emulation -+ // routine, then the original type is f128. -+ return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func)); -+} -+ -+/// Return true if the original type was vXfXX. -+static bool originalEVTTypeIsVectorFloat(EVT Ty) { -+ if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint()) -+ return true; -+ -+ return false; -+} -+ -+/// Return true if the original type was vXfXX / vXfXX. -+static bool originalTypeIsVectorFloat(const Type * Ty) { -+ if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy()) -+ return true; -+ -+ return false; -+} -+ -+LoongArchCCState::SpecialCallingConvType -+LoongArchCCState::getSpecialCallingConvForCallee(const SDNode *Callee, -+ const LoongArchSubtarget &Subtarget) { -+ LoongArchCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; -+ return SpecialCallingConv; -+} -+ -+void LoongArchCCState::PreAnalyzeCallResultForF128( -+ const SmallVectorImpl &Ins, -+ const Type *RetTy, const char *Call) { -+ for (unsigned i = 0; i < Ins.size(); ++i) { -+ OriginalArgWasF128.push_back( -+ originalTypeIsF128(RetTy, Call)); -+ OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy()); -+ } -+} -+ -+/// Identify lowered values that originated from f128 or float arguments and -+/// record this for use by RetCC_LoongArchLP64LPX32. -+void LoongArchCCState::PreAnalyzeReturnForF128( -+ const SmallVectorImpl &Outs) { -+ const MachineFunction &MF = getMachineFunction(); -+ for (unsigned i = 0; i < Outs.size(); ++i) { -+ OriginalArgWasF128.push_back( -+ originalTypeIsF128(MF.getFunction().getReturnType(), nullptr)); -+ OriginalArgWasFloat.push_back( -+ MF.getFunction().getReturnType()->isFloatingPointTy()); -+ } -+} -+ -+/// Identify lower values that originated from vXfXX and record -+/// this. -+void LoongArchCCState::PreAnalyzeCallResultForVectorFloat( -+ const SmallVectorImpl &Ins, const Type *RetTy) { -+ for (unsigned i = 0; i < Ins.size(); ++i) { -+ OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy)); -+ } -+} -+ -+/// Identify lowered values that originated from vXfXX arguments and record -+/// this. -+void LoongArchCCState::PreAnalyzeReturnForVectorFloat( -+ const SmallVectorImpl &Outs) { -+ for (unsigned i = 0; i < Outs.size(); ++i) { -+ ISD::OutputArg Out = Outs[i]; -+ OriginalRetWasFloatVector.push_back( -+ originalEVTTypeIsVectorFloat(Out.ArgVT)); -+ } -+} -+ -+/// Identify lowered values that originated from f128, float and sret to vXfXX -+/// arguments and record this. -+void LoongArchCCState::PreAnalyzeCallOperands( -+ const SmallVectorImpl &Outs, -+ std::vector &FuncArgs, -+ const char *Func) { -+ for (unsigned i = 0; i < Outs.size(); ++i) { -+ TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex]; -+ -+ OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func)); -+ OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy()); -+ OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy()); -+ CallOperandIsFixed.push_back(Outs[i].IsFixed); -+ } -+} -+ -+/// Identify lowered values that originated from f128, float and vXfXX arguments -+/// and record this. -+void LoongArchCCState::PreAnalyzeFormalArgumentsForF128( -+ const SmallVectorImpl &Ins) { -+ const MachineFunction &MF = getMachineFunction(); -+ for (unsigned i = 0; i < Ins.size(); ++i) { -+ Function::const_arg_iterator FuncArg = MF.getFunction().arg_begin(); -+ -+ // SRet arguments cannot originate from f128 or {f128} returns so we just -+ // push false. We have to handle this specially since SRet arguments -+ // aren't mapped to an original argument. -+ if (Ins[i].Flags.isSRet()) { -+ OriginalArgWasF128.push_back(false); -+ OriginalArgWasFloat.push_back(false); -+ OriginalArgWasFloatVector.push_back(false); -+ continue; -+ } -+ -+ assert(Ins[i].getOrigArgIndex() < MF.getFunction().arg_size()); -+ std::advance(FuncArg, Ins[i].getOrigArgIndex()); -+ -+ OriginalArgWasF128.push_back( -+ originalTypeIsF128(FuncArg->getType(), nullptr)); -+ OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); -+ -+ // The LoongArch vector ABI exhibits a corner case of sorts or quirk; if the -+ // first argument is actually an SRet pointer to a vector, then the next -+ // argument slot is $a2. -+ OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy()); -+ } -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h -new file mode 100644 -index 000000000..1c1a1446e ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h -@@ -0,0 +1,165 @@ -+//===---- LoongArchCCState.h - CCState with LoongArch specific extensions -----------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LoongArchCCSTATE_H -+#define LoongArchCCSTATE_H -+ -+#include "LoongArchISelLowering.h" -+#include "llvm/ADT/SmallVector.h" -+#include "llvm/CodeGen/CallingConvLower.h" -+ -+namespace llvm { -+class SDNode; -+class LoongArchSubtarget; -+ -+class LoongArchCCState : public CCState { -+public: -+ enum SpecialCallingConvType { NoSpecialCallingConv }; -+ -+ /// Determine the SpecialCallingConvType for the given callee -+ static SpecialCallingConvType -+ getSpecialCallingConvForCallee(const SDNode *Callee, -+ const LoongArchSubtarget &Subtarget); -+ -+private: -+ /// Identify lowered values that originated from f128 arguments and record -+ /// this for use by RetCC_LoongArchLP64LPX32. -+ void PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, -+ const Type *RetTy, const char * Func); -+ -+ /// Identify lowered values that originated from f128 arguments and record -+ /// this for use by RetCC_LoongArchLP64LPX32. -+ void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs); -+ -+ /// Identify lowered values that originated from f128 arguments and record -+ /// this. -+ void -+ PreAnalyzeCallOperands(const SmallVectorImpl &Outs, -+ std::vector &FuncArgs, -+ const char *Func); -+ -+ /// Identify lowered values that originated from f128 arguments and record -+ /// this for use by RetCC_LoongArchLP64LPX32. -+ void -+ PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl &Ins); -+ -+ void -+ PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl &Ins, -+ const Type *RetTy); -+ -+ void PreAnalyzeFormalArgumentsForVectorFloat( -+ const SmallVectorImpl &Ins); -+ -+ void -+ PreAnalyzeReturnForVectorFloat(const SmallVectorImpl &Outs); -+ -+ /// Records whether the value has been lowered from an f128. -+ SmallVector OriginalArgWasF128; -+ -+ /// Records whether the value has been lowered from float. -+ SmallVector OriginalArgWasFloat; -+ -+ /// Records whether the value has been lowered from a floating point vector. -+ SmallVector OriginalArgWasFloatVector; -+ -+ /// Records whether the return value has been lowered from a floating point -+ /// vector. -+ SmallVector OriginalRetWasFloatVector; -+ -+ /// Records whether the value was a fixed argument. -+ /// See ISD::OutputArg::IsFixed, -+ SmallVector CallOperandIsFixed; -+ -+ // FIXME: This should probably be a fully fledged calling convention. -+ SpecialCallingConvType SpecialCallingConv; -+ -+public: -+ LoongArchCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, -+ SmallVectorImpl &locs, LLVMContext &C, -+ SpecialCallingConvType SpecialCC = NoSpecialCallingConv) -+ : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} -+ -+ void -+ AnalyzeCallOperands(const SmallVectorImpl &Outs, -+ CCAssignFn Fn, -+ std::vector &FuncArgs, -+ const char *Func) { -+ PreAnalyzeCallOperands(Outs, FuncArgs, Func); -+ CCState::AnalyzeCallOperands(Outs, Fn); -+ OriginalArgWasF128.clear(); -+ OriginalArgWasFloat.clear(); -+ OriginalArgWasFloatVector.clear(); -+ CallOperandIsFixed.clear(); -+ } -+ -+ // The AnalyzeCallOperands in the base class is not usable since we must -+ // provide a means of accessing ArgListEntry::IsFixed. Delete them from this -+ // class. This doesn't stop them being used via the base class though. -+ void AnalyzeCallOperands(const SmallVectorImpl &Outs, -+ CCAssignFn Fn) = delete; -+ void AnalyzeCallOperands(const SmallVectorImpl &Outs, -+ SmallVectorImpl &Flags, -+ CCAssignFn Fn) = delete; -+ -+ void AnalyzeFormalArguments(const SmallVectorImpl &Ins, -+ CCAssignFn Fn) { -+ PreAnalyzeFormalArgumentsForF128(Ins); -+ CCState::AnalyzeFormalArguments(Ins, Fn); -+ OriginalArgWasFloat.clear(); -+ OriginalArgWasF128.clear(); -+ OriginalArgWasFloatVector.clear(); -+ } -+ -+ void AnalyzeCallResult(const SmallVectorImpl &Ins, -+ CCAssignFn Fn, const Type *RetTy, -+ const char *Func) { -+ PreAnalyzeCallResultForF128(Ins, RetTy, Func); -+ PreAnalyzeCallResultForVectorFloat(Ins, RetTy); -+ CCState::AnalyzeCallResult(Ins, Fn); -+ OriginalArgWasFloat.clear(); -+ OriginalArgWasF128.clear(); -+ OriginalArgWasFloatVector.clear(); -+ } -+ -+ void AnalyzeReturn(const SmallVectorImpl &Outs, -+ CCAssignFn Fn) { -+ PreAnalyzeReturnForF128(Outs); -+ PreAnalyzeReturnForVectorFloat(Outs); -+ CCState::AnalyzeReturn(Outs, Fn); -+ OriginalArgWasFloat.clear(); -+ OriginalArgWasF128.clear(); -+ OriginalArgWasFloatVector.clear(); -+ } -+ -+ bool CheckReturn(const SmallVectorImpl &ArgsFlags, -+ CCAssignFn Fn) { -+ PreAnalyzeReturnForF128(ArgsFlags); -+ PreAnalyzeReturnForVectorFloat(ArgsFlags); -+ bool Return = CCState::CheckReturn(ArgsFlags, Fn); -+ OriginalArgWasFloat.clear(); -+ OriginalArgWasF128.clear(); -+ OriginalArgWasFloatVector.clear(); -+ return Return; -+ } -+ -+ bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } -+ bool WasOriginalArgFloat(unsigned ValNo) { -+ return OriginalArgWasFloat[ValNo]; -+ } -+ bool WasOriginalArgVectorFloat(unsigned ValNo) const { -+ return OriginalArgWasFloatVector[ValNo]; -+ } -+ bool WasOriginalRetVectorFloat(unsigned ValNo) const { -+ return OriginalRetWasFloatVector[ValNo]; -+ } -+ bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } -+ SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } -+}; -+} -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td -index 984416316..e8564e85b 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td -@@ -1,23 +1,310 @@ --//=- LoongArchCallingConv.td - Calling Conventions LoongArch -*- tablegen -*-=// -+//===-- LoongArchCallingConv.td - Calling Conventions for LoongArch --*- tablegen -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. - // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - // - //===----------------------------------------------------------------------===// -+// This describes the calling conventions for LoongArch architecture. -+//===----------------------------------------------------------------------===// -+ -+/// CCIfSubtarget - Match if the current subtarget has a feature F. -+class CCIfSubtarget -+ : CCIf" -+ "(State.getMachineFunction().getSubtarget()).", -+ F), -+ A>; -+ -+// The inverse of CCIfSubtarget -+class CCIfSubtargetNot : CCIfSubtarget; -+ -+/// Match if the original argument (before lowering) was a float. -+/// For example, this is true for i32's that were lowered from soft-float. -+class CCIfOrigArgWasNotFloat -+ : CCIf<"!static_cast(&State)->WasOriginalArgFloat(ValNo)", -+ A>; -+ -+/// Match if the original argument (before lowering) was a 128-bit float (i.e. -+/// long double). -+class CCIfOrigArgWasF128 -+ : CCIf<"static_cast(&State)->WasOriginalArgF128(ValNo)", A>; -+ -+/// Match if this specific argument is a vararg. -+/// This is slightly different fro CCIfIsVarArg which matches if any argument is -+/// a vararg. -+class CCIfArgIsVarArg -+ : CCIf<"!static_cast(&State)->IsCallOperandFixed(ValNo)", A>; -+ -+/// Match if the return was a floating point vector. -+class CCIfOrigArgWasNotVectorFloat -+ : CCIf<"!static_cast(&State)" -+ "->WasOriginalRetVectorFloat(ValNo)", A>; -+ -+/// Match if the special calling conv is the specified value. -+class CCIfSpecialCallingConv -+ : CCIf<"static_cast(&State)->getSpecialCallingConv() == " -+ "LoongArchCCState::" # CC, A>; -+ -+// For soft-float, f128 values are returned in A0_64 rather than V1_64. -+def RetCC_F128SoftFloat : CallingConv<[ -+ CCAssignToReg<[A0_64, A1_64]> -+]>; -+ - // --// This describes the calling conventions for the LoongArch architecture. --// -+// For hard-float, f128 values are returned as a pair of f64's rather than a -+// pair of i64's. -+def RetCC_F128HardFloat : CallingConv<[ -+ //CCBitConvertToType, -+ -+ // Contrary to the ABI documentation, a struct containing a long double is -+ // returned in $f0, and $f1 instead of the usual $f0, and $f2. This is to -+ // match the de facto ABI as implemented by GCC. -+ CCIfInReg>, -+ -+ CCAssignToReg<[A0_64, A1_64]> -+]>; -+ -+// Handle F128 specially since we can't identify the original type during the -+// tablegen-erated code. -+def RetCC_F128 : CallingConv<[ -+ CCIfSubtarget<"useSoftFloat()", -+ CCIfType<[i64], CCDelegateTo>>, -+ CCIfSubtargetNot<"useSoftFloat()", -+ CCIfType<[i64], CCDelegateTo>> -+]>; -+ -+//===----------------------------------------------------------------------===// -+// LoongArch LP32 Calling Convention -+//===----------------------------------------------------------------------===// -+ -+def CC_LoongArchLP32 : CallingConv<[ -+ // Promote i8/i16 arguments to i32. -+ CCIfType<[i1, i8, i16], CCPromoteToType>, -+ -+ // Integer values get stored in stack slots that are 4 bytes in -+ // size and 4-byte aligned. -+ CCIfType<[i32, f32], CCAssignToStack<4, 4>>, -+ -+ // Integer values get stored in stack slots that are 8 bytes in -+ // size and 8-byte aligned. -+ CCIfType<[f64], CCAssignToStack<8, 8>> -+]>; -+ -+// Only the return rules are defined here for LP32. The rules for argument -+// passing are defined in LoongArchISelLowering.cpp. -+def RetCC_LoongArchLP32 : CallingConv<[ -+ // Promote i1/i8/i16 return values to i32. -+ CCIfType<[i1, i8, i16], CCPromoteToType>, -+ -+ // i32 are returned in registers V0, V1, A0, A1, unless the original return -+ // type was a vector of floats. -+ CCIfOrigArgWasNotVectorFloat>>, -+ -+ // f32 are returned in registers F0, F2 -+ CCIfType<[f32], CCAssignToReg<[F0, F1]>>, -+ -+ // f64 arguments are returned in F0_64 and F2_64 in FP64bit mode or -+ // in F0 and F1 in FP32bit mode. -+ CCIfType<[f64], CCIfSubtarget<"isFP64bit()", CCAssignToReg<[F0_64, F1_64]>>> -+]>; -+ -+def CC_LoongArchLP32_FP32 : CustomCallingConv; -+def CC_LoongArchLP32_FP64 : CustomCallingConv; -+def CC_LoongArch_F128 : CustomCallingConv; -+ -+def CC_LoongArchLP32_FP : CallingConv<[ -+ CCIfSubtargetNot<"isFP64bit()", CCDelegateTo>, -+ CCIfSubtarget<"isFP64bit()", CCDelegateTo> -+]>; -+ -+//===----------------------------------------------------------------------===// -+// LoongArch LPX32/LP64 Calling Convention -+//===----------------------------------------------------------------------===// -+ -+def CC_LoongArchLP64LPX32_SoftFloat : CallingConv<[ -+ CCAssignToReg<[A0, A1, A2, A3, -+ A4, A5, A6, A7]>, -+ CCAssignToStack<4, 8> -+]>; -+ -+def CC_LoongArchLP64LPX32 : CallingConv<[ -+ -+ // All integers (except soft-float integers) are promoted to 64-bit. -+ CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat>>, -+ -+ // The only i32's we have left are soft-float arguments. -+ CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], CCDelegateTo>>, -+ -+ // Integer arguments are passed in integer registers. -+ //CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, -+ // A4_64, A5_64, A6_64, A7_64], -+ // [F0_64, F1_64, F2_64, F3_64, -+ // F4_64, F5_64, F6_64, F7_64]>>, -+ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, -+ A4_64, A5_64, A6_64, A7_64]>>, -+ -+ // f32 arguments are passed in single precision FP registers. -+ CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3, -+ F4, F5, F6, F7]>>, -+ -+ // f64 arguments are passed in double precision FP registers. -+ CCIfType<[f64], CCAssignToReg<[F0_64, F1_64, F2_64, F3_64, -+ F4_64, F5_64, F6_64, F7_64]>>, -+ -+ // others f32 arguments are passed in single precision FP registers. -+ CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, A4, A5, A6, A7]>>, -+ -+ // others f64 arguments are passed in double precision FP registers. -+ CCIfType<[f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, -+ A4_64, A5_64, A6_64, A7_64]>>, -+ -+ CCIfSubtarget<"hasLSX()", -+ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], -+ CCAssignToRegWithShadow<[VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7], -+ [A0_64, A1_64, A2_64, A3_64, -+ A4_64, A5_64, A6_64, A7_64]>>>, -+ CCIfSubtarget<"hasLASX()", -+ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], -+ CCAssignToRegWithShadow<[XR0, XR1, XR2, XR3, XR4, XR5, XR6, XR7], -+ [A0_64, A1_64, A2_64, A3_64, -+ A4_64, A5_64, A6_64, A7_64]>>>, -+ -+ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. -+ CCIfType<[f32], CCAssignToStack<4, 8>>, -+ CCIfType<[i64, f64], CCAssignToStack<8, 8>>, -+ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], -+ CCAssignToStack<16, 16>>, -+ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], -+ CCAssignToStack<32, 32>> -+]>; -+ -+// LPX32/LP64 variable arguments. -+// All arguments are passed in integer registers. -+def CC_LoongArchLP64LPX32_VarArg : CallingConv<[ -+ // All integers are promoted to 64-bit. -+ CCIfType<[i8, i16, i32], CCPromoteToType>, -+ -+ CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, A4, A5, A6, A7]>>, -+ -+ CCIfType<[i64], CCIfOrigArgWasF128>>, -+ -+ CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, -+ A4_64, A5_64, A6_64, A7_64]>>, -+ -+ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. -+ CCIfType<[f32], CCAssignToStack<4, 8>>, -+ CCIfType<[i64, f64], CCAssignToStack<8, 8>> -+]>; -+ -+def RetCC_LoongArchLP64LPX32 : CallingConv<[ -+ // f128 needs to be handled similarly to f32 and f64. However, f128 is not -+ // legal and is lowered to i128 which is further lowered to a pair of i64's. -+ // This presents us with a problem for the calling convention since hard-float -+ // still needs to pass them in FPU registers, and soft-float needs to use $v0, -+ // and $a0 instead of the usual $v0, and $v1. We therefore resort to a -+ // pre-analyze (see PreAnalyzeReturnForF128()) step to pass information on -+ // whether the result was originally an f128 into the tablegen-erated code. -+ // -+ // f128 should only occur for the LP64 ABI where long double is 128-bit. On -+ // LPX32, long double is equivalent to double. -+ CCIfType<[i64], CCIfOrigArgWasF128>>, -+ -+ CCIfType<[i8, i16, i32, i64], CCIfInReg>>, -+ -+ // i64 are returned in registers V0_64, V1_64 -+ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64]>>, -+ -+ CCIfSubtarget<"hasLSX()", -+ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToReg<[VR0]>>>, -+ -+ CCIfSubtarget<"hasLASX()", -+ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], CCAssignToReg<[XR0]>>>, -+ -+ CCIfSubtarget<"hasLASX()", -+ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64]>>>, -+ -+ // f32 are returned in registers F0, F2 -+ CCIfType<[f32], CCAssignToReg<[F0, F1]>>, -+ -+ // f64 are returned in registers D0, D2 -+ CCIfType<[f64], CCAssignToReg<[F0_64, F1_64]>> -+]>; -+ - //===----------------------------------------------------------------------===// -+// LoongArch Calling Convention Dispatch -+//===----------------------------------------------------------------------===// -+ -+def RetCC_LoongArch : CallingConv<[ -+ CCIfSubtarget<"isABI_LPX32()", CCDelegateTo>, -+ CCIfSubtarget<"isABI_LP64()", CCDelegateTo>, -+ CCDelegateTo -+]>; -+ -+def CC_LoongArch_ByVal : CallingConv<[ -+ CCIfSubtarget<"isABI_LP32()", CCIfByVal>>, -+ CCIfByVal> -+]>; -+ -+def CC_LoongArch_FixedArg : CallingConv<[ -+ CCIfByVal>, -+ //CCIfByVal>>, -+ -+ // f128 needs to be handled similarly to f32 and f64 on hard-float. However, -+ // f128 is not legal and is lowered to i128 which is further lowered to a pair -+ // of i64's. -+ // This presents us with a problem for the calling convention since hard-float -+ // still needs to pass them in FPU registers. We therefore resort to a -+ // pre-analyze (see PreAnalyzeFormalArgsForF128()) step to pass information on -+ // whether the argument was originally an f128 into the tablegen-erated code. -+ // -+ // f128 should only occur for the LP64 ABI where long double is 128-bit. On -+ // LPX32, long double is equivalent to double. -+ CCIfType<[i64], -+ CCIfSubtargetNot<"useSoftFloat()", -+ CCIfOrigArgWasF128>>>, -+ -+ CCIfSubtarget<"isABI_LP32()", CCDelegateTo>, -+ CCDelegateTo -+]>; -+ -+def CC_LoongArch_VarArg : CallingConv<[ -+ CCIfByVal>, -+ -+ CCIfSubtarget<"isABI_LP32()", CCDelegateTo>, -+ CCDelegateTo -+]>; -+ -+def CC_LoongArch : CallingConv<[ -+ CCIfVarArg>>, -+ CCDelegateTo -+]>; -+ -+//===----------------------------------------------------------------------===// -+// Callee-saved register lists. -+//===----------------------------------------------------------------------===// -+ -+def CSR_SingleFloatOnly : CalleeSavedRegs<(add (sequence "F%u", 31, 24), RA, FP, -+ (sequence "S%u", 8, 0))>; -+ -+//def CSR_LP32_FPXX : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, -+// (sequence "S%u", 8, 0))> { -+// let OtherPreserved = (add (decimate (sequence "F%u", 30, 20), 2)); -+//} - --def CSR_ILP32S_LP64S -- : CalleeSavedRegs<(add R1, (sequence "R%u", 22, 31))>; -+def CSR_LP32 : CalleeSavedRegs<(add (sequence "F%u_64", 31, 24), RA, FP, -+ (sequence "S%u", 8, 0))>; - --def CSR_ILP32F_LP64F -- : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u", 24, 31))>; -+//def CSR_LP32_FP64 : -+// CalleeSavedRegs<(add (decimate (sequence "D%u_64", 30, 20), 2), RA, FP, -+// (sequence "S%u", 8, 0))>; - --def CSR_ILP32D_LP64D -- : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u_64", 24, 31))>; -+def CSR_LPX32 : CalleeSavedRegs<(add F20_64, F22_64, F24_64, F26_64, F28_64, -+ F30_64, RA_64, FP_64, -+ (sequence "S%u_64", 8, 0))>; - --// Needed for implementation of LoongArchRegisterInfo::getNoPreservedMask() --def CSR_NoRegs : CalleeSavedRegs<(add)>; -+//def CSR_LP64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, SP_64, FP_64, -+def CSR_LP64 : CalleeSavedRegs<(add (sequence "F%u_64", 31, 24), RA_64, FP_64, -+ (sequence "S%u_64", 8, 0))>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp -new file mode 100644 -index 000000000..0f33e1db6 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp -@@ -0,0 +1,2471 @@ -+//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file contains a pass that expands pseudo instructions into target -+// instructions to allow proper scheduling, if-conversion, and other late -+// optimizations. This pass should be run after register allocation but before -+// the post-regalloc scheduling pass. -+// -+// This is currently only used for expanding atomic pseudos after register -+// allocation. We do this to avoid the fast register allocator introducing -+// spills between ll and sc. These stores cause some LoongArch implementations to -+// abort the atomic RMW sequence. -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArch.h" -+#include "LoongArchInstrInfo.h" -+#include "LoongArchSubtarget.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/CodeGen/LivePhysRegs.h" -+#include "llvm/CodeGen/MachineFunctionPass.h" -+#include "llvm/CodeGen/MachineInstrBuilder.h" -+ -+using namespace llvm; -+ -+#define DEBUG_TYPE "loongarch-pseudo" -+ -+namespace { -+ class LoongArchExpandPseudo : public MachineFunctionPass { -+ public: -+ static char ID; -+ LoongArchExpandPseudo() : MachineFunctionPass(ID) {} -+ -+ const LoongArchInstrInfo *TII; -+ const LoongArchSubtarget *STI; -+ -+ bool runOnMachineFunction(MachineFunction &Fn) override; -+ -+ MachineFunctionProperties getRequiredProperties() const override { -+ return MachineFunctionProperties().set( -+ MachineFunctionProperties::Property::NoVRegs); -+ } -+ -+ StringRef getPassName() const override { -+ return "LoongArch pseudo instruction expansion pass"; -+ } -+ -+ private: -+ bool expandAtomicCmpSwap(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MBBI, -+ MachineBasicBlock::iterator &NextMBBI); -+ bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MBBI, -+ MachineBasicBlock::iterator &NextMBBI); -+ -+ bool expandAtomicBinOp(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI, unsigned Size); -+ bool expandXINSERT_BOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ bool expandINSERT_HOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ bool expandXINSERT_FWOp(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ bool expandAtomicBinOpSubword(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ -+ bool expandPseudoCall(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ bool expandPseudoTailCall(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I); -+ -+ bool expandPseudoTEQ(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ -+ bool expandLoadAddr(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI); -+ -+ bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, -+ MachineBasicBlock::iterator &NMBB); -+ bool expandMBB(MachineBasicBlock &MBB); -+ }; -+ char LoongArchExpandPseudo::ID = 0; -+} -+ -+static bool hasDbar(MachineBasicBlock *MBB) { -+ -+ for (MachineBasicBlock::iterator MBBb = MBB->begin(), MBBe = MBB->end(); -+ MBBb != MBBe; ++MBBb) { -+ if (MBBb->getOpcode() == LoongArch::DBAR) -+ return true; -+ if (MBBb->mayLoad() || MBBb->mayStore()) -+ break; -+ } -+ return false; -+} -+ -+bool LoongArchExpandPseudo::expandAtomicCmpSwapSubword( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ unsigned LL, SC; -+ unsigned ZERO = LoongArch::ZERO; -+ unsigned BNE = LoongArch::BNE32; -+ unsigned BEQ = LoongArch::BEQ32; -+ unsigned SEOp = -+ I->getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA ? LoongArch::EXT_W_B32 : LoongArch::EXT_W_H32; -+ -+ LL = LoongArch::LL_W; -+ SC = LoongArch::SC_W; -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned Ptr = I->getOperand(1).getReg(); -+ unsigned Mask = I->getOperand(2).getReg(); -+ unsigned ShiftCmpVal = I->getOperand(3).getReg(); -+ unsigned Mask2 = I->getOperand(4).getReg(); -+ unsigned ShiftNewVal = I->getOperand(5).getReg(); -+ unsigned ShiftAmnt = I->getOperand(6).getReg(); -+ unsigned Scratch = I->getOperand(7).getReg(); -+ unsigned Scratch2 = I->getOperand(8).getReg(); -+ -+ // insert new blocks after the current block -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB.getIterator(); -+ MF->insert(It, loop1MBB); -+ MF->insert(It, loop2MBB); -+ MF->insert(It, sinkMBB); -+ MF->insert(It, exitMBB); -+ -+ // Transfer the remainder of BB and its successor edges to exitMBB. -+ exitMBB->splice(exitMBB->begin(), &BB, -+ std::next(MachineBasicBlock::iterator(I)), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ // thisMBB: -+ // ... -+ // fallthrough --> loop1MBB -+ BB.addSuccessor(loop1MBB, BranchProbability::getOne()); -+ loop1MBB->addSuccessor(sinkMBB); -+ loop1MBB->addSuccessor(loop2MBB); -+ loop1MBB->normalizeSuccProbs(); -+ loop2MBB->addSuccessor(loop1MBB); -+ loop2MBB->addSuccessor(sinkMBB); -+ loop2MBB->normalizeSuccProbs(); -+ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ -+ // loop1MBB: -+ // ll dest, 0(ptr) -+ // and Mask', dest, Mask -+ // bne Mask', ShiftCmpVal, exitMBB -+ BuildMI(loop1MBB, DL, TII->get(LL), Scratch).addReg(Ptr).addImm(0); -+ BuildMI(loop1MBB, DL, TII->get(LoongArch::AND32), Scratch2) -+ .addReg(Scratch) -+ .addReg(Mask); -+ BuildMI(loop1MBB, DL, TII->get(BNE)) -+ .addReg(Scratch2).addReg(ShiftCmpVal).addMBB(sinkMBB); -+ -+ // loop2MBB: -+ // and dest, dest, mask2 -+ // or dest, dest, ShiftNewVal -+ // sc dest, dest, 0(ptr) -+ // beq dest, $0, loop1MBB -+ BuildMI(loop2MBB, DL, TII->get(LoongArch::AND32), Scratch) -+ .addReg(Scratch, RegState::Kill) -+ .addReg(Mask2); -+ BuildMI(loop2MBB, DL, TII->get(LoongArch::OR32), Scratch) -+ .addReg(Scratch, RegState::Kill) -+ .addReg(ShiftNewVal); -+ BuildMI(loop2MBB, DL, TII->get(SC), Scratch) -+ .addReg(Scratch, RegState::Kill) -+ .addReg(Ptr) -+ .addImm(0); -+ BuildMI(loop2MBB, DL, TII->get(BEQ)) -+ .addReg(Scratch, RegState::Kill) -+ .addReg(ZERO) -+ .addMBB(loop1MBB); -+ -+ // sinkMBB: -+ // srl srlres, Mask', shiftamt -+ // sign_extend dest,srlres -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::SRL_W), Dest) -+ .addReg(Scratch2) -+ .addReg(ShiftAmnt); -+ -+ BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); -+ -+ if (!hasDbar(sinkMBB)) { -+ MachineBasicBlock::iterator Pos = sinkMBB->begin(); -+ BuildMI(*sinkMBB, Pos, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); -+ } -+ -+ LivePhysRegs LiveRegs; -+ computeAndAddLiveIns(LiveRegs, *loop1MBB); -+ computeAndAddLiveIns(LiveRegs, *loop2MBB); -+ computeAndAddLiveIns(LiveRegs, *sinkMBB); -+ computeAndAddLiveIns(LiveRegs, *exitMBB); -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ const unsigned Size = -+ I->getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8; -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ -+ unsigned LL, SC, ZERO, BNE, BEQ, MOVE; -+ -+ if (Size == 4) { -+ LL = LoongArch::LL_W; -+ SC = LoongArch::SC_W; -+ BNE = LoongArch::BNE32; -+ BEQ = LoongArch::BEQ32; -+ -+ ZERO = LoongArch::ZERO; -+ MOVE = LoongArch::OR32; -+ } else { -+ LL = LoongArch::LL_D; -+ SC = LoongArch::SC_D; -+ ZERO = LoongArch::ZERO_64; -+ BNE = LoongArch::BNE; -+ BEQ = LoongArch::BEQ; -+ MOVE = LoongArch::OR; -+ } -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned Ptr = I->getOperand(1).getReg(); -+ unsigned OldVal = I->getOperand(2).getReg(); -+ unsigned NewVal = I->getOperand(3).getReg(); -+ unsigned Scratch = I->getOperand(4).getReg(); -+ -+ // insert new blocks after the current block -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB.getIterator(); -+ MF->insert(It, loop1MBB); -+ MF->insert(It, loop2MBB); -+ MF->insert(It, exitMBB); -+ -+ // Transfer the remainder of BB and its successor edges to exitMBB. -+ exitMBB->splice(exitMBB->begin(), &BB, -+ std::next(MachineBasicBlock::iterator(I)), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ // thisMBB: -+ // ... -+ // fallthrough --> loop1MBB -+ BB.addSuccessor(loop1MBB, BranchProbability::getOne()); -+ loop1MBB->addSuccessor(exitMBB); -+ loop1MBB->addSuccessor(loop2MBB); -+ loop1MBB->normalizeSuccProbs(); -+ loop2MBB->addSuccessor(loop1MBB); -+ loop2MBB->addSuccessor(exitMBB); -+ loop2MBB->normalizeSuccProbs(); -+ -+ // loop1MBB: -+ // ll dest, 0(ptr) -+ // bne dest, oldval, exitMBB -+ BuildMI(loop1MBB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); -+ BuildMI(loop1MBB, DL, TII->get(BNE)) -+ .addReg(Dest, RegState::Kill).addReg(OldVal).addMBB(exitMBB); -+ -+ // loop2MBB: -+ // move scratch, NewVal -+ // sc Scratch, Scratch, 0(ptr) -+ // beq Scratch, $0, loop1MBB -+ BuildMI(loop2MBB, DL, TII->get(MOVE), Scratch).addReg(NewVal).addReg(ZERO); -+ BuildMI(loop2MBB, DL, TII->get(SC), Scratch) -+ .addReg(Scratch).addReg(Ptr).addImm(0); -+ BuildMI(loop2MBB, DL, TII->get(BEQ)) -+ .addReg(Scratch, RegState::Kill).addReg(ZERO).addMBB(loop1MBB); -+ -+ if (!hasDbar(exitMBB)) { -+ MachineBasicBlock::iterator Pos = exitMBB->begin(); -+ BuildMI(*exitMBB, Pos, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); -+ } -+ -+ LivePhysRegs LiveRegs; -+ computeAndAddLiveIns(LiveRegs, *loop1MBB); -+ computeAndAddLiveIns(LiveRegs, *loop2MBB); -+ computeAndAddLiveIns(LiveRegs, *exitMBB); -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandXINSERT_FWOp( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ -+ unsigned isGP64 = 0; -+ switch (I->getOpcode()) { -+ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: -+ isGP64 = 1; -+ break; -+ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: -+ break; -+ default: -+ llvm_unreachable("Unknown subword vector pseudo for expansion!"); -+ } -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned SrcVecReg = I->getOperand(1).getReg(); -+ unsigned LaneReg = I->getOperand(2).getReg(); -+ unsigned SrcValReg = I->getOperand(3).getReg(); -+ -+ unsigned Dsttmp = I->getOperand(4).getReg(); -+ unsigned RI = I->getOperand(5).getReg(); -+ unsigned RJ = I->getOperand(6).getReg(); -+ Dsttmp = SrcVecReg; -+ -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *blocks[11]; -+ MachineFunction::iterator It = ++BB.getIterator(); -+ for (int i = 0; i < 11; i++) { -+ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); -+ MF->insert(It, blocks[i]); -+ } -+ -+ MachineBasicBlock *mainMBB = blocks[0]; -+ MachineBasicBlock *FirstMBB = blocks[1]; -+ MachineBasicBlock *sinkMBB = blocks[9]; -+ MachineBasicBlock *exitMBB = blocks[10]; -+ -+ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ BB.addSuccessor(mainMBB, BranchProbability::getOne()); -+ for (int i = 1; i < 9; i++) { -+ mainMBB->addSuccessor(blocks[i]); -+ blocks[i]->addSuccessor(sinkMBB); -+ } -+ -+ unsigned ADDI, BLT, ZERO; -+ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; -+ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; -+ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ -+ for (int i = 1; i < 8; i++) { -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); -+ BuildMI(mainMBB, DL, TII->get(BLT)) -+ .addReg(LaneReg) -+ .addReg(RI) -+ .addMBB(blocks[i + 1]); -+ } -+ -+ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); -+ -+ BuildMI(FirstMBB, DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) -+ .addReg(SrcVecReg) -+ .addReg(RJ) -+ .addImm(7); -+ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ for (int i = 0; i < 7; i++) { -+ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) -+ .addReg(SrcVecReg) -+ .addReg(RJ) -+ .addImm(i); -+ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ } -+ -+ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) -+ .addReg(Dsttmp) -+ .addImm(0); -+ -+ LivePhysRegs LiveRegs; -+ for (int i = 0; i < 11; i++) { -+ computeAndAddLiveIns(LiveRegs, *blocks[i]); -+ } -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandINSERT_HOp( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ -+ unsigned isGP64 = 0; -+ switch (I->getOpcode()) { -+ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: -+ isGP64 = 1; -+ break; -+ default: -+ llvm_unreachable("Unknown subword vector pseudo for expansion!"); -+ } -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned SrcVecReg = I->getOperand(1).getReg(); -+ unsigned LaneReg = I->getOperand(2).getReg(); -+ unsigned SrcValReg = I->getOperand(3).getReg(); -+ -+ unsigned Dsttmp = I->getOperand(4).getReg(); -+ unsigned RI = I->getOperand(5).getReg(); -+ Dsttmp = SrcVecReg; -+ -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *blocks[11]; -+ MachineFunction::iterator It = ++BB.getIterator(); -+ for (int i = 0; i < 11; i++) { -+ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); -+ MF->insert(It, blocks[i]); -+ } -+ -+ MachineBasicBlock *mainMBB = blocks[0]; -+ MachineBasicBlock *FirstMBB = blocks[1]; -+ MachineBasicBlock *sinkMBB = blocks[9]; -+ MachineBasicBlock *exitMBB = blocks[10]; -+ -+ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ BB.addSuccessor(mainMBB, BranchProbability::getOne()); -+ for (int i = 1; i < 9; i++) { -+ mainMBB->addSuccessor(blocks[i]); -+ blocks[i]->addSuccessor(sinkMBB); -+ } -+ -+ unsigned ADDI, BLT, ZERO; -+ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; -+ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; -+ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ -+ for (int i = 1; i < 8; i++) { -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); -+ BuildMI(mainMBB, DL, TII->get(BLT)) -+ .addReg(LaneReg) -+ .addReg(RI) -+ .addMBB(blocks[i + 1]); -+ } -+ -+ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); -+ -+ BuildMI(FirstMBB, DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) -+ .addReg(SrcVecReg) -+ .addReg(SrcValReg) -+ .addImm(7); -+ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ for (int i = 0; i < 7; i++) { -+ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) -+ .addReg(SrcVecReg) -+ .addReg(SrcValReg) -+ .addImm(i); -+ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ } -+ -+ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::VORI_B), Dest) -+ .addReg(Dsttmp) -+ .addImm(0); -+ -+ LivePhysRegs LiveRegs; -+ for (int i = 0; i < 11; i++) { -+ computeAndAddLiveIns(LiveRegs, *blocks[i]); -+ } -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandXINSERT_BOp( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ -+ unsigned isGP64 = 0; -+ switch (I->getOpcode()) { -+ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: -+ isGP64 = 1; -+ break; -+ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: -+ break; -+ default: -+ llvm_unreachable("Unknown subword vector pseudo for expansion!"); -+ } -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned SrcVecReg = I->getOperand(1).getReg(); -+ unsigned LaneReg = I->getOperand(2).getReg(); -+ unsigned SrcValReg = I->getOperand(3).getReg(); -+ -+ unsigned R4r = I->getOperand(5).getReg(); -+ unsigned Rib = I->getOperand(6).getReg(); -+ unsigned Ris = I->getOperand(7).getReg(); -+ unsigned R7b1 = I->getOperand(8).getReg(); -+ unsigned R7b2 = I->getOperand(9).getReg(); -+ unsigned R7b3 = I->getOperand(10).getReg(); -+ unsigned R7r80_3 = I->getOperand(11).getReg(); -+ unsigned R7r80l_3 = I->getOperand(12).getReg(); -+ unsigned R7r81_3 = I->getOperand(13).getReg(); -+ unsigned R7r81l_3 = I->getOperand(14).getReg(); -+ unsigned R7r82_3 = I->getOperand(15).getReg(); -+ unsigned R7r82l_3 = I->getOperand(16).getReg(); -+ unsigned RI = I->getOperand(17).getReg(); -+ unsigned tmp_Dst73 = I->getOperand(18).getReg(); -+ unsigned Rimm = I->getOperand(19).getReg(); -+ unsigned R70 = I->getOperand(20).getReg(); -+ tmp_Dst73 = SrcVecReg; -+ -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SevenMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SevenMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SevenMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SevenMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SevenMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ZeroMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ZeroMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ZeroMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ZeroMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ZeroMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *OneMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *OneMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *OneMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *OneMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *OneMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TwoMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TwoMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TwoMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TwoMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TwoMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ThreeMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ThreeMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ThreeMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ThreeMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *ThreeMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FourMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FourMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FourMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FourMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FourMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FiveMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FiveMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FiveMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FiveMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *FiveMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SixMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SixMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SixMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SixMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *SixMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB.getIterator(); -+ MF->insert(It, mainMBB); -+ MF->insert(It, SevenMBB); -+ MF->insert(It, SevenMBB3); -+ MF->insert(It, SevenMBB0); -+ MF->insert(It, SevenMBB1); -+ MF->insert(It, SevenMBB2); -+ MF->insert(It, ZeroMBB); -+ MF->insert(It, ZeroMBB3); -+ MF->insert(It, ZeroMBB0); -+ MF->insert(It, ZeroMBB1); -+ MF->insert(It, ZeroMBB2); -+ MF->insert(It, OneMBB); -+ MF->insert(It, OneMBB3); -+ MF->insert(It, OneMBB0); -+ MF->insert(It, OneMBB1); -+ MF->insert(It, OneMBB2); -+ MF->insert(It, TwoMBB); -+ MF->insert(It, TwoMBB3); -+ MF->insert(It, TwoMBB0); -+ MF->insert(It, TwoMBB1); -+ MF->insert(It, TwoMBB2); -+ MF->insert(It, ThreeMBB); -+ MF->insert(It, ThreeMBB3); -+ MF->insert(It, ThreeMBB0); -+ MF->insert(It, ThreeMBB1); -+ MF->insert(It, ThreeMBB2); -+ MF->insert(It, FourMBB); -+ MF->insert(It, FourMBB3); -+ MF->insert(It, FourMBB0); -+ MF->insert(It, FourMBB1); -+ MF->insert(It, FourMBB2); -+ MF->insert(It, FiveMBB); -+ MF->insert(It, FiveMBB3); -+ MF->insert(It, FiveMBB0); -+ MF->insert(It, FiveMBB1); -+ MF->insert(It, FiveMBB2); -+ MF->insert(It, SixMBB); -+ MF->insert(It, SixMBB3); -+ MF->insert(It, SixMBB0); -+ MF->insert(It, SixMBB1); -+ MF->insert(It, SixMBB2); -+ MF->insert(It, sinkMBB); -+ MF->insert(It, exitMBB); -+ -+ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ BB.addSuccessor(mainMBB, BranchProbability::getOne()); -+ mainMBB->addSuccessor(SevenMBB); -+ mainMBB->addSuccessor(ZeroMBB); -+ mainMBB->addSuccessor(OneMBB); -+ mainMBB->addSuccessor(TwoMBB); -+ mainMBB->addSuccessor(ThreeMBB); -+ mainMBB->addSuccessor(FourMBB); -+ mainMBB->addSuccessor(FiveMBB); -+ mainMBB->addSuccessor(SixMBB); -+ SevenMBB->addSuccessor(SevenMBB0); -+ SevenMBB->addSuccessor(SevenMBB1); -+ SevenMBB->addSuccessor(SevenMBB2); -+ SevenMBB->addSuccessor(SevenMBB3); -+ SevenMBB0->addSuccessor(sinkMBB); -+ SevenMBB1->addSuccessor(sinkMBB); -+ SevenMBB2->addSuccessor(sinkMBB); -+ SevenMBB3->addSuccessor(sinkMBB); -+ ZeroMBB->addSuccessor(ZeroMBB0); -+ ZeroMBB->addSuccessor(ZeroMBB1); -+ ZeroMBB->addSuccessor(ZeroMBB2); -+ ZeroMBB->addSuccessor(ZeroMBB3); -+ ZeroMBB0->addSuccessor(sinkMBB); -+ ZeroMBB1->addSuccessor(sinkMBB); -+ ZeroMBB2->addSuccessor(sinkMBB); -+ ZeroMBB3->addSuccessor(sinkMBB); -+ OneMBB->addSuccessor(OneMBB0); -+ OneMBB->addSuccessor(OneMBB1); -+ OneMBB->addSuccessor(OneMBB2); -+ OneMBB->addSuccessor(OneMBB3); -+ OneMBB0->addSuccessor(sinkMBB); -+ OneMBB1->addSuccessor(sinkMBB); -+ OneMBB2->addSuccessor(sinkMBB); -+ OneMBB3->addSuccessor(sinkMBB); -+ TwoMBB->addSuccessor(TwoMBB0); -+ TwoMBB->addSuccessor(TwoMBB1); -+ TwoMBB->addSuccessor(TwoMBB2); -+ TwoMBB->addSuccessor(TwoMBB3); -+ TwoMBB0->addSuccessor(sinkMBB); -+ TwoMBB1->addSuccessor(sinkMBB); -+ TwoMBB2->addSuccessor(sinkMBB); -+ TwoMBB3->addSuccessor(sinkMBB); -+ ThreeMBB->addSuccessor(ThreeMBB0); -+ ThreeMBB->addSuccessor(ThreeMBB1); -+ ThreeMBB->addSuccessor(ThreeMBB2); -+ ThreeMBB->addSuccessor(ThreeMBB3); -+ ThreeMBB0->addSuccessor(sinkMBB); -+ ThreeMBB1->addSuccessor(sinkMBB); -+ ThreeMBB2->addSuccessor(sinkMBB); -+ ThreeMBB3->addSuccessor(sinkMBB); -+ FourMBB->addSuccessor(FourMBB0); -+ FourMBB->addSuccessor(FourMBB1); -+ FourMBB->addSuccessor(FourMBB2); -+ FourMBB->addSuccessor(FourMBB3); -+ FourMBB0->addSuccessor(sinkMBB); -+ FourMBB1->addSuccessor(sinkMBB); -+ FourMBB2->addSuccessor(sinkMBB); -+ FourMBB3->addSuccessor(sinkMBB); -+ FiveMBB->addSuccessor(FiveMBB0); -+ FiveMBB->addSuccessor(FiveMBB1); -+ FiveMBB->addSuccessor(FiveMBB2); -+ FiveMBB->addSuccessor(FiveMBB3); -+ FiveMBB0->addSuccessor(sinkMBB); -+ FiveMBB1->addSuccessor(sinkMBB); -+ FiveMBB2->addSuccessor(sinkMBB); -+ FiveMBB3->addSuccessor(sinkMBB); -+ SixMBB->addSuccessor(SixMBB0); -+ SixMBB->addSuccessor(SixMBB1); -+ SixMBB->addSuccessor(SixMBB2); -+ SixMBB->addSuccessor(SixMBB3); -+ SixMBB0->addSuccessor(sinkMBB); -+ SixMBB1->addSuccessor(sinkMBB); -+ SixMBB2->addSuccessor(sinkMBB); -+ SixMBB3->addSuccessor(sinkMBB); -+ -+ unsigned SRLI, ADDI, OR, MOD, BLT, ZERO; -+ SRLI = isGP64 ? LoongArch::SRLI_D : LoongArch::SRLI_W; -+ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; -+ OR = isGP64 ? LoongArch::OR : LoongArch::OR32; -+ MOD = isGP64 ? LoongArch::MOD_DU : LoongArch::MOD_WU; -+ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; -+ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ -+ BuildMI(mainMBB, DL, TII->get(SRLI), Rimm).addReg(LaneReg).addImm(2); -+ BuildMI(mainMBB, DL, TII->get(ADDI), R4r).addReg(ZERO).addImm(4); -+ BuildMI(mainMBB, DL, TII->get(OR), Rib).addReg(Rimm).addReg(ZERO); -+ BuildMI(mainMBB, DL, TII->get(MOD), Ris).addReg(Rib).addReg(R4r); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(1); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ZeroMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(2); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(OneMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(3); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(TwoMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(4); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ThreeMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(5); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FourMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(6); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FiveMBB); -+ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(7); -+ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(SixMBB); -+ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB); -+ -+ BuildMI(SevenMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(7); -+ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(SevenMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b1) -+ .addMBB(SevenMBB0); -+ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(SevenMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b2) -+ .addMBB(SevenMBB1); -+ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(SevenMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b3) -+ .addMBB(SevenMBB2); -+ BuildMI(SevenMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB3); -+ -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0x00fff); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(7); -+ BuildMI(SevenMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xff00f); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(7); -+ BuildMI(SevenMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xffff0); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(7); -+ BuildMI(SevenMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xfffff); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(7); -+ BuildMI(SevenMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ZeroMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(0); -+ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(ZeroMBB0); -+ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(ZeroMBB1); -+ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(ZeroMBB2); -+ BuildMI(ZeroMBB, DL, TII->get(LoongArch::B32)).addMBB(ZeroMBB3); -+ -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(0); -+ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(0); -+ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(0); -+ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(0); -+ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(OneMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(1); -+ BuildMI(OneMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(OneMBB0); -+ BuildMI(OneMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(OneMBB1); -+ BuildMI(OneMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(OneMBB2); -+ BuildMI(OneMBB, DL, TII->get(LoongArch::B32)).addMBB(OneMBB3); -+ -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(1); -+ BuildMI(OneMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(1); -+ BuildMI(OneMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(1); -+ BuildMI(OneMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(1); -+ BuildMI(OneMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(TwoMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(2); -+ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(TwoMBB0); -+ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(TwoMBB1); -+ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(TwoMBB2); -+ BuildMI(TwoMBB, DL, TII->get(LoongArch::B32)).addMBB(TwoMBB3); -+ -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(2); -+ BuildMI(TwoMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(2); -+ BuildMI(TwoMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(2); -+ BuildMI(TwoMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(2); -+ BuildMI(TwoMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ThreeMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(3); -+ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(ThreeMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b1) -+ .addMBB(ThreeMBB0); -+ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(ThreeMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b2) -+ .addMBB(ThreeMBB1); -+ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(ThreeMBB, DL, TII->get(BLT)) -+ .addReg(Ris) -+ .addReg(R7b3) -+ .addMBB(ThreeMBB2); -+ BuildMI(ThreeMBB, DL, TII->get(LoongArch::B32)).addMBB(ThreeMBB3); -+ -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0x00fff); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(3); -+ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xff00f); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(3); -+ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xffff0); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(3); -+ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) -+ .addImm(0xfffff); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(3); -+ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FourMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(4); -+ BuildMI(FourMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FourMBB0); -+ BuildMI(FourMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FourMBB1); -+ BuildMI(FourMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FourMBB2); -+ BuildMI(FourMBB, DL, TII->get(LoongArch::B32)).addMBB(FourMBB3); -+ -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(4); -+ BuildMI(FourMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(4); -+ BuildMI(FourMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(4); -+ BuildMI(FourMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(4); -+ BuildMI(FourMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FiveMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(5); -+ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FiveMBB0); -+ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FiveMBB1); -+ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FiveMBB2); -+ BuildMI(FiveMBB, DL, TII->get(LoongArch::B32)).addMBB(FiveMBB3); -+ -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(5); -+ BuildMI(FiveMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(5); -+ BuildMI(FiveMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(5); -+ BuildMI(FiveMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(5); -+ BuildMI(FiveMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SixMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) -+ .addReg(SrcVecReg) -+ .addImm(6); -+ BuildMI(SixMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); -+ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(SixMBB0); -+ BuildMI(SixMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); -+ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(SixMBB1); -+ BuildMI(SixMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); -+ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(SixMBB2); -+ BuildMI(SixMBB, DL, TII->get(LoongArch::B32)).addMBB(SixMBB3); -+ -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80_3); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(6); -+ BuildMI(SixMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(8); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xfff); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(6); -+ BuildMI(SixMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(16); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0x0ff); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(6); -+ BuildMI(SixMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) -+ .addReg(SrcValReg) -+ .addImm(24); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) -+ .addReg(R7r80_3) -+ .addImm(24); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) -+ .addReg(R7r81l_3) -+ .addImm(0xf00); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) -+ .addReg(R70) -+ .addReg(R7r81_3); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) -+ .addReg(R7r82l_3) -+ .addReg(R7r80l_3); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) -+ .addReg(SrcVecReg) -+ .addReg(R7r82_3) -+ .addImm(6); -+ BuildMI(SixMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); -+ -+ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) -+ .addReg(tmp_Dst73) -+ .addImm(0); -+ -+ LivePhysRegs LiveRegs; -+ computeAndAddLiveIns(LiveRegs, *mainMBB); -+ computeAndAddLiveIns(LiveRegs, *SevenMBB); -+ computeAndAddLiveIns(LiveRegs, *SevenMBB0); -+ computeAndAddLiveIns(LiveRegs, *SevenMBB1); -+ computeAndAddLiveIns(LiveRegs, *SevenMBB2); -+ computeAndAddLiveIns(LiveRegs, *SevenMBB3); -+ computeAndAddLiveIns(LiveRegs, *ZeroMBB); -+ computeAndAddLiveIns(LiveRegs, *ZeroMBB0); -+ computeAndAddLiveIns(LiveRegs, *ZeroMBB1); -+ computeAndAddLiveIns(LiveRegs, *ZeroMBB2); -+ computeAndAddLiveIns(LiveRegs, *ZeroMBB3); -+ computeAndAddLiveIns(LiveRegs, *OneMBB); -+ computeAndAddLiveIns(LiveRegs, *OneMBB0); -+ computeAndAddLiveIns(LiveRegs, *OneMBB1); -+ computeAndAddLiveIns(LiveRegs, *OneMBB2); -+ computeAndAddLiveIns(LiveRegs, *OneMBB3); -+ computeAndAddLiveIns(LiveRegs, *TwoMBB); -+ computeAndAddLiveIns(LiveRegs, *TwoMBB0); -+ computeAndAddLiveIns(LiveRegs, *TwoMBB1); -+ computeAndAddLiveIns(LiveRegs, *TwoMBB2); -+ computeAndAddLiveIns(LiveRegs, *TwoMBB3); -+ computeAndAddLiveIns(LiveRegs, *ThreeMBB); -+ computeAndAddLiveIns(LiveRegs, *ThreeMBB0); -+ computeAndAddLiveIns(LiveRegs, *ThreeMBB1); -+ computeAndAddLiveIns(LiveRegs, *ThreeMBB2); -+ computeAndAddLiveIns(LiveRegs, *ThreeMBB3); -+ computeAndAddLiveIns(LiveRegs, *FourMBB); -+ computeAndAddLiveIns(LiveRegs, *FourMBB0); -+ computeAndAddLiveIns(LiveRegs, *FourMBB1); -+ computeAndAddLiveIns(LiveRegs, *FourMBB2); -+ computeAndAddLiveIns(LiveRegs, *FourMBB3); -+ computeAndAddLiveIns(LiveRegs, *FiveMBB); -+ computeAndAddLiveIns(LiveRegs, *FiveMBB0); -+ computeAndAddLiveIns(LiveRegs, *FiveMBB1); -+ computeAndAddLiveIns(LiveRegs, *FiveMBB2); -+ computeAndAddLiveIns(LiveRegs, *FiveMBB3); -+ computeAndAddLiveIns(LiveRegs, *SixMBB); -+ computeAndAddLiveIns(LiveRegs, *SixMBB0); -+ computeAndAddLiveIns(LiveRegs, *SixMBB1); -+ computeAndAddLiveIns(LiveRegs, *SixMBB2); -+ computeAndAddLiveIns(LiveRegs, *SixMBB3); -+ computeAndAddLiveIns(LiveRegs, *sinkMBB); -+ computeAndAddLiveIns(LiveRegs, *exitMBB); -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandAtomicBinOpSubword( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ unsigned LL, SC; -+ unsigned BEQ = LoongArch::BEQ32; -+ unsigned SEOp = LoongArch::EXT_W_H32; -+ -+ LL = LoongArch::LL_W; -+ SC = LoongArch::SC_W; -+ -+ bool IsSwap = false; -+ bool IsNand = false; -+ bool IsMAX = false; -+ bool IsMIN = false; -+ bool IsUnsigned = false; -+ -+ unsigned Opcode = 0; -+ switch (I->getOpcode()) { -+ case LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA: -+ IsNand = true; -+ break; -+ case LoongArch::ATOMIC_SWAP_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_SWAP_I16_POSTRA: -+ IsSwap = true; -+ break; -+ case LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA: -+ Opcode = LoongArch::ADD_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_W; -+ IsMAX = true; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_W; -+ IsMIN = true; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_WU; -+ IsMAX = true; -+ IsUnsigned = true; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_WU; -+ IsMIN = true; -+ IsUnsigned = true; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA: -+ Opcode = LoongArch::SUB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_AND_I16_POSTRA: -+ Opcode = LoongArch::AND32; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_OR_I16_POSTRA: -+ Opcode = LoongArch::OR32; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA: -+ SEOp = LoongArch::EXT_W_B32; -+ LLVM_FALLTHROUGH; -+ case LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA: -+ Opcode = LoongArch::XOR32; -+ break; -+ default: -+ llvm_unreachable("Unknown subword atomic pseudo for expansion!"); -+ } -+ -+ unsigned Dest = I->getOperand(0).getReg(); -+ unsigned Ptr = I->getOperand(1).getReg(); -+ unsigned Incr = I->getOperand(2).getReg(); -+ unsigned Mask = I->getOperand(3).getReg(); -+ unsigned Mask2 = I->getOperand(4).getReg(); -+ unsigned ShiftAmnt = I->getOperand(5).getReg(); -+ unsigned OldVal = I->getOperand(6).getReg(); -+ unsigned BinOpRes = I->getOperand(7).getReg(); -+ unsigned StoreVal = I->getOperand(8).getReg(); -+ -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB.getIterator(); -+ MF->insert(It, loopMBB); -+ MF->insert(It, sinkMBB); -+ MF->insert(It, exitMBB); -+ -+ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ BB.addSuccessor(loopMBB, BranchProbability::getOne()); -+ loopMBB->addSuccessor(sinkMBB); -+ loopMBB->addSuccessor(loopMBB); -+ loopMBB->normalizeSuccProbs(); -+ -+ BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); -+ if (IsNand) { -+ // and andres, oldval, incr2 -+ // nor binopres, $0, andres -+ // and newval, binopres, mask -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) -+ .addReg(OldVal) -+ .addReg(Incr); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::NOR32), BinOpRes) -+ .addReg(LoongArch::ZERO) -+ .addReg(BinOpRes); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) -+ .addReg(BinOpRes) -+ .addReg(Mask); -+ } else if (IsMAX || IsMIN) { -+ -+ unsigned SLTScratch4 = IsUnsigned ? LoongArch::SLTU32 : LoongArch::SLT32; -+ unsigned CMPIncr = IsMAX ? LoongArch::MASKEQZ32 : LoongArch::MASKNEZ32; -+ unsigned CMPOldVal = IsMAX ? LoongArch::MASKNEZ32 : LoongArch::MASKEQZ32; -+ -+ unsigned Scratch4 = I->getOperand(9).getReg(); -+ unsigned Scratch5 = I->getOperand(10).getReg(); -+ -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), Scratch5) -+ .addReg(OldVal) -+ .addReg(Mask); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), Incr) -+ .addReg(Incr) -+ .addReg(Mask); -+ BuildMI(loopMBB, DL, TII->get(SLTScratch4), Scratch4) -+ .addReg(Scratch5) -+ .addReg(Incr); -+ BuildMI(loopMBB, DL, TII->get(CMPOldVal), BinOpRes) -+ .addReg(Scratch5) -+ .addReg(Scratch4); -+ BuildMI(loopMBB, DL, TII->get(CMPIncr), Scratch4) -+ .addReg(Incr) -+ .addReg(Scratch4); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::OR32), BinOpRes) -+ .addReg(BinOpRes) -+ .addReg(Scratch4); -+ -+ } else if (!IsSwap) { -+ // binopres, oldval, incr2 -+ // and newval, binopres, mask -+ BuildMI(loopMBB, DL, TII->get(Opcode), BinOpRes) -+ .addReg(OldVal) -+ .addReg(Incr); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) -+ .addReg(BinOpRes) -+ .addReg(Mask); -+ } else { // atomic.swap -+ // and newval, incr2, mask -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) -+ .addReg(Incr) -+ .addReg(Mask); -+ } -+ -+ // and StoreVal, OlddVal, Mask2 -+ // or StoreVal, StoreVal, BinOpRes -+ // StoreVal = sc StoreVal, 0(Ptr) -+ // beq StoreVal, zero, loopMBB -+ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), StoreVal) -+ .addReg(OldVal) -+ .addReg(Mask2); -+ BuildMI(loopMBB, DL, TII->get(LoongArch::OR32), StoreVal) -+ .addReg(StoreVal) -+ .addReg(BinOpRes); -+ BuildMI(loopMBB, DL, TII->get(SC), StoreVal) -+ .addReg(StoreVal) -+ .addReg(Ptr) -+ .addImm(0); -+ BuildMI(loopMBB, DL, TII->get(BEQ)) -+ .addReg(StoreVal) -+ .addReg(LoongArch::ZERO) -+ .addMBB(loopMBB); -+ -+ // sinkMBB: -+ // and maskedoldval1,oldval,mask -+ // srl srlres,maskedoldval1,shiftamt -+ // sign_extend dest,srlres -+ -+ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::AND32), Dest) -+ .addReg(OldVal) -+ .addReg(Mask); -+ BuildMI(sinkMBB, DL, TII->get(LoongArch::SRL_W), Dest) -+ .addReg(Dest) -+ .addReg(ShiftAmnt); -+ -+ BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); -+ -+ LivePhysRegs LiveRegs; -+ computeAndAddLiveIns(LiveRegs, *loopMBB); -+ computeAndAddLiveIns(LiveRegs, *sinkMBB); -+ computeAndAddLiveIns(LiveRegs, *exitMBB); -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI, -+ unsigned Size) { -+ MachineFunction *MF = BB.getParent(); -+ -+ DebugLoc DL = I->getDebugLoc(); -+ -+ unsigned LL, SC, ZERO, BEQ, SUB; -+ if (Size == 4) { -+ LL = LoongArch::LL_W; -+ SC = LoongArch::SC_W; -+ BEQ = LoongArch::BEQ32; -+ ZERO = LoongArch::ZERO; -+ SUB = LoongArch::SUB_W; -+ } else { -+ LL = LoongArch::LL_D; -+ SC = LoongArch::SC_D; -+ ZERO = LoongArch::ZERO_64; -+ BEQ = LoongArch::BEQ; -+ SUB = LoongArch::SUB_D; -+ } -+ -+ unsigned OldVal = I->getOperand(0).getReg(); -+ unsigned Ptr = I->getOperand(1).getReg(); -+ unsigned Incr = I->getOperand(2).getReg(); -+ unsigned Scratch = I->getOperand(3).getReg(); -+ -+ unsigned Opcode = 0; -+ unsigned OR = 0; -+ unsigned AND = 0; -+ unsigned NOR = 0; -+ bool IsNand = false; -+ bool IsSub = false; -+ switch (I->getOpcode()) { -+ case LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA: -+ Opcode = LoongArch::AMADD_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA: -+ IsSub = true; -+ Opcode = LoongArch::AMADD_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I32_POSTRA: -+ Opcode = LoongArch::AMAND_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I32_POSTRA: -+ Opcode = LoongArch::AMOR_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA: -+ Opcode = LoongArch::AMXOR_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA: -+ IsNand = true; -+ AND = LoongArch::AND32; -+ NOR = LoongArch::NOR32; -+ break; -+ case LoongArch::ATOMIC_SWAP_I32_POSTRA: -+ OR = LoongArch::AMSWAP_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_W; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_WU; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_WU; -+ break; -+ case LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA: -+ Opcode = LoongArch::AMADD_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA: -+ IsSub = true; -+ Opcode = LoongArch::AMADD_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I64_POSTRA: -+ Opcode = LoongArch::AMAND_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I64_POSTRA: -+ Opcode = LoongArch::AMOR_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA: -+ Opcode = LoongArch::AMXOR_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA: -+ IsNand = true; -+ AND = LoongArch::AND; -+ NOR = LoongArch::NOR; -+ break; -+ case LoongArch::ATOMIC_SWAP_I64_POSTRA: -+ OR = LoongArch::AMSWAP_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_D; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA: -+ Opcode = LoongArch::AMMAX_DB_DU; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA: -+ Opcode = LoongArch::AMMIN_DB_DU; -+ break; -+ default: -+ llvm_unreachable("Unknown pseudo atomic!"); -+ } -+ -+ const BasicBlock *LLVM_BB = BB.getBasicBlock(); -+ MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB.getIterator(); -+ MF->insert(It, loopMBB); -+ MF->insert(It, exitMBB); -+ -+ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); -+ -+ BB.addSuccessor(loopMBB, BranchProbability::getOne()); -+ loopMBB->addSuccessor(exitMBB); -+ loopMBB->addSuccessor(loopMBB); -+ loopMBB->normalizeSuccProbs(); -+ -+ assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); -+ assert((OldVal != Incr) && "Clobbered the wrong reg!"); -+ if (Opcode) { -+ if(IsSub){ -+ BuildMI(loopMBB, DL, TII->get(SUB), Scratch).addReg(ZERO).addReg(Incr); -+ BuildMI(loopMBB, DL, TII->get(Opcode), OldVal).addReg(Scratch).addReg(Ptr).addImm(0); -+ } -+ else{ -+ BuildMI(loopMBB, DL, TII->get(Opcode), OldVal).addReg(Incr).addReg(Ptr).addImm(0); -+ } -+ } else if (IsNand) { -+ assert(AND && NOR && -+ "Unknown nand instruction for atomic pseudo expansion"); -+ BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); -+ BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr); -+ BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch); -+ BuildMI(loopMBB, DL, TII->get(SC), Scratch).addReg(Scratch).addReg(Ptr).addImm(0); -+ BuildMI(loopMBB, DL, TII->get(BEQ)).addReg(Scratch).addReg(ZERO).addMBB(loopMBB); -+ } else { -+ assert(OR && "Unknown instruction for atomic pseudo expansion!"); -+ BuildMI(loopMBB, DL, TII->get(OR), OldVal).addReg(Incr).addReg(Ptr).addImm(0); -+ } -+ -+ -+ NMBBI = BB.end(); -+ I->eraseFromParent(); -+ -+ LivePhysRegs LiveRegs; -+ computeAndAddLiveIns(LiveRegs, *loopMBB); -+ computeAndAddLiveIns(LiveRegs, *exitMBB); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ MachineFunction *MF = BB.getParent(); -+ MachineInstr &MI = *I; -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned Op = MI.getOpcode(); -+ unsigned DestReg = MI.getOperand(0).getReg(); -+ unsigned TmpReg; -+ const MachineOperand &MO = MI.getOperand(1); -+ Reloc::Model RM = MF->getTarget().getRelocationModel(); -+ -+ MachineInstrBuilder MIB1, MIB2, MIB3, MIB4, MIB5; -+ unsigned HiFlag, LoFlag, HigherFlag, HighestFlag; -+ unsigned HiOp, LoOp, HigherOp, HighestOp, LastOp; -+ bool UseGot = false; -+ -+ HiOp = LoongArch::PCADDU12I_ri; -+ LoOp = LoongArch::ORI_rri; -+ HigherOp = LoongArch::LU32I_D_ri; -+ HighestOp = LoongArch::LU52I_D_rri; -+ -+ switch (Op) { -+ case LoongArch::LoadAddrLocal: -+ if (RM == Reloc::Static) { // for jit -+ HiFlag = LoongArchII::MO_ABS_HI; -+ LoFlag = LoongArchII::MO_ABS_LO; -+ HigherFlag = LoongArchII::MO_ABS_HIGHER; -+ HighestFlag = LoongArchII::MO_ABS_HIGHEST; -+ // lu12i.w + ori + lu32i.d + lu52i.d -+ HiOp = LoongArch::LU12I_W; -+ LoOp = LoongArch::ORI; -+ HigherOp = LoongArch::LU32I_D; -+ HighestOp = LoongArch::LU52I_D; -+ } else { -+ // pcaddu12i + addi.d -+ LoFlag = LoongArchII::MO_PCREL_LO; -+ HiFlag = LoongArchII::MO_PCREL_HI; -+ LoOp = LoongArch::ADDI_D_rri; -+ } -+ break; -+ case LoongArch::LoadAddrLocalRR: -+ // pcaddu12i + ori + lu32i.d + lu52i.d + add.d -+ LoFlag = LoongArchII::MO_PCREL_RRLO; -+ HiFlag = LoongArchII::MO_PCREL_RRHI; -+ HigherFlag = LoongArchII::MO_PCREL_RRHIGHER; -+ HighestFlag = LoongArchII::MO_PCREL_RRHIGHEST; -+ LastOp = LoongArch::ADD_D_rrr; -+ break; -+ case LoongArch::LoadAddrGlobal: -+ case LoongArch::LoadAddrGlobal_Alias: -+ // pcaddu12i + ld.d -+ LoFlag = LoongArchII::MO_GOT_LO; -+ HiFlag = LoongArchII::MO_GOT_HI; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::LD_D_rrii; -+ UseGot = true; -+ break; -+ case LoongArch::LoadAddrGlobalRR: -+ // pcaddu12i + ori + lu32i.d + lu52i.d +ldx.d -+ LoFlag = LoongArchII::MO_GOT_RRLO; -+ HiFlag = LoongArchII::MO_GOT_RRHI; -+ HigherFlag = LoongArchII::MO_GOT_RRHIGHER; -+ HighestFlag = LoongArchII::MO_GOT_RRHIGHEST; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::ORI_rrii; -+ HigherOp = LoongArch::LU32I_D_rii; -+ HighestOp = LoongArch::LU52I_D_rrii; -+ LastOp = LoongArch::LDX_D_rrr; -+ UseGot = true; -+ break; -+ case LoongArch::LoadAddrTLS_LE: -+ // lu12i.w + ori + lu32i.d + lu52i.d -+ LoFlag = LoongArchII::MO_TLSLE_LO; -+ HiFlag = LoongArchII::MO_TLSLE_HI; -+ HigherFlag = LoongArchII::MO_TLSLE_HIGHER; -+ HighestFlag = LoongArchII::MO_TLSLE_HIGHEST; -+ HiOp = LoongArch::LU12I_W_ri; -+ break; -+ case LoongArch::LoadAddrTLS_IE: -+ // pcaddu12i + ld.d -+ LoFlag = LoongArchII::MO_TLSIE_LO; -+ HiFlag = LoongArchII::MO_TLSIE_HI; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::LD_D_rrii; -+ UseGot = true; -+ break; -+ case LoongArch::LoadAddrTLS_IE_RR: -+ // pcaddu12i + ori + lu32i.d + lu52i.d +ldx.d -+ LoFlag = LoongArchII::MO_TLSIE_RRLO; -+ HiFlag = LoongArchII::MO_TLSIE_RRHI; -+ HigherFlag = LoongArchII::MO_TLSIE_RRHIGHER; -+ HighestFlag = LoongArchII::MO_TLSIE_RRHIGHEST; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::ORI_rrii; -+ HigherOp = LoongArch::LU32I_D_rii; -+ HighestOp = LoongArch::LU52I_D_rrii; -+ LastOp = LoongArch::LDX_D_rrr; -+ UseGot = true; -+ break; -+ case LoongArch::LoadAddrTLS_LD: -+ case LoongArch::LoadAddrTLS_GD: -+ // pcaddu12i + addi.d -+ LoFlag = LoongArchII::MO_TLSGD_LO; -+ HiFlag = LoongArchII::MO_TLSGD_HI; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::ADDI_D_rrii; -+ UseGot = true; -+ break; -+ case LoongArch::LoadAddrTLS_LD_RR: -+ case LoongArch::LoadAddrTLS_GD_RR: -+ // pcaddu12i + ori + lu32i.d + lu52i.d + add.d -+ LoFlag = LoongArchII::MO_TLSGD_RRLO; -+ HiFlag = LoongArchII::MO_TLSGD_RRHI; -+ HigherFlag = LoongArchII::MO_TLSGD_RRHIGHER; -+ HighestFlag = LoongArchII::MO_TLSGD_RRHIGHEST; -+ HiOp = LoongArch::PCADDU12I_rii; -+ LoOp = LoongArch::ORI_rrii; -+ HigherOp = LoongArch::LU32I_D_rii; -+ HighestOp = LoongArch::LU52I_D_rrii; -+ LastOp = LoongArch::ADD_D_rrr; -+ UseGot = true; -+ break; -+ default: -+ break; -+ } -+ -+ MIB1 = BuildMI(BB, I, DL, TII->get(HiOp), DestReg); -+ -+ switch (Op) { -+ case LoongArch::LoadAddrLocal: -+ if (RM == Reloc::Static) { // for jit -+ // la.abs rd, symbol -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg).addReg(DestReg); -+ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), DestReg); -+ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), DestReg).addReg(DestReg); -+ if (MO.isJTI()) { -+ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); -+ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); -+ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); -+ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); -+ } else if (MO.isBlockAddress()) { -+ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); -+ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); -+ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); -+ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ MIB3.addDisp(MO, 0, HigherFlag); -+ MIB4.addDisp(MO, 0, HighestFlag); -+ } -+ break; -+ } -+ LLVM_FALLTHROUGH; -+ case LoongArch::LoadAddrGlobal: // la.global rd, symbol -+ case LoongArch::LoadAddrGlobal_Alias: // la rd, symbol -+ case LoongArch::LoadAddrTLS_IE: // la.tls.ie rd, symbol -+ case LoongArch::LoadAddrTLS_LD: // la.tls.ld rd, symbol -+ case LoongArch::LoadAddrTLS_GD: // la.tls.gd rd, symbol -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg) -+ .addReg(DestReg); -+ if (MO.isJTI()) { -+ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); -+ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); -+ } else if (MO.isBlockAddress()) { -+ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); -+ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ } -+ if (UseGot == true) { -+ MIB1.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ MIB2.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ } -+ break; -+ -+ case LoongArch::LoadAddrLocalRR: //la.local rd, rs, symbol -+ case LoongArch::LoadAddrGlobalRR: // la.global rd, rs, symbol -+ case LoongArch::LoadAddrTLS_IE_RR: // la.tls.ie rd, rs, symbol -+ case LoongArch::LoadAddrTLS_LD_RR: // la.tls.ld rd, rs, symbol -+ case LoongArch::LoadAddrTLS_GD_RR: // la.tls.gd rd, rs, symbol -+ TmpReg = MI.getOperand(MI.getNumOperands()-1).getReg(); -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), TmpReg) -+ .addReg(TmpReg); -+ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), TmpReg); -+ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), TmpReg) -+ .addReg(TmpReg); -+ MIB5 = BuildMI(BB, I, DL, TII->get(LastOp), DestReg) -+ .addReg(DestReg) -+ .addReg(TmpReg); -+ if (MO.isJTI()) { -+ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); -+ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); -+ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); -+ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); -+ } else if (MO.isBlockAddress()) { -+ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); -+ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); -+ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); -+ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ MIB3.addDisp(MO, 0, HigherFlag); -+ MIB4.addDisp(MO, 0, HighestFlag); -+ } -+ if (UseGot == true) { -+ MIB1.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ MIB2.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ MIB3.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ MIB4.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); -+ } -+ break; -+ case LoongArch::LoadAddrTLS_LE: // la.tls.le rd, symbol -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg) -+ .addReg(DestReg); -+ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), DestReg); -+ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), DestReg) -+ .addReg(DestReg); -+ if (MO.isJTI()) { -+ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); -+ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); -+ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); -+ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); -+ } else if (MO.isBlockAddress()) { -+ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); -+ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); -+ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); -+ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ MIB3.addDisp(MO, 0, HigherFlag); -+ MIB4.addDisp(MO, 0, HighestFlag); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ MI.eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandPseudoTailCall( -+ MachineBasicBlock &BB, MachineBasicBlock::iterator I) { -+ -+ MachineInstr &MI = *I; -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ const MachineOperand &MO = MI.getOperand(0); -+ -+ unsigned NoFlag = LoongArchII::MO_NO_FLAG; -+ -+ MachineInstrBuilder MIB = -+ BuildMI(BB, I, DL, TII->get(LoongArch::PseudoTailReturn)); -+ -+ if (MO.isSymbol()) { -+ MIB.addExternalSymbol(MO.getSymbolName(), NoFlag); -+ } else { -+ MIB.addDisp(MO, 0, NoFlag); -+ } -+ -+ MI.eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandPseudoCall(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ MachineFunction *MF = BB.getParent(); -+ MachineInstr &MI = *I; -+ DebugLoc DL = MI.getDebugLoc(); -+ CodeModel::Model M = MF->getTarget().getCodeModel(); -+ Reloc::Model RM = MF->getTarget().getRelocationModel(); -+ -+ unsigned Ra = LoongArch::RA_64; -+ const MachineOperand &MO = MI.getOperand(0); -+ unsigned HiFlag, LoFlag, HigherFlag, HighestFlag, NoFlag; -+ -+ HiFlag = LoongArchII::MO_CALL_HI; -+ LoFlag = LoongArchII::MO_CALL_LO; -+ NoFlag = LoongArchII::MO_NO_FLAG; -+ -+ if (RM == Reloc::Static) { // for jit -+ MachineInstrBuilder MIB1, MIB2, MIB3, MIB4, MIB5; -+ -+ HiFlag = LoongArchII::MO_ABS_HI; -+ LoFlag = LoongArchII::MO_ABS_LO; -+ HigherFlag = LoongArchII::MO_ABS_HIGHER; -+ HighestFlag = LoongArchII::MO_ABS_HIGHEST; -+ // lu12i.w + ori + lu32i.d + lu52i.d + jirl -+ -+ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::LU12I_W), Ra); -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::ORI), Ra) -+ .addReg(Ra); -+ MIB3 = BuildMI(BB, I, DL, TII->get(LoongArch::LU32I_D), Ra); -+ MIB4 = BuildMI(BB, I, DL, TII->get(LoongArch::LU52I_D), Ra) -+ .addReg(Ra); -+ MIB5 = -+ BuildMI(BB, I, DL, TII->get(LoongArch::JIRL), Ra).addReg(Ra).addImm(0); -+ if (MO.isSymbol()) { -+ MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); -+ MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); -+ MIB3.addExternalSymbol(MO.getSymbolName(), HigherFlag); -+ MIB4.addExternalSymbol(MO.getSymbolName(), HighestFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ MIB3.addDisp(MO, 0, HigherFlag); -+ MIB4.addDisp(MO, 0, HighestFlag); -+ } -+ } else if (M == CodeModel::Large) { -+ // pcaddu18i + jirl -+ MachineInstrBuilder MIB1; -+ MachineInstrBuilder MIB2; -+ -+ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::PCADDU18I), Ra); -+ MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::JIRL_CALL), Ra).addReg(Ra); -+ if (MO.isSymbol()) { -+ MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); -+ MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); -+ } else { -+ MIB1.addDisp(MO, 0, HiFlag); -+ MIB2.addDisp(MO, 0, LoFlag); -+ } -+ } else { -+ // bl -+ MachineInstrBuilder MIB1; -+ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::BL)); -+ if (MO.isSymbol()) { -+ MIB1.addExternalSymbol(MO.getSymbolName(), NoFlag); -+ } else { -+ MIB1.addDisp(MO, 0, NoFlag); -+ } -+ } -+ -+ MI.eraseFromParent(); -+ -+ return true; -+} -+ -+bool LoongArchExpandPseudo::expandPseudoTEQ(MachineBasicBlock &BB, -+ MachineBasicBlock::iterator I, -+ MachineBasicBlock::iterator &NMBBI) { -+ MachineInstr &MI = *I; -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned Divisor = MI.getOperand(0).getReg(); -+ unsigned BneOp = LoongArch::BNE; -+ unsigned Zero = LoongArch::ZERO_64; -+ -+ // beq $Divisor, $zero, 8 -+ BuildMI(BB, I, DL, TII->get(BneOp), Divisor) -+ .addReg(Zero) -+ .addImm(8); -+ // break 7 -+ BuildMI(BB, I, DL, TII->get(LoongArch::BREAK)) -+ .addImm(7);; -+ -+ MI.eraseFromParent(); -+ -+ return true; -+} -+bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MBBI, -+ MachineBasicBlock::iterator &NMBB) { -+ -+ bool Modified = false; -+ -+ switch (MBBI->getOpcode()) { -+ case LoongArch::PseudoTEQ: -+ return expandPseudoTEQ(MBB, MBBI, NMBB); -+ case LoongArch::PseudoCall: -+ return expandPseudoCall(MBB, MBBI, NMBB); -+ case LoongArch::PseudoTailCall: -+ return expandPseudoTailCall(MBB, MBBI); -+ case LoongArch::LoadAddrLocal: -+ case LoongArch::LoadAddrLocalRR: -+ case LoongArch::LoadAddrGlobal: -+ case LoongArch::LoadAddrGlobalRR: -+ case LoongArch::LoadAddrGlobal_Alias: -+ case LoongArch::LoadAddrTLS_LD: -+ case LoongArch::LoadAddrTLS_LD_RR: -+ case LoongArch::LoadAddrTLS_GD: -+ case LoongArch::LoadAddrTLS_GD_RR: -+ case LoongArch::LoadAddrTLS_IE: -+ case LoongArch::LoadAddrTLS_IE_RR: -+ case LoongArch::LoadAddrTLS_LE: -+ return expandLoadAddr(MBB, MBBI, NMBB); -+ case LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA: -+ case LoongArch::ATOMIC_CMP_SWAP_I64_POSTRA: -+ return expandAtomicCmpSwap(MBB, MBBI, NMBB); -+ case LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA: -+ case LoongArch::ATOMIC_CMP_SWAP_I16_POSTRA: -+ return expandAtomicCmpSwapSubword(MBB, MBBI, NMBB); -+ case LoongArch::ATOMIC_SWAP_I8_POSTRA: -+ case LoongArch::ATOMIC_SWAP_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_AND_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_AND_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_OR_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_OR_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA: -+ return expandAtomicBinOpSubword(MBB, MBBI, NMBB); -+ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: -+ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: -+ return expandXINSERT_BOp(MBB, MBBI, NMBB); -+ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: -+ return expandINSERT_HOp(MBB, MBBI, NMBB); -+ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: -+ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: -+ return expandXINSERT_FWOp(MBB, MBBI, NMBB); -+ case LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_AND_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_OR_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA: -+ case LoongArch::ATOMIC_SWAP_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA: -+ return expandAtomicBinOp(MBB, MBBI, NMBB, 4); -+ case LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_AND_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_OR_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA: -+ case LoongArch::ATOMIC_SWAP_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA: -+ case LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA: -+ return expandAtomicBinOp(MBB, MBBI, NMBB, 8); -+ default: -+ return Modified; -+ } -+} -+ -+bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) { -+ bool Modified = false; -+ -+ MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); -+ while (MBBI != E) { -+ MachineBasicBlock::iterator NMBBI = std::next(MBBI); -+ Modified |= expandMI(MBB, MBBI, NMBBI); -+ MBBI = NMBBI; -+ } -+ -+ return Modified; -+} -+ -+bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) { -+ STI = &static_cast(MF.getSubtarget()); -+ TII = STI->getInstrInfo(); -+ -+ bool Modified = false; -+ for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; -+ ++MFI) -+ Modified |= expandMBB(*MFI); -+ -+ if (Modified) -+ MF.RenumberBlocks(); -+ -+ return Modified; -+} -+ -+/// createLoongArchExpandPseudoPass - returns an instance of the pseudo instruction -+/// expansion pass. -+FunctionPass *llvm::createLoongArchExpandPseudoPass() { -+ return new LoongArchExpandPseudo(); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td -deleted file mode 100644 -index 20448492a..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td -+++ /dev/null -@@ -1,229 +0,0 @@ --//=-- LoongArchInstrInfoF.td - Single-Precision Float instr --*- tablegen -*-=// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// --// --// This file describes the baisc single-precision floating-point instructions. --// --//===----------------------------------------------------------------------===// -- --//===----------------------------------------------------------------------===// --// LoongArch specific DAG Nodes. --//===----------------------------------------------------------------------===// -- --def SDT_LoongArchMOVGR2FR_W_LA64 -- : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>; --def SDT_LoongArchMOVFR2GR_S_LA64 -- : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>; --def SDT_LoongArchFTINT : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>; -- --def loongarch_movgr2fr_w_la64 -- : SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>; --def loongarch_movfr2gr_s_la64 -- : SDNode<"LoongArchISD::MOVFR2GR_S_LA64", SDT_LoongArchMOVFR2GR_S_LA64>; --def loongarch_ftint : SDNode<"LoongArchISD::FTINT", SDT_LoongArchFTINT>; -- --//===----------------------------------------------------------------------===// --// Instructions --//===----------------------------------------------------------------------===// -- --let Predicates = [HasBasicF] in { -- --// Arithmetic Operation Instructions --def FADD_S : FP_ALU_3R<0b00000001000000001, "fadd.s", FPR32>; --def FSUB_S : FP_ALU_3R<0b00000001000000101, "fsub.s", FPR32>; --def FMUL_S : FP_ALU_3R<0b00000001000001001, "fmul.s", FPR32>; --def FDIV_S : FP_ALU_3R<0b00000001000001101, "fdiv.s", FPR32>; --def FMADD_S : FP_ALU_4R<0b000010000001, "fmadd.s", FPR32>; --def FMSUB_S : FP_ALU_4R<0b000010000101, "fmsub.s", FPR32>; --def FNMADD_S : FP_ALU_4R<0b000010001001, "fnmadd.s", FPR32>; --def FNMSUB_S : FP_ALU_4R<0b000010001101, "fnmsub.s", FPR32>; --def FMAX_S : FP_ALU_3R<0b00000001000010001, "fmax.s", FPR32>; --def FMIN_S : FP_ALU_3R<0b00000001000010101, "fmin.s", FPR32>; --def FMAXA_S : FP_ALU_3R<0b00000001000011001, "fmaxa.s", FPR32>; --def FMINA_S : FP_ALU_3R<0b00000001000011101, "fmina.s", FPR32>; --def FABS_S : FP_ALU_2R<0b0000000100010100000001, "fabs.s", FPR32>; --def FNEG_S : FP_ALU_2R<0b0000000100010100000101, "fneg.s", FPR32>; --def FSQRT_S : FP_ALU_2R<0b0000000100010100010001, "fsqrt.s", FPR32>; --def FRECIP_S : FP_ALU_2R<0b0000000100010100010101, "frecip.s", FPR32>; --def FRSQRT_S : FP_ALU_2R<0b0000000100010100011001, "frsqrt.s", FPR32>; --def FSCALEB_S : FP_ALU_3R<0b00000001000100001, "fscaleb.s", FPR32>; --def FLOGB_S : FP_ALU_2R<0b0000000100010100001001, "flogb.s", FPR32>; --def FCOPYSIGN_S : FP_ALU_3R<0b00000001000100101, "fcopysign.s", FPR32>; --def FCLASS_S : FP_ALU_2R<0b0000000100010100001101, "fclass.s", FPR32>; -- -- --// Comparison Instructions --def FCMP_CAF_S : FP_CMP; --def FCMP_CUN_S : FP_CMP; --def FCMP_CEQ_S : FP_CMP; --def FCMP_CUEQ_S : FP_CMP; --def FCMP_CLT_S : FP_CMP; --def FCMP_CULT_S : FP_CMP; --def FCMP_CLE_S : FP_CMP; --def FCMP_CULE_S : FP_CMP; --def FCMP_CNE_S : FP_CMP; --def FCMP_COR_S : FP_CMP; --def FCMP_CUNE_S : FP_CMP; --def FCMP_SAF_S : FP_CMP; --def FCMP_SUN_S : FP_CMP; --def FCMP_SEQ_S : FP_CMP; --def FCMP_SUEQ_S : FP_CMP; --def FCMP_SLT_S : FP_CMP; --def FCMP_SULT_S : FP_CMP; --def FCMP_SLE_S : FP_CMP; --def FCMP_SULE_S : FP_CMP; --def FCMP_SNE_S : FP_CMP; --def FCMP_SOR_S : FP_CMP; --def FCMP_SUNE_S : FP_CMP; -- --// Conversion Instructions --def FFINT_S_W : FP_CONV<0b0000000100011101000100, "ffint.s.w", FPR32, FPR32>; --def FTINT_W_S : FP_CONV<0b0000000100011011000001, "ftint.w.s", FPR32, FPR32>; --def FTINTRM_W_S : FP_CONV<0b0000000100011010000001, "ftintrm.w.s", FPR32, -- FPR32>; --def FTINTRP_W_S : FP_CONV<0b0000000100011010010001, "ftintrp.w.s", FPR32, -- FPR32>; --def FTINTRZ_W_S : FP_CONV<0b0000000100011010100001, "ftintrz.w.s", FPR32, -- FPR32>; --def FTINTRNE_W_S : FP_CONV<0b0000000100011010110001, "ftintrne.w.s", FPR32, -- FPR32>; --def FRINT_S : FP_CONV<0b0000000100011110010001, "frint.s", FPR32, FPR32>; -- --// Move Instructions --def FSEL_S : FP_SEL<0b00001101000000, "fsel", FPR32>; --def FMOV_S : FP_MOV<0b0000000100010100100101, "fmov.s", FPR32, FPR32>; --def MOVGR2FR_W : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR32, GPR>; --def MOVFR2GR_S : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR32>; --def MOVGR2FCSR : FP_MOV<0b0000000100010100110000, "movgr2fcsr", FCSR, GPR>; --def MOVFCSR2GR : FP_MOV<0b0000000100010100110010, "movfcsr2gr", GPR, FCSR>; --def MOVFR2CF_S : FP_MOV<0b0000000100010100110100, "movfr2cf", CFR, FPR32>; --def MOVCF2FR_S : FP_MOV<0b0000000100010100110101, "movcf2fr", FPR32, CFR>; --def MOVGR2CF : FP_MOV<0b0000000100010100110110, "movgr2cf", CFR, GPR>; --def MOVCF2GR : FP_MOV<0b0000000100010100110111, "movcf2gr", GPR, CFR>; -- --// Branch Instructions --def BCEQZ : FP_BRANCH<0b01001000, "bceqz">; --def BCNEZ : FP_BRANCH<0b01001001, "bcnez">; -- --// Common Memory Access Instructions --def FLD_S : FP_LOAD_2RI12<0b0010101100, "fld.s", FPR32>; --def FST_S : FP_STORE_2RI12<0b0010101101, "fst.s", FPR32>; --def FLDX_S : FP_LOAD_3R<0b00111000001100000, "fldx.s", FPR32>; --def FSTX_S : FP_STORE_3R<0b00111000001110000, "fstx.s", FPR32>; -- --// Bound Check Memory Access Instructions --def FLDGT_S : FP_LOAD_3R<0b00111000011101000, "fldgt.s", FPR32>; --def FLDLE_S : FP_LOAD_3R<0b00111000011101010, "fldle.s", FPR32>; --def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>; --def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>; -- --} // Predicates = [HasBasicF] -- --//===----------------------------------------------------------------------===// --// Pseudo-instructions and codegen patterns --//===----------------------------------------------------------------------===// -- --/// Generic pattern classes -- --class PatFpr -- : Pat<(OpNode RegTy:$fj), (Inst $fj)>; --class PatFprFpr -- : Pat<(OpNode RegTy:$fj, RegTy:$fk), (Inst $fj, $fk)>; -- --let Predicates = [HasBasicF] in { -- --/// Float arithmetic operations -- --def : PatFprFpr; --def : PatFprFpr; --def : PatFprFpr; --def : PatFprFpr; --def : PatFpr; -- --/// Setcc -- --// Match non-signaling comparison -- --// TODO: change setcc to any_fsetcc after call is supported because --// we need to call llvm.experimental.constrained.fcmp.f32 in testcase. --// See RISCV float-fcmp-strict.ll for reference. --class PatFPSetcc -- : Pat<(setcc RegTy:$fj, RegTy:$fk, cc), -- (MOVCF2GR (CmpInst RegTy:$fj, RegTy:$fk))>; --// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE. --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; -- --// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_S instructions. -- --/// Select -- --def : Pat<(select GPR:$cc, FPR32:$fk, FPR32:$fj), -- (FSEL_S FPR32:$fj, FPR32:$fk, (MOVGR2CF GPR:$cc))>; -- --/// Selectcc -- --class PatFPSelectcc -- : Pat<(select (GRLenVT (setcc RegTy:$a, RegTy:$b, cc)), RegTy:$t, RegTy:$f), -- (SelInst RegTy:$f, RegTy:$t, (CmpInst RegTy:$a, RegTy:$b))>; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; -- --/// Loads -- --defm : LdPat; -- --/// Stores -- --defm : StPat; -- --/// Floating point constants -- --def : Pat<(f32 fpimm0), (MOVGR2FR_W R0)>; --def : Pat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W R0))>; --def : Pat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1)))>; -- --// FP Conversion --def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>; --} // Predicates = [HasBasicF] -- --let Predicates = [HasBasicF, IsLA64] in { --// GPR -> FPR --def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>; --// FPR -> GPR --def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src), -- (MOVFR2GR_S FPR32:$src)>; --// int -> f32 --def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>; --} // Predicates = [HasBasicF, IsLA64] -- --let Predicates = [HasBasicF, IsLA32] in { --// GPR -> FPR --def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>; --// FPR -> GPR --def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>; --// int -> f32 --def : Pat<(f32 (sint_to_fp (i32 GPR:$src))), (FFINT_S_W (MOVGR2FR_W GPR:$src))>; --} // Predicates = [HasBasicF, IsLA64] -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td -deleted file mode 100644 -index bb50cec9f..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td -+++ /dev/null -@@ -1,242 +0,0 @@ --//=-- LoongArchInstrInfoD.td - Double-Precision Float instr -*- tablegen -*-==// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// --// --// This file describes the basic double-precision floating-point instructions. --// --//===----------------------------------------------------------------------===// -- --//===----------------------------------------------------------------------===// --// Instructions --//===----------------------------------------------------------------------===// -- --let Predicates = [HasBasicD] in { -- --// Arithmetic Operation Instructions --def FADD_D : FP_ALU_3R<0b00000001000000010, "fadd.d", FPR64>; --def FSUB_D : FP_ALU_3R<0b00000001000000110, "fsub.d", FPR64>; --def FMUL_D : FP_ALU_3R<0b00000001000001010, "fmul.d", FPR64>; --def FDIV_D : FP_ALU_3R<0b00000001000001110, "fdiv.d", FPR64>; --def FMADD_D : FP_ALU_4R<0b000010000010, "fmadd.d", FPR64>; --def FMSUB_D : FP_ALU_4R<0b000010000110, "fmsub.d", FPR64>; --def FNMADD_D : FP_ALU_4R<0b000010001010, "fnmadd.d", FPR64>; --def FNMSUB_D : FP_ALU_4R<0b000010001110, "fnmsub.d", FPR64>; --def FMAX_D : FP_ALU_3R<0b00000001000010010, "fmax.d", FPR64>; --def FMIN_D : FP_ALU_3R<0b00000001000010110, "fmin.d", FPR64>; --def FMAXA_D : FP_ALU_3R<0b00000001000011010, "fmaxa.d", FPR64>; --def FMINA_D : FP_ALU_3R<0b00000001000011110, "fmina.d", FPR64>; --def FABS_D : FP_ALU_2R<0b0000000100010100000010, "fabs.d", FPR64>; --def FNEG_D : FP_ALU_2R<0b0000000100010100000110, "fneg.d", FPR64>; --def FSQRT_D : FP_ALU_2R<0b0000000100010100010010, "fsqrt.d", FPR64>; --def FRECIP_D : FP_ALU_2R<0b0000000100010100010110, "frecip.d", FPR64>; --def FRSQRT_D : FP_ALU_2R<0b0000000100010100011010, "frsqrt.d", FPR64>; --def FSCALEB_D : FP_ALU_3R<0b00000001000100010, "fscaleb.d", FPR64>; --def FLOGB_D : FP_ALU_2R<0b0000000100010100001010, "flogb.d", FPR64>; --def FCOPYSIGN_D : FP_ALU_3R<0b00000001000100110, "fcopysign.d", FPR64>; --def FCLASS_D : FP_ALU_2R<0b0000000100010100001110, "fclass.d", FPR64>; -- --// Comparison Instructions --def FCMP_CAF_D : FP_CMP; --def FCMP_CUN_D : FP_CMP; --def FCMP_CEQ_D : FP_CMP; --def FCMP_CUEQ_D : FP_CMP; --def FCMP_CLT_D : FP_CMP; --def FCMP_CULT_D : FP_CMP; --def FCMP_CLE_D : FP_CMP; --def FCMP_CULE_D : FP_CMP; --def FCMP_CNE_D : FP_CMP; --def FCMP_COR_D : FP_CMP; --def FCMP_CUNE_D : FP_CMP; --def FCMP_SAF_D : FP_CMP; --def FCMP_SUN_D : FP_CMP; --def FCMP_SEQ_D : FP_CMP; --def FCMP_SUEQ_D : FP_CMP; --def FCMP_SLT_D : FP_CMP; --def FCMP_SULT_D : FP_CMP; --def FCMP_SLE_D : FP_CMP; --def FCMP_SULE_D : FP_CMP; --def FCMP_SNE_D : FP_CMP; --def FCMP_SOR_D : FP_CMP; --def FCMP_SUNE_D : FP_CMP; -- --// Conversion Instructions --def FFINT_S_L : FP_CONV<0b0000000100011101000110, "ffint.s.l", FPR32, FPR64>; --def FTINT_L_S : FP_CONV<0b0000000100011011001001, "ftint.l.s", FPR64, FPR32>; --def FTINTRM_L_S : FP_CONV<0b0000000100011010001001, "ftintrm.l.s", FPR64, -- FPR32>; --def FTINTRP_L_S : FP_CONV<0b0000000100011010011001, "ftintrp.l.s", FPR64, -- FPR32>; --def FTINTRZ_L_S : FP_CONV<0b0000000100011010101001, "ftintrz.l.s", FPR64, -- FPR32>; --def FTINTRNE_L_S : FP_CONV<0b0000000100011010111001, "ftintrne.l.s", FPR64, -- FPR32>; --def FCVT_S_D : FP_CONV<0b0000000100011001000110, "fcvt.s.d", FPR32, FPR64>; --def FCVT_D_S : FP_CONV<0b0000000100011001001001, "fcvt.d.s", FPR64, FPR32>; --def FFINT_D_W : FP_CONV<0b0000000100011101001000, "ffint.d.w", FPR64, FPR32>; --def FFINT_D_L : FP_CONV<0b0000000100011101001010, "ffint.d.l", FPR64, FPR64>; --def FTINT_W_D : FP_CONV<0b0000000100011011000010, "ftint.w.d", FPR32, FPR64>; --def FTINT_L_D : FP_CONV<0b0000000100011011001010, "ftint.l.d", FPR64, FPR64>; --def FTINTRM_W_D : FP_CONV<0b0000000100011010000010, "ftintrm.w.d", FPR32, -- FPR64>; --def FTINTRM_L_D : FP_CONV<0b0000000100011010001010, "ftintrm.l.d", FPR64, -- FPR64>; --def FTINTRP_W_D : FP_CONV<0b0000000100011010010010, "ftintrp.w.d", FPR32, -- FPR64>; --def FTINTRP_L_D : FP_CONV<0b0000000100011010011010, "ftintrp.l.d", FPR64, -- FPR64>; --def FTINTRZ_W_D : FP_CONV<0b0000000100011010100010, "ftintrz.w.d", FPR32, -- FPR64>; --def FTINTRZ_L_D : FP_CONV<0b0000000100011010101010, "ftintrz.l.d", FPR64, -- FPR64>; --def FTINTRNE_W_D : FP_CONV<0b0000000100011010110010, "ftintrne.w.d", FPR32, -- FPR64>; --def FTINTRNE_L_D : FP_CONV<0b0000000100011010111010, "ftintrne.l.d", FPR64, -- FPR64>; --def FRINT_D : FP_CONV<0b0000000100011110010010, "frint.d", FPR64, FPR64>; -- --// Move Instructions --def FMOV_D : FP_MOV<0b0000000100010100100110, "fmov.d", FPR64, FPR64>; --def MOVFRH2GR_S : FP_MOV<0b0000000100010100101111, "movfrh2gr.s", GPR, FPR64>; --let isCodeGenOnly = 1 in { --def MOVFR2GR_S_64 : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR64>; --def FSEL_D : FP_SEL<0b00001101000000, "fsel", FPR64>; --} // isCodeGenOnly = 1 --let Constraints = "$dst = $out" in { --def MOVGR2FRH_W : FPFmtMOV<0b0000000100010100101011, (outs FPR64:$out), -- (ins FPR64:$dst, GPR:$src), "movgr2frh.w", -- "$dst, $src">; --} // Constraints = "$dst = $out" -- --// Common Memory Access Instructions --def FLD_D : FP_LOAD_2RI12<0b0010101110, "fld.d", FPR64>; --def FST_D : FP_STORE_2RI12<0b0010101111, "fst.d", FPR64>; --def FLDX_D : FP_LOAD_3R<0b00111000001101000, "fldx.d", FPR64>; --def FSTX_D : FP_STORE_3R<0b00111000001111000, "fstx.d", FPR64>; -- --// Bound Check Memory Access Instructions --def FLDGT_D : FP_LOAD_3R<0b00111000011101001, "fldgt.d", FPR64>; --def FLDLE_D : FP_LOAD_3R<0b00111000011101011, "fldle.d", FPR64>; --def FSTGT_D : FP_STORE_3R<0b00111000011101101, "fstgt.d", FPR64>; --def FSTLE_D : FP_STORE_3R<0b00111000011101111, "fstle.d", FPR64>; -- --} // Predicates = [HasBasicD] -- --// Instructions only available on LA64 --let Predicates = [HasBasicD, IsLA64] in { --def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>; --def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>; --} // Predicates = [HasBasicD, IsLA64] -- --// Instructions only available on LA32 --let Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 in { --def MOVGR2FR_W_64 : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR64, GPR>; --} // Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 -- --//===----------------------------------------------------------------------===// --// Pseudo-instructions and codegen patterns --//===----------------------------------------------------------------------===// -- --let Predicates = [HasBasicD] in { -- --/// Float arithmetic operations -- --def : PatFprFpr; --def : PatFprFpr; --def : PatFprFpr; --def : PatFprFpr; --def : PatFpr; -- --/// Setcc -- --// Match non-signaling comparison -- --// TODO: Change setcc to any_fsetcc after call is supported because --// we need to call llvm.experimental.constrained.fcmp.f64 in testcase. --// See RISCV float-fcmp-strict.ll for reference. -- --// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE. --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; --def : PatFPSetcc; -- --// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_D instructions. -- --/// Select -- --def : Pat<(select GPR:$cc, FPR64:$fk, FPR64:$fj), -- (FSEL_D FPR64:$fj, FPR64:$fk, (MOVGR2CF GPR:$cc))>; -- --/// Selectcc -- --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; --def : PatFPSelectcc; -- --/// Loads -- --defm : LdPat; -- --/// Stores -- --defm : StPat; -- --/// FP conversion operations -- --def : Pat<(loongarch_ftint FPR64:$src), (FTINTRZ_W_D FPR64:$src)>; --def : Pat<(f64 (loongarch_ftint FPR64:$src)), (FTINTRZ_L_D FPR64:$src)>; --def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_L_S FPR32:$src)>; -- --// f64 -> f32 --def : Pat<(f32 (fpround FPR64:$src)), (FCVT_S_D FPR64:$src)>; --// f32 -> f64 --def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>; --} // Predicates = [HasBasicD] -- --/// Floating point constants -- --let Predicates = [HasBasicD, IsLA64] in { --def : Pat<(f64 fpimm0), (MOVGR2FR_D R0)>; --def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FR_D R0))>; --def : Pat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D R0, 1)))>; -- --// Convert int to FP --def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))), -- (FFINT_D_W (MOVGR2FR_W GPR:$src))>; --def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>; -- --def : Pat<(f64 (uint_to_fp (i64 (zexti32 (i64 GPR:$src))))), -- (FFINT_D_W (MOVGR2FR_W GPR:$src))>; -- --def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>; -- --// Convert FP to int --def : Pat<(bitconvert FPR64:$src), (MOVFR2GR_D FPR64:$src)>; --} // Predicates = [HasBasicD, IsLA64] -- --let Predicates = [HasBasicD, IsLA32] in { --def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>; --def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>; --def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>; -- --// Convert int to FP --def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>; --} // Predicates = [HasBasicD, IsLA32] -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td -deleted file mode 100644 -index d2ba1fdff..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td -+++ /dev/null -@@ -1,241 +0,0 @@ --//==- LoongArchInstrFormatsF.td - LoongArch FP Instr Formats -*- tablegen -*-=// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// -- --//===----------------------------------------------------------------------===// --// Describe LoongArch floating-point instructions format --// --// opcode - operation code. --// fd - destination register operand. --// {c/f}{j/k/a} - source register operand. --// immN - immediate data operand. --// --//===----------------------------------------------------------------------===// -- --// 2R-type --// --class FPFmt2R op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> fj; -- bits<5> fd; -- -- let Inst{31-10} = op; -- let Inst{9-5} = fj; -- let Inst{4-0} = fd; --} -- --// 3R-type --// --class FPFmt3R op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> fk; -- bits<5> fj; -- bits<5> fd; -- -- let Inst{31-15} = op; -- let Inst{14-10} = fk; -- let Inst{9-5} = fj; -- let Inst{4-0} = fd; --} -- --// 4R-type --// --class FPFmt4R op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> fa; -- bits<5> fk; -- bits<5> fj; -- bits<5> fd; -- -- let Inst{31-20} = op; -- let Inst{19-15} = fa; -- let Inst{14-10} = fk; -- let Inst{9-5} = fj; -- let Inst{4-0} = fd; --} -- --// 2RI12-type --// --class FPFmt2RI12 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<12> imm12; -- bits<5> rj; -- bits<5> fd; -- -- let Inst{31-22} = op; -- let Inst{21-10} = imm12; -- let Inst{9-5} = rj; -- let Inst{4-0} = fd; --} -- --// FmtFCMP --// --class FPFmtFCMP op, bits<5> cond, dag outs, dag ins, string opcstr, -- string opnstr, list pattern = []> -- : LAInst { -- bits<5> fk; -- bits<5> fj; -- bits<3> cd; -- -- let Inst{31-20} = op; -- let Inst{19-15} = cond; -- let Inst{14-10} = fk; -- let Inst{9-5} = fj; -- let Inst{4-3} = 0b00; -- let Inst{2-0} = cd; --} -- --// FPFmtBR --// --class FPFmtBR opcode, dag outs, dag ins, string opcstr, -- string opnstr, list pattern = []> -- : LAInst { -- bits<21> imm21; -- bits<3> cj; -- -- let Inst{31-26} = opcode{7-2}; -- let Inst{25-10} = imm21{15-0}; -- let Inst{9-8} = opcode{1-0}; -- let Inst{7-5} = cj; -- let Inst{4-0} = imm21{20-16}; --} -- --// FmtFSEL --// --class FPFmtFSEL op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<3> ca; -- bits<5> fk; -- bits<5> fj; -- bits<5> fd; -- -- let Inst{31-18} = op; -- let Inst{17-15} = ca; -- let Inst{14-10} = fk; -- let Inst{9-5} = fj; -- let Inst{4-0} = fd; --} -- --// FPFmtMOV --// --class FPFmtMOV op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> src; -- bits<5> dst; -- -- let Inst{31-10} = op; -- let Inst{9-5} = src; -- let Inst{4-0} = dst; --} -- --// FPFmtMEM --// --class FPFmtMEM op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> rk; -- bits<5> rj; -- bits<5> fd; -- -- let Inst{31-15} = op; -- let Inst{14-10} = rk; -- let Inst{9-5} = rj; -- let Inst{4-0} = fd; --} -- --//===----------------------------------------------------------------------===// --// Instruction class templates --//===----------------------------------------------------------------------===// -- --class FP_ALU_2R op, string opstr, RegisterClass rc> -- : FPFmt2R; -- --class FP_ALU_3R op, string opstr, RegisterClass rc> -- : FPFmt3R; -- --class FP_ALU_4R op, string opstr, RegisterClass rc> -- : FPFmt4R; -- --class FPCMPOpc value> { -- bits<12> val = value; --} -- --class FPCMPCond value> { -- bits<5> val = value; --} -- --class FP_CMP -- : FPFmtFCMP; -- --class FP_CONV op, string opstr, RegisterClass rcd, RegisterClass rcs> -- : FPFmt2R; -- --class FP_MOV op, string opstr, RegisterClass rcd, RegisterClass rcs> -- : FPFmtMOV; -- --class FP_SEL op, string opstr, RegisterClass rc> -- : FPFmtFSEL; -- --class FP_BRANCH opcode, string opstr> -- : FPFmtBR { -- let isBranch = 1; -- let isTerminator = 1; --} -- --let mayLoad = 1 in { --class FP_LOAD_3R op, string opstr, RegisterClass rc> -- : FPFmtMEM; --class FP_LOAD_2RI12 op, string opstr, RegisterClass rc> -- : FPFmt2RI12; --} // mayLoad = 1 -- --let mayStore = 1 in { --class FP_STORE_3R op, string opstr, RegisterClass rc> -- : FPFmtMEM; --class FP_STORE_2RI12 op, string opstr, RegisterClass rc> -- : FPFmt2RI12; --} // mayStore = 1 -- --def FPCMP_OPC_S : FPCMPOpc<0b000011000001>; --def FPCMP_OPC_D : FPCMPOpc<0b000011000010>; -- --def FPCMP_COND_CAF : FPCMPCond<0x0>; --def FPCMP_COND_CUN : FPCMPCond<0x8>; --def FPCMP_COND_CEQ : FPCMPCond<0x4>; --def FPCMP_COND_CUEQ : FPCMPCond<0xC>; --def FPCMP_COND_CLT : FPCMPCond<0x2>; --def FPCMP_COND_CULT : FPCMPCond<0xA>; --def FPCMP_COND_CLE : FPCMPCond<0x6>; --def FPCMP_COND_CULE : FPCMPCond<0xE>; --def FPCMP_COND_CNE : FPCMPCond<0x10>; --def FPCMP_COND_COR : FPCMPCond<0x14>; --def FPCMP_COND_CUNE : FPCMPCond<0x18>; --def FPCMP_COND_SAF : FPCMPCond<0x1>; --def FPCMP_COND_SUN : FPCMPCond<0x9>; --def FPCMP_COND_SEQ : FPCMPCond<0x5>; --def FPCMP_COND_SUEQ : FPCMPCond<0xD>; --def FPCMP_COND_SLT : FPCMPCond<0x3>; --def FPCMP_COND_SULT : FPCMPCond<0xB>; --def FPCMP_COND_SLE : FPCMPCond<0x7>; --def FPCMP_COND_SULE : FPCMPCond<0xF>; --def FPCMP_COND_SNE : FPCMPCond<0x11>; --def FPCMP_COND_SOR : FPCMPCond<0x15>; --def FPCMP_COND_SUNE : FPCMPCond<0x19>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp -index 0d9ec9e2e..7c4c141e1 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information -*- C++ -*-==// -+//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information --------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,192 +11,365 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchFrameLowering.h" --#include "LoongArchMachineFunctionInfo.h" --#include "LoongArchSubtarget.h" - #include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "LoongArchInstrInfo.h" -+#include "LoongArchMachineFunction.h" -+#include "LoongArchTargetMachine.h" -+#include "LoongArchRegisterInfo.h" -+#include "LoongArchSubtarget.h" -+#include "llvm/ADT/BitVector.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/ADT/StringSwitch.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" - #include "llvm/CodeGen/MachineFrameInfo.h" - #include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineInstr.h" - #include "llvm/CodeGen/MachineInstrBuilder.h" -+#include "llvm/CodeGen/MachineModuleInfo.h" -+#include "llvm/CodeGen/MachineOperand.h" - #include "llvm/CodeGen/MachineRegisterInfo.h" - #include "llvm/CodeGen/RegisterScavenging.h" --#include "llvm/IR/DiagnosticInfo.h" -+#include "llvm/CodeGen/TargetInstrInfo.h" -+#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "llvm/CodeGen/TargetSubtargetInfo.h" -+#include "llvm/IR/DataLayout.h" -+#include "llvm/IR/DebugLoc.h" -+#include "llvm/IR/Function.h" - #include "llvm/MC/MCDwarf.h" -+#include "llvm/MC/MCRegisterInfo.h" -+#include "llvm/MC/MachineLocation.h" -+#include "llvm/Support/CodeGen.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Target/TargetOptions.h" -+#include -+#include -+#include -+#include - - using namespace llvm; - --#define DEBUG_TYPE "loongarch-frame-lowering" -- --// Return true if the specified function should have a dedicated frame --// pointer register. This is true if frame pointer elimination is --// disabled, if it needs dynamic stack realignment, if the function has --// variable sized allocas, or if the frame address is taken. --bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const { -- const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); -- -- const MachineFrameInfo &MFI = MF.getFrameInfo(); -- return MF.getTarget().Options.DisableFramePointerElim(MF) || -- RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || -- MFI.isFrameAddressTaken(); --} -- --bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const { -+// We would like to split the SP adjustment to reduce prologue/epilogue -+// as following instructions. In this way, the offset of the callee saved -+// register could fit in a single store. -+uint64_t -+LoongArchFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF, -+ bool IsPrologue) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); -- const TargetRegisterInfo *TRI = STI.getRegisterInfo(); -- -- return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF); --} -- --void LoongArchFrameLowering::adjustReg(MachineBasicBlock &MBB, -- MachineBasicBlock::iterator MBBI, -- const DebugLoc &DL, Register DestReg, -- Register SrcReg, int64_t Val, -- MachineInstr::MIFlag Flag) const { -- const LoongArchInstrInfo *TII = STI.getInstrInfo(); -- bool IsLA64 = STI.is64Bit(); -- -- if (DestReg == SrcReg && Val == 0) -- return; -+ const std::vector &CSI = MFI.getCalleeSavedInfo(); -+ uint64_t StackSize = MFI.getStackSize(); - -- if (isInt<12>(Val)) { -- // addi.w/d $DstReg, $SrcReg, Val -- BuildMI(MBB, MBBI, DL, -- TII->get(IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W), DestReg) -- .addReg(SrcReg) -- .addImm(Val) -- .setMIFlag(Flag); -- return; -+ // Return the FirstSPAdjustAmount if the StackSize can not fit in signed -+ // 12-bit and there exists a callee saved register need to be pushed. -+ if (!isInt<12>(StackSize)) { -+ // FirstSPAdjustAmount is choosed as (2048 - StackAlign) -+ // because 2048 will cause sp = sp + 2048 in epilogue split into -+ // multi-instructions. The offset smaller than 2048 can fit in signle -+ // load/store instruction and we have to stick with the stack alignment. -+ return CSI.size() > 0 ? 2048 - getStackAlign().value() -+ : (IsPrologue ? 2048 : 0); - } -- -- report_fatal_error("adjustReg cannot yet handle adjustments >12 bits"); -+ return 0; - } - --// Determine the size of the frame and maximum call frame size. --void LoongArchFrameLowering::determineFrameLayout(MachineFunction &MF) const { -- MachineFrameInfo &MFI = MF.getFrameInfo(); -- -- // Get the number of bytes to allocate from the FrameInfo. -- uint64_t FrameSize = MFI.getStackSize(); -- -- // Make sure the frame is aligned. -- FrameSize = alignTo(FrameSize, getStackAlign()); -- -- // Update frame info. -- MFI.setStackSize(FrameSize); --} -+//===----------------------------------------------------------------------===// -+// -+// Stack Frame Processing methods -+// +----------------------------+ -+// -+// The stack is allocated decrementing the stack pointer on -+// the first instruction of a function prologue. Once decremented, -+// all stack references are done thought a positive offset -+// from the stack/frame pointer, so the stack is considering -+// to grow up! Otherwise terrible hacks would have to be made -+// to get this stack ABI compliant :) -+// -+// The stack frame required by the ABI (after call): -+// Offset -+// -+// 0 ---------- -+// 4 Args to pass -+// . Alloca allocations -+// . Local Area -+// . CPU "Callee Saved" Registers -+// . saved FP -+// . saved RA -+// . FPU "Callee Saved" Registers -+// StackSize ----------- -+// -+// Offset - offset from sp after stack allocation on function prologue -+// -+// The sp is the stack pointer subtracted/added from the stack size -+// at the Prologue/Epilogue -+// -+// References to the previous stack (to obtain arguments) are done -+// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1)) -+// -+// Examples: -+// - reference to the actual stack frame -+// for any local area var there is smt like : FI >= 0, StackOffset: 4 -+// st.w REGX, SP, 4 -+// -+// - reference to previous stack frame -+// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16. -+// The emitted instruction will be something like: -+// ld.w REGX, SP, 16+StackSize -+// -+// Since the total stack size is unknown on LowerFormalArguments, all -+// stack references (ObjectOffset) created to reference the function -+// arguments, are negative numbers. This way, on eliminateFrameIndex it's -+// possible to detect those references and the offsets are adjusted to -+// their real location. -+// -+//===----------------------------------------------------------------------===// -+// -+LoongArchFrameLowering::LoongArchFrameLowering(const LoongArchSubtarget &STI) -+ : TargetFrameLowering(StackGrowsDown, STI.getStackAlignment(), 0, -+ STI.getStackAlignment()), STI(STI) {} - - void LoongArchFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); -- const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); -- const LoongArchInstrInfo *TII = STI.getInstrInfo(); -- MachineBasicBlock::iterator MBBI = MBB.begin(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); - -- Register SPReg = LoongArch::R3; -- Register FPReg = LoongArch::R22; -- -- // Debug location must be unknown since the first debug location is used -- // to determine the end of the prologue. -- DebugLoc DL; -- -- // Determine the correct frame layout -- determineFrameLayout(MF); -+ const LoongArchInstrInfo &TII = -+ *static_cast(STI.getInstrInfo()); -+ const LoongArchRegisterInfo &RegInfo = -+ *static_cast(STI.getRegisterInfo()); -+ MachineBasicBlock::iterator MBBI = MBB.begin(); -+ DebugLoc dl; -+ LoongArchABIInfo ABI = STI.getABI(); -+ unsigned SP = ABI.GetStackPtr(); -+ unsigned FP = ABI.GetFramePtr(); -+ unsigned ZERO = ABI.GetNullPtr(); -+ unsigned MOVE = ABI.GetGPRMoveOp(); -+ unsigned ADDI = ABI.GetPtrAddiOp(); -+ unsigned AND = ABI.IsLP64() ? LoongArch::AND : LoongArch::AND32; -+ unsigned SLLI = ABI.IsLP64() ? LoongArch::SLLI_D : LoongArch::SLLI_W; -+ -+ const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? -+ &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; - - // First, compute final stack size. - uint64_t StackSize = MFI.getStackSize(); -+ uint64_t RealStackSize = StackSize; - -- // Early exit if there is no need to allocate space in the stack. -+ // No need to allocate space on the stack. - if (StackSize == 0 && !MFI.adjustsStack()) - return; - -+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF, true); -+ uint64_t SecondSPAdjustAmount = RealStackSize - FirstSPAdjustAmount; -+ // Split the SP adjustment to reduce the offsets of callee saved spill. -+ if (FirstSPAdjustAmount) -+ StackSize = FirstSPAdjustAmount; -+ - // Adjust stack. -- adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); -- // Emit ".cfi_def_cfa_offset StackSize". -- unsigned CFIIndex = -- MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); -- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) -- .addCFIIndex(CFIIndex) -- .setMIFlag(MachineInstr::FrameSetup); -+ TII.adjustReg(SP, SP, -StackSize, MBB, MBBI, MachineInstr::FrameSetup); -+ if (FirstSPAdjustAmount != 2048 || SecondSPAdjustAmount == 0) { -+ // Emit ".cfi_def_cfa_offset StackSize". -+ unsigned CFIIndex = -+ MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); -+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) -+ .addCFIIndex(CFIIndex); -+ } - -- const auto &CSI = MFI.getCalleeSavedInfo(); -+ MachineModuleInfo &MMI = MF.getMMI(); -+ const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); -+ -+ const std::vector &CSI = MFI.getCalleeSavedInfo(); -+ -+ if (!CSI.empty()) { -+ // Find the instruction past the last instruction that saves a callee-saved -+ // register to the stack. -+ for (unsigned i = 0; i < CSI.size(); ++i) -+ ++MBBI; -+ -+ // Iterate over list of callee-saved registers and emit .cfi_offset -+ // directives. -+ for (std::vector::const_iterator I = CSI.begin(), -+ E = CSI.end(); I != E; ++I) { -+ int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); -+ unsigned Reg = I->getReg(); -+ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( -+ nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); -+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) -+ .addCFIIndex(CFIIndex); -+ } -+ } - -- // The frame pointer is callee-saved, and code has been generated for us to -- // save it to the stack. We need to skip over the storing of callee-saved -- // registers as the frame pointer must be modified after it has been saved -- // to the stack, not before. -- std::advance(MBBI, CSI.size()); -- -- // Iterate over list of callee-saved registers and emit .cfi_offset -- // directives. -- for (const auto &Entry : CSI) { -- int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx()); -- unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( -- nullptr, RI->getDwarfRegNum(Entry.getReg(), true), Offset)); -- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) -- .addCFIIndex(CFIIndex) -- .setMIFlag(MachineInstr::FrameSetup); -+ if (LoongArchFI->callsEhReturn()) { -+ // Insert instructions that spill eh data registers. -+ for (int I = 0; I < 4; ++I) { -+ if (!MBB.isLiveIn(ABI.GetEhDataReg(I))) -+ MBB.addLiveIn(ABI.GetEhDataReg(I)); -+ TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false, -+ LoongArchFI->getEhDataRegFI(I), RC, &RegInfo); -+ } -+ -+ // Emit .cfi_offset directives for eh data registers. -+ for (int I = 0; I < 4; ++I) { -+ int64_t Offset = MFI.getObjectOffset(LoongArchFI->getEhDataRegFI(I)); -+ unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true); -+ unsigned CFIIndex = MF.addFrameInst( -+ MCCFIInstruction::createOffset(nullptr, Reg, Offset)); -+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) -+ .addCFIIndex(CFIIndex); -+ } - } - -- // Generate new FP. -+ // If framepointer enabled, set it to point to the stack pointer on entry. - if (hasFP(MF)) { -- adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); -- -- // Emit ".cfi_def_cfa $fp, 0" -- unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( -- nullptr, RI->getDwarfRegNum(FPReg, true), 0)); -- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) -+ // Insert instruction "addi.w/d $fp, $sp, StackSize" at this location. -+ TII.adjustReg(FP, SP, StackSize - LoongArchFI->getVarArgsSaveSize(), MBB, -+ MBBI, MachineInstr::FrameSetup); -+ // Emit ".cfi_def_cfa $fp, $varargs_size". -+ unsigned CFIIndex = MF.addFrameInst( -+ MCCFIInstruction::cfiDefCfa(nullptr, MRI->getDwarfRegNum(FP, true), -+ LoongArchFI->getVarArgsSaveSize())); -+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlag(MachineInstr::FrameSetup); - } -+ -+ // Emit the second SP adjustment after saving callee saved registers. -+ if (FirstSPAdjustAmount && SecondSPAdjustAmount) { -+ if (hasFP(MF)) { -+ assert(SecondSPAdjustAmount > 0 && -+ "SecondSPAdjustAmount should be greater than zero"); -+ TII.adjustReg(SP, SP, -SecondSPAdjustAmount, MBB, MBBI, -+ MachineInstr::FrameSetup); -+ } else { -+ // FIXME: RegScavenger will place the spill instruction before the -+ // prologue if a VReg is created in the prologue. This will pollute the -+ // caller's stack data. Therefore, until there is better way, we just use -+ // the `addi.w/d` instruction for stack adjustment to ensure that VReg -+ // will not be created. -+ for (int Val = SecondSPAdjustAmount; Val > 0; Val -= 2048) -+ BuildMI(MBB, MBBI, dl, TII.get(ADDI), SP) -+ .addReg(SP) -+ .addImm(Val < 2048 ? -Val : -2048) -+ .setMIFlag(MachineInstr::FrameSetup); -+ // If we are using a frame-pointer, and thus emitted ".cfi_def_cfa fp, 0", -+ // don't emit an sp-based .cfi_def_cfa_offset. -+ // Emit ".cfi_def_cfa_offset StackSize" -+ unsigned CFIIndex = MF.addFrameInst( -+ MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize())); -+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) -+ .addCFIIndex(CFIIndex) -+ .setMIFlag(MachineInstr::FrameSetup); -+ } -+ } -+ -+ // Realign stack. -+ if (hasFP(MF)) { -+ if (RegInfo.hasStackRealignment(MF)) { -+ // addiu $Reg, $zero, -MaxAlignment -+ // andi $sp, $sp, $Reg -+ unsigned VR = MF.getRegInfo().createVirtualRegister(RC); -+ assert((Log2(MFI.getMaxAlign()) < 16) && -+ "Function's alignment size requirement is not supported."); -+ int MaxAlign = -(int)MFI.getMaxAlign().value(); -+ int Alignment = (int)MFI.getMaxAlign().value(); -+ -+ if (Alignment <= 2048) { -+ BuildMI(MBB, MBBI, dl, TII.get(ADDI), VR).addReg(ZERO).addImm(MaxAlign); -+ BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); -+ } else { -+ const unsigned NrBitsToZero = countTrailingZeros((unsigned)Alignment); -+ BuildMI(MBB, MBBI, dl, TII.get(ADDI), VR).addReg(ZERO).addImm(-1); -+ BuildMI(MBB, MBBI, dl, TII.get(SLLI), VR) -+ .addReg(VR) -+ .addImm(NrBitsToZero); -+ BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); -+ } -+ -+ if (hasBP(MF)) { -+ // move $s7, $sp -+ unsigned BP = STI.isABI_LP64() ? LoongArch::S7_64 : LoongArch::S7; -+ BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP).addReg(SP).addReg(ZERO); -+ } -+ } -+ } - } - - void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { -- const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); -- MachineFrameInfo &MFI = MF.getFrameInfo(); -- Register SPReg = LoongArch::R3; -- - MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); -- DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); - -- const auto &CSI = MFI.getCalleeSavedInfo(); -- // Skip to before the restores of callee-saved registers. -- auto LastFrameDestroy = MBBI; -- if (!CSI.empty()) -- LastFrameDestroy = std::prev(MBBI, CSI.size()); -+ const LoongArchInstrInfo &TII = -+ *static_cast(STI.getInstrInfo()); -+ const LoongArchRegisterInfo &RegInfo = -+ *static_cast(STI.getRegisterInfo()); -+ -+ DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); -+ LoongArchABIInfo ABI = STI.getABI(); -+ unsigned SP = ABI.GetStackPtr(); -+ unsigned FP = ABI.GetFramePtr(); - - // Get the number of bytes from FrameInfo. - uint64_t StackSize = MFI.getStackSize(); - - // Restore the stack pointer. -- if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) { -- assert(hasFP(MF) && "frame pointer should not have been eliminated"); -- adjustReg(MBB, LastFrameDestroy, DL, SPReg, LoongArch::R22, -StackSize, -- MachineInstr::FrameDestroy); -+ if (hasFP(MF) && -+ (RegInfo.hasStackRealignment(MF) || MFI.hasVarSizedObjects())) { -+ // Find the first instruction that restores a callee-saved register. -+ MachineBasicBlock::iterator I = MBBI; -+ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) -+ --I; -+ TII.adjustReg(SP, FP, -(StackSize - LoongArchFI->getVarArgsSaveSize()), MBB, -+ I); - } - -- // Deallocate stack -- adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); --} -+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); -+ if (FirstSPAdjustAmount) { -+ uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount; -+ assert(SecondSPAdjustAmount > 0 && -+ "SecondSPAdjustAmount should be greater than zero"); -+ // Find the first instruction that restores a callee-saved register. -+ MachineBasicBlock::iterator I = MBBI; -+ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) -+ --I; -+ -+ TII.adjustReg(SP, SP, SecondSPAdjustAmount, MBB, I); -+ } - --void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, -- BitVector &SavedRegs, -- RegScavenger *RS) const { -- TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); -- // Unconditionally spill RA and FP only if the function uses a frame -- // pointer. -- if (hasFP(MF)) { -- SavedRegs.set(LoongArch::R1); -- SavedRegs.set(LoongArch::R22); -+ if (LoongArchFI->callsEhReturn()) { -+ const TargetRegisterClass *RC = -+ ABI.ArePtrs64bit() ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ -+ // Find first instruction that restores a callee-saved register. -+ MachineBasicBlock::iterator I = MBBI; -+ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) -+ --I; -+ -+ // Insert instructions that restore eh data registers. -+ for (int J = 0; J < 4; ++J) -+ TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J), -+ LoongArchFI->getEhDataRegFI(J), RC, &RegInfo); - } -- // Mark BP as used if function has dedicated base pointer. -- if (hasBP(MF)) -- SavedRegs.set(LoongArchABI::getBPReg()); -+ -+ if (FirstSPAdjustAmount) -+ StackSize = FirstSPAdjustAmount; -+ -+ if (!StackSize) -+ return; -+ -+ // Final adjust stack. -+ TII.adjustReg(SP, SP, StackSize, MBB, MBBI); - } - --StackOffset LoongArchFrameLowering::getFrameIndexReference( -- const MachineFunction &MF, int FI, Register &FrameReg) const { -+StackOffset -+LoongArchFrameLowering::getFrameIndexReference(const MachineFunction &MF, -+ int FI, -+ Register &FrameReg) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); -+ LoongArchABIInfo ABI = STI.getABI(); -+ const auto *LoongArchFI = MF.getInfo(); - - // Callee-saved registers should be referenced relative to the stack - // pointer (positive offset), otherwise use the frame pointer (negative -@@ -207,17 +380,182 @@ StackOffset LoongArchFrameLowering::getFrameIndexReference( - StackOffset Offset = - StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + - MFI.getOffsetAdjustment()); -+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); - - if (CSI.size()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); - } - -- FrameReg = RI->getFrameRegister(MF); -- if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) { -- FrameReg = LoongArch::R3; -+ bool EhDataRegFI = LoongArchFI->isEhDataRegFI(FI); -+ if ((FI >= MinCSFI && FI <= MaxCSFI) || EhDataRegFI) { -+ FrameReg = ABI.GetStackPtr(); -+ -+ if (FirstSPAdjustAmount) -+ Offset += StackOffset::getFixed(FirstSPAdjustAmount); -+ else -+ Offset += StackOffset::getFixed(MFI.getStackSize()); -+ } else if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) { -+ // If the stack was realigned, the frame pointer is set in order to allow -+ // SP to be restored, so we need another base register to record the stack -+ // after realignment. -+ FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr(); - Offset += StackOffset::getFixed(MFI.getStackSize()); -+ } else { -+ FrameReg = RI->getFrameRegister(MF); -+ if (hasFP(MF)) -+ Offset += StackOffset::getFixed(LoongArchFI->getVarArgsSaveSize()); -+ else -+ Offset += StackOffset::getFixed(MFI.getStackSize()); - } -- - return Offset; - } -+ -+bool LoongArchFrameLowering::spillCalleeSavedRegisters( -+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, -+ ArrayRef CSI, const TargetRegisterInfo *TRI) const { -+ MachineFunction *MF = MBB.getParent(); -+ const TargetInstrInfo &TII = *STI.getInstrInfo(); -+ -+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) { -+ // Add the callee-saved register as live-in. Do not add if the register is -+ // RA and return address is taken, because it has already been added in -+ // method LoongArchTargetLowering::lowerRETURNADDR. -+ // It's killed at the spill, unless the register is RA and return address -+ // is taken. -+ unsigned Reg = CSI[i].getReg(); -+ bool IsRAAndRetAddrIsTaken = (Reg == LoongArch::RA || Reg == LoongArch::RA_64) -+ && MF->getFrameInfo().isReturnAddressTaken(); -+ if (!IsRAAndRetAddrIsTaken) -+ MBB.addLiveIn(Reg); -+ -+ // Insert the spill to the stack frame. -+ bool IsKill = !IsRAAndRetAddrIsTaken; -+ const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); -+ TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, -+ CSI[i].getFrameIdx(), RC, TRI); -+ } -+ -+ return true; -+} -+ -+bool -+LoongArchFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { -+ const MachineFrameInfo &MFI = MF.getFrameInfo(); -+ // Reserve call frame if the size of the maximum call frame fits into 12-bit -+ // immediate field and there are no variable sized objects on the stack. -+ // Make sure the second register scavenger spill slot can be accessed with one -+ // instruction. -+ return isInt<12>(MFI.getMaxCallFrameSize() + getStackAlignment()) && -+ !MFI.hasVarSizedObjects(); -+} -+ -+/// Mark \p Reg and all registers aliasing it in the bitset. -+static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, -+ unsigned Reg) { -+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); -+ for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) -+ SavedRegs.set(*AI); -+} -+ -+void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, -+ BitVector &SavedRegs, -+ RegScavenger *RS) const { -+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); -+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); -+ LoongArchABIInfo ABI = STI.getABI(); -+ unsigned FP = ABI.GetFramePtr(); -+ unsigned BP = ABI.IsLP64() ? LoongArch::S7_64 : LoongArch::S7; -+ -+ // Mark $fp as used if function has dedicated frame pointer. -+ if (hasFP(MF)) -+ setAliasRegs(MF, SavedRegs, FP); -+ // Mark $s7 as used if function has dedicated base pointer. -+ if (hasBP(MF)) -+ setAliasRegs(MF, SavedRegs, BP); -+ -+ // Create spill slots for eh data registers if function calls eh_return. -+ if (LoongArchFI->callsEhReturn()) -+ LoongArchFI->createEhDataRegsFI(); -+ -+ // Set scavenging frame index if necessary. -+ uint64_t MaxSPOffset = estimateStackSize(MF); -+ -+ // If there is a variable -+ // sized object on the stack, the estimation cannot account for it. -+ if (isIntN(12, MaxSPOffset) && -+ !MF.getFrameInfo().hasVarSizedObjects()) -+ return; -+ -+ const TargetRegisterClass &RC = -+ ABI.ArePtrs64bit() ? LoongArch::GPR64RegClass : LoongArch::GPR32RegClass; -+ int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC), -+ TRI->getSpillAlign(RC), false); -+ RS->addScavengingFrameIndex(FI); -+} -+ -+// hasFP - Return true if the specified function should have a dedicated frame -+// pointer register. This is true if the function has variable sized allocas, -+// if it needs dynamic stack realignment, if frame pointer elimination is -+// disabled, or if the frame address is taken. -+bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const { -+ const MachineFrameInfo &MFI = MF.getFrameInfo(); -+ const TargetRegisterInfo *TRI = STI.getRegisterInfo(); -+ -+ return MF.getTarget().Options.DisableFramePointerElim(MF) || -+ MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || -+ TRI->hasStackRealignment(MF); -+} -+ -+bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const { -+ const MachineFrameInfo &MFI = MF.getFrameInfo(); -+ const TargetRegisterInfo *TRI = STI.getRegisterInfo(); -+ -+ return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF); -+} -+ -+// Estimate the size of the stack, including the incoming arguments. We need to -+// account for register spills, local objects, reserved call frame and incoming -+// arguments. This is required to determine the largest possible positive offset -+// from $sp so that it can be determined if an emergency spill slot for stack -+// addresses is required. -+uint64_t LoongArchFrameLowering:: -+estimateStackSize(const MachineFunction &MF) const { -+ const MachineFrameInfo &MFI = MF.getFrameInfo(); -+ const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); -+ -+ int64_t Size = 0; -+ -+ // Iterate over fixed sized objects which are incoming arguments. -+ for (int I = MFI.getObjectIndexBegin(); I != 0; ++I) -+ if (MFI.getObjectOffset(I) > 0) -+ Size += MFI.getObjectSize(I); -+ -+ // Conservatively assume all callee-saved registers will be saved. -+ for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) { -+ unsigned RegSize = TRI.getSpillSize(*TRI.getMinimalPhysRegClass(*R)); -+ Size = alignTo(Size + RegSize, RegSize); -+ } -+ -+ // Get the size of the rest of the frame objects and any possible reserved -+ // call frame, accounting for alignment. -+ return Size + MFI.estimateStackSize(MF); -+} -+ -+// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -+MachineBasicBlock::iterator LoongArchFrameLowering:: -+eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const { -+ unsigned SP = STI.getABI().IsLP64() ? LoongArch::SP_64 : LoongArch::SP; -+ -+ if (!hasReservedCallFrame(MF)) { -+ int64_t Amount = I->getOperand(0).getImm(); -+ if (I->getOpcode() == LoongArch::ADJCALLSTACKDOWN) -+ Amount = -Amount; -+ -+ STI.getInstrInfo()->adjustReg(SP, SP, Amount, MBB, I); -+ } -+ -+ return MBB.erase(I); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h -index 72d8e006a..74aabaeb4 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h -@@ -1,4 +1,4 @@ --//=- LoongArchFrameLowering.h - TargetFrameLowering for LoongArch -*- C++ -*--// -+//===-- LoongArchFrameLowering.h - Define frame lowering for LoongArch ----*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,51 +6,66 @@ - // - //===----------------------------------------------------------------------===// - // --// This class implements LoongArch-specific bits of TargetFrameLowering class. -+// - // - //===----------------------------------------------------------------------===// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H - -+#include "LoongArch.h" - #include "llvm/CodeGen/TargetFrameLowering.h" - - namespace llvm { --class LoongArchSubtarget; -+ class LoongArchSubtarget; - - class LoongArchFrameLowering : public TargetFrameLowering { - const LoongArchSubtarget &STI; - - public: -- explicit LoongArchFrameLowering(const LoongArchSubtarget &STI) -- : TargetFrameLowering(StackGrowsDown, -- /*StackAlignment=*/Align(16), -- /*LocalAreaOffset=*/0), -- STI(STI) {} -+ explicit LoongArchFrameLowering(const LoongArchSubtarget &STI); - -+ /// emitProlog/emitEpilog - These methods insert prolog and epilog code into -+ /// the function. - void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - -+ StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, -+ Register &FrameReg) const override; -+ -+ bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MI, -+ ArrayRef CSI, -+ const TargetRegisterInfo *TRI) const override; -+ -+ bool hasReservedCallFrame(const MachineFunction &MF) const override; -+ - void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS) const override; - -- MachineBasicBlock::iterator -- eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, -- MachineBasicBlock::iterator MI) const override { -- return MBB.erase(MI); -+ bool hasFP(const MachineFunction &MF) const override; -+ -+ bool hasBP(const MachineFunction &MF) const; -+ -+ bool enableShrinkWrapping(const MachineFunction &MF) const override { -+ return true; - } - -- StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, -- Register &FrameReg) const override; -+ MachineBasicBlock::iterator -+ eliminateCallFramePseudoInstr(MachineFunction &MF, -+ MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const override; - -- bool hasFP(const MachineFunction &MF) const override; -- bool hasBP(const MachineFunction &MF) const; -+ // Get the first stack adjustment amount for split the SP adjustment. -+ // Return 0 if we don't want to to split the SP adjustment in prologue and -+ // epilogue. -+ uint64_t getFirstSPAdjustAmount(const MachineFunction &MF, -+ bool IsPrologue = false) const; - --private: -- void determineFrameLayout(MachineFunction &MF) const; -- void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, -- const DebugLoc &DL, Register DestReg, Register SrcReg, -- int64_t Val, MachineInstr::MIFlag Flag) const; -+protected: -+ uint64_t estimateStackSize(const MachineFunction &MF) const; - }; --} // end namespace llvm --#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H -+ -+} // End llvm namespace -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp -index bb40ff817..0efb739e0 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp -@@ -1,4 +1,4 @@ --//=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===// -+//===-- LoongArchISelDAGToDAG.cpp - A Dag to Dag Inst Selector for LoongArch --------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,176 +11,868 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchISelDAGToDAG.h" --#include "LoongArchISelLowering.h" -+#include "LoongArch.h" -+#include "LoongArchMachineFunction.h" -+#include "LoongArchRegisterInfo.h" -+#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" - #include "MCTargetDesc/LoongArchMCTargetDesc.h" --#include "MCTargetDesc/LoongArchMatInt.h" --#include "llvm/Support/KnownBits.h" -- -+#include "llvm/CodeGen/MachineConstantPool.h" -+#include "llvm/CodeGen/MachineFrameInfo.h" -+#include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineInstrBuilder.h" -+#include "llvm/CodeGen/MachineRegisterInfo.h" -+#include "llvm/CodeGen/SelectionDAGNodes.h" -+#include "llvm/IR/CFG.h" -+#include "llvm/IR/Dominators.h" -+#include "llvm/IR/GlobalValue.h" -+#include "llvm/IR/Instructions.h" -+#include "llvm/IR/Intrinsics.h" -+#include "llvm/IR/IntrinsicsLoongArch.h" -+#include "llvm/IR/Type.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/raw_ostream.h" -+#include "llvm/Target/TargetMachine.h" - using namespace llvm; - - #define DEBUG_TYPE "loongarch-isel" - --void LoongArchDAGToDAGISel::Select(SDNode *Node) { -- // If we have a custom node, we have already selected. -- if (Node->isMachineOpcode()) { -- LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); -- Node->setNodeId(-1); -- return; -- } -+//===----------------------------------------------------------------------===// -+// Instruction Selector Implementation -+//===----------------------------------------------------------------------===// - -- // Instruction Selection not handled by the auto-generated tablegen selection -- // should be handled here. -- unsigned Opcode = Node->getOpcode(); -- MVT GRLenVT = Subtarget->getGRLenVT(); -- SDLoc DL(Node); -- MVT VT = Node->getSimpleValueType(0); -+//===----------------------------------------------------------------------===// -+// LoongArchDAGToDAGISel - LoongArch specific code to select LoongArch machine -+// instructions for SelectionDAG operations. -+//===----------------------------------------------------------------------===// - -- switch (Opcode) { -- default: -- break; -- case ISD::Constant: { -- int64_t Imm = cast(Node)->getSExtValue(); -- if (Imm == 0 && VT == GRLenVT) { -- SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, -- LoongArch::R0, GRLenVT); -- ReplaceNode(Node, New.getNode()); -- return; -- } -- SDNode *Result = nullptr; -- SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT); -- // The instructions in the sequence are handled here. -- for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { -- SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT); -- if (Inst.Opc == LoongArch::LU12I_W) -- Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm); -- else -- Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm); -- SrcReg = SDValue(Result, 0); -- } -+void LoongArchDAGToDAGISel::PostprocessISelDAG() { doPeepholeLoadStoreADDI(); } - -- ReplaceNode(Node, Result); -- return; -+void LoongArchDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { -+ AU.addRequired(); -+ SelectionDAGISel::getAnalysisUsage(AU); -+} -+ -+bool LoongArchDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { -+ Subtarget = &static_cast(MF.getSubtarget()); -+ bool Ret = SelectionDAGISel::runOnMachineFunction(MF); -+ -+ return Ret; -+} -+ -+/// Match frameindex -+bool LoongArchDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { -+ EVT ValTy = Addr.getValueType(); -+ -+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); -+ Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); -+ return true; - } -- case ISD::FrameIndex: { -- SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT); -- int FI = cast(Node)->getIndex(); -- SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); -- unsigned ADDIOp = -- Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; -- ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm)); -- return; -+ return false; -+} -+ -+/// Match frameindex+offset and frameindex|offset -+bool LoongArchDAGToDAGISel::selectAddrFrameIndexOffset( -+ SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits, -+ unsigned ShiftAmount = 0) const { -+ if (CurDAG->isBaseWithConstantOffset(Addr)) { -+ ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)); -+ if (isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) { -+ EVT ValTy = Addr.getValueType(); -+ -+ // If the first operand is a FI, get the TargetFI Node -+ if (FrameIndexSDNode *FIN = -+ dyn_cast(Addr.getOperand(0))) -+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); -+ else { -+ Base = Addr.getOperand(0); -+ // If base is a FI, additional offset calculation is done in -+ // eliminateFrameIndex, otherwise we need to check the alignment -+ const Align Alignment(1ULL << ShiftAmount); -+ if (!isAligned(Alignment, CN->getZExtValue())) -+ return false; -+ } -+ -+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), -+ ValTy); -+ return true; -+ } - } -- // TODO: Add selection nodes needed later. -+ return false; -+} -+ -+/// ComplexPattern used on LoongArchInstrInfo -+/// Used on LoongArch Load/Store instructions -+bool LoongArchDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ // if Address is FI, get the TargetFrameIndex. -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (!TM.isPositionIndependent()) { -+ if ((Addr.getOpcode() == ISD::TargetExternalSymbol || -+ Addr.getOpcode() == ISD::TargetGlobalAddress)) -+ return false; - } - -- // Select the default instruction. -- SelectCode(Node); -+ // Addresses of the form FI+const or FI|const -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) -+ return true; -+ -+ return false; - } - --bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { -- // If this is FrameIndex, select it directly. Otherwise just let it get -- // selected to a register independently. -- if (auto *FIN = dyn_cast(Addr)) -- Base = -- CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT()); -- else -- Base = Addr; -+/// ComplexPattern used on LoongArchInstrInfo -+/// Used on LoongArch Load/Store instructions -+bool LoongArchDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ Base = Addr; -+ Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); - return true; - } - --bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, -- SDValue &ShAmt) { -- // Shift instructions on LoongArch only read the lower 5 or 6 bits of the -- // shift amount. If there is an AND on the shift amount, we can bypass it if -- // it doesn't affect any of those bits. -- if (N.getOpcode() == ISD::AND && isa(N.getOperand(1))) { -- const APInt &AndMask = N->getConstantOperandAPInt(1); -+bool LoongArchDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ return selectAddrRegImm(Addr, Base, Offset) || -+ selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) -+ return true; -+ -+ return false; -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm12(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; - -- // Since the max shift amount is a power of 2 we can subtract 1 to make a -- // mask that covers the bits needed to represent all shift amounts. -- assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); -- APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1); -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 1)) -+ return true; - -- if (ShMask.isSubsetOf(AndMask)) { -- ShAmt = N.getOperand(0); -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 2)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm11Lsl1(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11, 1)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm9Lsl3(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9, 3)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm14Lsl2(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 14, 2)) -+ return true; -+ -+ return false; -+} -+ -+bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const { -+ if (selectAddrFrameIndex(Addr, Base, Offset)) -+ return true; -+ -+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 3)) -+ return true; -+ -+ return selectAddrDefault(Addr, Base, Offset); -+} -+ -+// Select constant vector splats. -+// -+// Returns true and sets Imm if: -+// * LSX is enabled -+// * N is a ISD::BUILD_VECTOR representing a constant splat -+bool LoongArchDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, -+ unsigned MinSizeInBits) const { -+ if (!(Subtarget->hasLSX() || Subtarget->hasLASX())) -+ return false; -+ -+ BuildVectorSDNode *Node = dyn_cast(N); -+ -+ if (!Node) -+ return false; -+ -+ APInt SplatValue, SplatUndef; -+ unsigned SplatBitSize; -+ bool HasAnyUndefs; -+ -+ if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, -+ MinSizeInBits)) -+ return false; -+ -+ Imm = SplatValue; -+ -+ return true; -+} -+ -+// Select constant vector splats. -+// -+// In addition to the requirements of selectVSplat(), this function returns -+// true and sets Imm if: -+// * The splat value is the same width as the elements of the vector -+// * The splat value fits in an integer with the specified signed-ness and -+// width. -+// -+// This function looks through ISD::BITCAST nodes. -+// TODO: This might not be appropriate for big-endian LSX since BITCAST is -+// sometimes a shuffle in big-endian mode. -+// -+// It's worth noting that this function is not used as part of the selection -+// of [v/xv]ldi.[bhwd] since it does not permit using the wrong-typed -+// [v/xv]ldi.[bhwd] instruction to achieve the desired bit pattern. -+// [v/xv]ldi.[bhwd] is selected in LoongArchDAGToDAGISel::selectNode. -+bool LoongArchDAGToDAGISel::selectVSplatCommon(SDValue N, SDValue &Imm, -+ bool Signed, -+ unsigned ImmBitSize) const { -+ APInt ImmValue; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); -+ -+ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && -+ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { -+ -+ if ((Signed && ImmValue.isSignedIntN(ImmBitSize)) || -+ (!Signed && ImmValue.isIntN(ImmBitSize))) { -+ Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy); - return true; - } -+ } -+ -+ return false; -+} -+ -+// Select constant vector splats. -+bool LoongArchDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 1); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 2); -+} - -- // SimplifyDemandedBits may have optimized the mask so try restoring any -- // bits that are known zero. -- KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); -- if (ShMask.isSubsetOf(AndMask | Known.Zero)) { -- ShAmt = N.getOperand(0); -+bool LoongArchDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 3); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 4); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 5); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 6); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, false, 8); -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const { -+ return selectVSplatCommon(N, Imm, true, 5); -+} -+ -+// Select constant vector splats whose value is a power of 2. -+// -+// In addition to the requirements of selectVSplat(), this function returns -+// true and sets Imm if: -+// * The splat value is the same width as the elements of the vector -+// * The splat value is a power of two. -+// -+// This function looks through ISD::BITCAST nodes. -+// TODO: This might not be appropriate for big-endian LSX since BITCAST is -+// sometimes a shuffle in big-endian mode. -+bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N, -+ SDValue &Imm) const { -+ APInt ImmValue; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); -+ -+ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && -+ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { -+ int32_t Log2 = ImmValue.exactLogBase2(); -+ -+ if (Log2 != -1) { -+ Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); - return true; - } -- } else if (N.getOpcode() == LoongArchISD::BSTRPICK) { -- // Similar to the above AND, if there is a BSTRPICK on the shift amount, we -- // can bypass it. -- assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); -- assert(isa(N.getOperand(1)) && "Illegal msb operand!"); -- assert(isa(N.getOperand(2)) && "Illegal lsb operand!"); -- uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2); -- if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) { -- ShAmt = N.getOperand(0); -+ } -+ -+ return false; -+} -+ -+bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, -+ SDValue &Imm) const { -+ APInt ImmValue; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); -+ -+ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && -+ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { -+ int32_t Log2 = (~ImmValue).exactLogBase2(); -+ -+ if (Log2 != -1) { -+ Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); - return true; - } -- } else if (N.getOpcode() == ISD::SUB && -- isa(N.getOperand(0))) { -- uint64_t Imm = N.getConstantOperandVal(0); -- // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to -- // generate a NEG instead of a SUB of a constant. -- if (Imm != 0 && Imm % ShiftWidth == 0) { -- SDLoc DL(N); -- EVT VT = N.getValueType(); -- SDValue Zero = -- CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT); -- unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W; -- MachineSDNode *Neg = -- CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1)); -- ShAmt = SDValue(Neg, 0); -+ } -+ -+ return false; -+} -+ -+// Select constant vector splats whose value only has a consecutive sequence -+// of left-most bits set (e.g. 0b11...1100...00). -+// -+// In addition to the requirements of selectVSplat(), this function returns -+// true and sets Imm if: -+// * The splat value is the same width as the elements of the vector -+// * The splat value is a consecutive sequence of left-most bits. -+// -+// This function looks through ISD::BITCAST nodes. -+// TODO: This might not be appropriate for big-endian LSX since BITCAST is -+// sometimes a shuffle in big-endian mode. -+bool LoongArchDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { -+ APInt ImmValue; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); -+ -+ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && -+ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { -+ // Extract the run of set bits starting with bit zero from the bitwise -+ // inverse of ImmValue, and test that the inverse of this is the same -+ // as the original value. -+ if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { -+ -+ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), -+ EltTy); - return true; - } - } - -- ShAmt = N; -- return true; -+ return false; - } - --bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { -- if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && -- cast(N.getOperand(1))->getVT() == MVT::i32) { -- Val = N.getOperand(0); -- return true; -- } -- MVT VT = N.getSimpleValueType(); -- if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) { -- Val = N; -- return true; -+// Select constant vector splats whose value only has a consecutive sequence -+// of right-most bits set (e.g. 0b00...0011...11). -+// -+// In addition to the requirements of selectVSplat(), this function returns -+// true and sets Imm if: -+// * The splat value is the same width as the elements of the vector -+// * The splat value is a consecutive sequence of right-most bits. -+// -+// This function looks through ISD::BITCAST nodes. -+// TODO: This might not be appropriate for big-endian LSX since BITCAST is -+// sometimes a shuffle in big-endian mode. -+bool LoongArchDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { -+ APInt ImmValue; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); -+ -+ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && -+ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { -+ // Extract the run of set bits starting with bit zero, and test that the -+ // result is the same as the original value -+ if (ImmValue == (ImmValue & ~(ImmValue + 1))) { -+ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), -+ EltTy); -+ return true; -+ } - } - - return false; - } - --bool LoongArchDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { -- if (N.getOpcode() == ISD::AND) { -- auto *C = dyn_cast(N.getOperand(1)); -- if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) { -- Val = N.getOperand(0); -+bool LoongArchDAGToDAGISel::trySelect(SDNode *Node) { -+ unsigned Opcode = Node->getOpcode(); -+ SDLoc DL(Node); -+ -+ /// -+ // Instruction Selection not handled by the auto-generated -+ // tablegen selection should be handled here. -+ /// -+ switch(Opcode) { -+ default: break; -+ case ISD::ConstantFP: { -+ ConstantFPSDNode *CN = dyn_cast(Node); -+ if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { -+ if (Subtarget->is64Bit()) { -+ SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, -+ LoongArch::ZERO_64, MVT::i64); -+ ReplaceNode(Node, -+ CurDAG->getMachineNode(LoongArch::MOVGR2FR_D, DL, MVT::f64, Zero)); -+ } - return true; - } -+ break; - } -- MVT VT = N.getSimpleValueType(); -- APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 32); -- if (CurDAG->MaskedValueIsZero(N, Mask)) { -- Val = N; -+ -+ case ISD::Constant: { -+ const ConstantSDNode *CN = dyn_cast(Node); -+ MVT VT = CN->getSimpleValueType(0); -+ int64_t Imm = CN->getSExtValue(); -+ LoongArchAnalyzeImmediate::InstSeq Seq = -+ LoongArchAnalyzeImmediate::generateInstSeq(Imm, VT == MVT::i64); -+ SDLoc DL(CN); -+ SDNode *Result = nullptr; -+ SDValue SrcReg = CurDAG->getRegister( -+ VT == MVT::i64 ? LoongArch::ZERO_64 : LoongArch::ZERO, VT); -+ -+ // The instructions in the sequence are handled here. -+ for (LoongArchAnalyzeImmediate::Inst &Inst : Seq) { -+ SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, VT); -+ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) -+ Result = CurDAG->getMachineNode(Inst.Opc, DL, VT, SDImm); -+ else -+ Result = CurDAG->getMachineNode(Inst.Opc, DL, VT, SrcReg, SDImm); -+ SrcReg = SDValue(Result, 0); -+ } -+ ReplaceNode(Node, Result); - return true; - } - -+ case ISD::BUILD_VECTOR: { -+ // Select appropriate vldi.[bhwd] instructions for constant splats of -+ // 128-bit when LSX is enabled. Select appropriate xvldi.[bhwd] instructions -+ // for constant splats of 256-bit when LASX is enabled. Fixup any register -+ // class mismatches that occur as a result. -+ // -+ // This allows the compiler to use a wider range of immediates than would -+ // otherwise be allowed. If, for example, v4i32 could only use [v/xv]ldi.h -+ // then it would not be possible to load { 0x01010101, 0x01010101, -+ // 0x01010101, 0x01010101 } without using a constant pool. This would be -+ // sub-optimal when // '[v/xv]ldi.b vd, 1' is capable of producing that -+ // bit-pattern in the same set/ of registers. Similarly, [v/xv]ldi.h isn't -+ // capable of producing { 0x00000000, 0x00000001, 0x00000000, 0x00000001 } -+ // but '[v/xv]ldi.d vd, 1' can. -+ -+ const LoongArchABIInfo &ABI = -+ static_cast(TM).getABI(); -+ -+ BuildVectorSDNode *BVN = cast(Node); -+ APInt SplatValue, SplatUndef; -+ unsigned SplatBitSize; -+ bool HasAnyUndefs; -+ unsigned LdiOp; -+ EVT ResVecTy = BVN->getValueType(0); -+ EVT ViaVecTy; -+ -+ if ((!Subtarget->hasLSX() || !BVN->getValueType(0).is128BitVector()) && -+ (!Subtarget->hasLASX() || !BVN->getValueType(0).is256BitVector())) -+ return false; -+ -+ if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, -+ HasAnyUndefs, 8)) -+ return false; -+ -+ bool IsLASX256 = BVN->getValueType(0).is256BitVector(); -+ -+ switch (SplatBitSize) { -+ default: -+ return false; -+ case 8: -+ LdiOp = IsLASX256 ? LoongArch::XVLDI_B : LoongArch::VLDI_B; -+ ViaVecTy = IsLASX256 ? MVT::v32i8 : MVT::v16i8; -+ break; -+ case 16: -+ LdiOp = IsLASX256 ? LoongArch::XVLDI_H : LoongArch::VLDI_H; -+ ViaVecTy = IsLASX256 ? MVT::v16i16 : MVT::v8i16; -+ break; -+ case 32: -+ LdiOp = IsLASX256 ? LoongArch::XVLDI_W : LoongArch::VLDI_W; -+ ViaVecTy = IsLASX256 ? MVT::v8i32 : MVT::v4i32; -+ break; -+ case 64: -+ LdiOp = IsLASX256 ? LoongArch::XVLDI_D : LoongArch::VLDI_D; -+ ViaVecTy = IsLASX256 ? MVT::v4i64 : MVT::v2i64; -+ break; -+ } -+ -+ SDNode *Res; -+ -+ // If we have a signed 13 bit integer, we can splat it directly. -+ // -+ // If we have something bigger we can synthesize the value into a GPR and -+ // splat from there. -+ if (SplatValue.isSignedIntN(10)) { -+ SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, -+ ViaVecTy.getVectorElementType()); -+ -+ Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); -+ } else if (SplatValue.isSignedIntN(12)) { -+ bool Is32BitSplat = SplatBitSize < 64 ? true : false; -+ const unsigned ADDIOp = -+ Is32BitSplat ? LoongArch::ADDI_W : LoongArch::ADDI_D; -+ const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; -+ SDValue ZeroVal = CurDAG->getRegister( -+ Is32BitSplat ? LoongArch::ZERO : LoongArch::ZERO_64, SplatMVT); -+ -+ const unsigned FILLOp = -+ (SplatBitSize == 16) -+ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_H : LoongArch::VREPLGR2VR_H) -+ : (SplatBitSize == 32 -+ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_W -+ : LoongArch::VREPLGR2VR_W) -+ : (SplatBitSize == 64 -+ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_D -+ : LoongArch::VREPLGR2VR_D) -+ : 0)); -+ -+ assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!"); -+ -+ short Lo = SplatValue.getLoBits(12).getSExtValue(); -+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT); -+ -+ Res = CurDAG->getMachineNode(ADDIOp, DL, SplatMVT, ZeroVal, LoVal); -+ Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0)); -+ } else if (SplatValue.isSignedIntN(16) && SplatBitSize == 16) { -+ const unsigned Lo = SplatValue.getLoBits(12).getZExtValue(); -+ const unsigned Hi = SplatValue.lshr(12).getLoBits(4).getZExtValue(); -+ SDValue ZeroVal = CurDAG->getRegister(LoongArch::ZERO, MVT::i32); -+ -+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); -+ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); -+ if (Hi) -+ Res = CurDAG->getMachineNode(LoongArch::LU12I_W32, DL, MVT::i32, HiVal); -+ -+ if (Lo) -+ Res = CurDAG->getMachineNode(LoongArch::ORI32, DL, MVT::i32, -+ Hi ? SDValue(Res, 0) : ZeroVal, LoVal); -+ -+ assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); -+ const unsigned FILLOp = -+ IsLASX256 ? LoongArch::XVREPLGR2VR_H : LoongArch::VREPLGR2VR_H; -+ EVT FILLTy = IsLASX256 ? MVT::v16i16 : MVT::v8i16; -+ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); -+ } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) { -+ // Only handle the cases where the splat size agrees with the size -+ // of the SplatValue here. -+ const unsigned Lo = SplatValue.getLoBits(12).getZExtValue(); -+ const unsigned Hi = SplatValue.lshr(12).getLoBits(20).getZExtValue(); -+ SDValue ZeroVal = CurDAG->getRegister(LoongArch::ZERO, MVT::i32); -+ -+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); -+ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); -+ if (Hi) -+ Res = CurDAG->getMachineNode(LoongArch::LU12I_W32, DL, MVT::i32, HiVal); -+ -+ if (Lo) -+ Res = CurDAG->getMachineNode(LoongArch::ORI32, DL, MVT::i32, -+ Hi ? SDValue(Res, 0) : ZeroVal, LoVal); -+ -+ assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); -+ const unsigned FILLOp = -+ IsLASX256 ? LoongArch::XVREPLGR2VR_W : LoongArch::VREPLGR2VR_W; -+ EVT FILLTy = IsLASX256 ? MVT::v8i32 : MVT::v4i32; -+ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); -+ -+ } else if ((SplatValue.isSignedIntN(32) && SplatBitSize == 64 && -+ ABI.IsLP64()) || -+ (SplatValue.isSignedIntN(64))) { -+ -+ int64_t Imm = SplatValue.getSExtValue(); -+ LoongArchAnalyzeImmediate::InstSeq Seq = -+ LoongArchAnalyzeImmediate::generateInstSeq(Imm, true); -+ SDValue SrcReg = CurDAG->getRegister(LoongArch::ZERO_64, MVT::i64); -+ -+ for (LoongArchAnalyzeImmediate::Inst &Inst : Seq) { -+ SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, MVT::i64); -+ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) -+ Res = CurDAG->getMachineNode(Inst.Opc, DL, MVT::i64, SDImm); -+ else -+ Res = CurDAG->getMachineNode(Inst.Opc, DL, MVT::i64, SrcReg, SDImm); -+ SrcReg = SDValue(Res, 0); -+ } -+ -+ const unsigned FILLOp = -+ IsLASX256 ? LoongArch::XVREPLGR2VR_D : LoongArch::VREPLGR2VR_D; -+ EVT FILLTy = IsLASX256 ? MVT::v4i64 : MVT::v2i64; -+ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); -+ -+ } else -+ return false; -+ -+ if (ResVecTy != ViaVecTy) { -+ // If LdiOp is writing to a different register class to ResVecTy, then -+ // fix it up here. This COPY_TO_REGCLASS should never cause a move.v -+ // since the source and destination register sets contain the same -+ // registers. -+ const TargetLowering *TLI = getTargetLowering(); -+ MVT ResVecTySimple = ResVecTy.getSimpleVT(); -+ const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple); -+ Res = CurDAG->getMachineNode( -+ LoongArch::COPY_TO_REGCLASS, DL, ResVecTy, SDValue(Res, 0), -+ CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); -+ } -+ -+ ReplaceNode(Node, Res); -+ return true; -+ } -+ } -+ - return false; - } - --// This pass converts a legalized DAG into a LoongArch-specific DAG, ready --// for instruction scheduling. --FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { -- return new LoongArchDAGToDAGISel(TM); -+/// Select instructions not customized! Used for -+/// expanded, promoted and normal instructions -+void LoongArchDAGToDAGISel::Select(SDNode *Node) { -+ // If we have a custom node, we already have selected! -+ if (Node->isMachineOpcode()) { -+ LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); -+ Node->setNodeId(-1); -+ return; -+ } -+ -+ // See if subclasses can handle this node. -+ if (trySelect(Node)) -+ return; -+ -+ // Select the default instruction -+ SelectCode(Node); -+} -+ -+bool LoongArchDAGToDAGISel:: -+SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, -+ std::vector &OutOps) { -+ SDValue Base, Offset; -+ -+ switch(ConstraintID) { -+ default: -+ llvm_unreachable("Unexpected asm memory constraint"); -+ // All memory constraints can at least accept raw pointers. -+ case InlineAsm::Constraint_i: -+ OutOps.push_back(Op); -+ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); -+ return false; -+ case InlineAsm::Constraint_m: -+ if (selectAddrRegImm12(Op, Base, Offset)) { -+ OutOps.push_back(Base); -+ OutOps.push_back(Offset); -+ return false; -+ } -+ OutOps.push_back(Op); -+ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); -+ return false; -+ case InlineAsm::Constraint_R: -+ if (selectAddrRegImm12(Op, Base, Offset)) { -+ OutOps.push_back(Base); -+ OutOps.push_back(Offset); -+ return false; -+ } -+ OutOps.push_back(Op); -+ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); -+ return false; -+ case InlineAsm::Constraint_ZC: -+ if (selectIntAddrSImm14Lsl2(Op, Base, Offset)) { -+ OutOps.push_back(Base); -+ OutOps.push_back(Offset); -+ return false; -+ } -+ OutOps.push_back(Op); -+ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); -+ return false; -+ case InlineAsm::Constraint_ZB: -+ OutOps.push_back(Op); -+ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); -+ return false; -+ } -+ return true; -+} -+ -+// This optimisation is ported from RISCV. -+// Merge an ADDI into the offset of a load/store instruction where possible. -+// (load (addi base, off1), off2) -> (load base, off1+off2) -+// (store val, (addi base, off1), off2) -> (store val, base, off1+off2) -+// This is possible when off1+off2 fits a 12-bit immediate. -+void LoongArchDAGToDAGISel::doPeepholeLoadStoreADDI() { -+ SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); -+ ++Position; -+ -+ while (Position != CurDAG->allnodes_begin()) { -+ SDNode *N = &*--Position; -+ // Skip dead nodes and any non-machine opcodes. -+ if (N->use_empty() || !N->isMachineOpcode()) -+ continue; -+ -+ int OffsetOpIdx; -+ int BaseOpIdx; -+ -+ // TODO: handle more instructions. -+ switch (N->getMachineOpcode()) { -+ default: -+ continue; -+ case LoongArch::LD_B: -+ case LoongArch::LD_B32: -+ case LoongArch::LD_BU: -+ case LoongArch::LD_BU32: -+ case LoongArch::LD_H: -+ case LoongArch::LD_H32: -+ case LoongArch::LD_HU: -+ case LoongArch::LD_HU32: -+ case LoongArch::LD_W: -+ case LoongArch::LD_W32: -+ case LoongArch::LD_WU: -+ case LoongArch::LD_D: -+ BaseOpIdx = 0; -+ OffsetOpIdx = 1; -+ break; -+ case LoongArch::ST_B: -+ case LoongArch::ST_B32: -+ case LoongArch::ST_H: -+ case LoongArch::ST_H32: -+ case LoongArch::ST_W: -+ case LoongArch::ST_W32: -+ case LoongArch::ST_D: -+ BaseOpIdx = 1; -+ OffsetOpIdx = 2; -+ break; -+ } -+ -+ if (!isa(N->getOperand(OffsetOpIdx))) -+ continue; -+ -+ SDValue Base = N->getOperand(BaseOpIdx); -+ -+ // If the base is an ADDI, we can merge it in to the load/store. -+ // TODO: handle more instructions, i.e. ADDI_W. -+ if (!Base.isMachineOpcode() || Base.getMachineOpcode() != LoongArch::ADDI_D) -+ continue; -+ -+ SDValue ImmOperand = Base.getOperand(1); -+ uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); -+ -+ if (auto *Const = dyn_cast(ImmOperand)) { -+ int64_t Offset1 = Const->getSExtValue(); -+ int64_t CombinedOffset = Offset1 + Offset2; -+ if (!isInt<12>(CombinedOffset)) -+ continue; -+ ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand), -+ ImmOperand.getValueType()); -+ // TODO: handle below cases. -+#if 0 -+ } else if (auto *GA = dyn_cast(ImmOperand)) { -+ // If the off1 in (addi base, off1) is a global variable's address (its -+ // low part, really), then we can rely on the alignment of that variable -+ // to provide a margin of safety before off1 can overflow the 12 bits. -+ // Check if off2 falls within that margin; if so off1+off2 can't overflow. -+ const DataLayout &DL = CurDAG->getDataLayout(); -+ Align Alignment = GA->getGlobal()->getPointerAlignment(DL); -+ if (Offset2 != 0 && Alignment <= Offset2) -+ continue; -+ int64_t Offset1 = GA->getOffset(); -+ int64_t CombinedOffset = Offset1 + Offset2; -+ ImmOperand = CurDAG->getTargetGlobalAddress( -+ GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(), -+ CombinedOffset, GA->getTargetFlags()); -+ } else if (auto *CP = dyn_cast(ImmOperand)) { -+ // Ditto. -+ Align Alignment = CP->getAlign(); -+ if (Offset2 != 0 && Alignment <= Offset2) -+ continue; -+ int64_t Offset1 = CP->getOffset(); -+ int64_t CombinedOffset = Offset1 + Offset2; -+ ImmOperand = CurDAG->getTargetConstantPool( -+ CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(), -+ CombinedOffset, CP->getTargetFlags()); -+#endif -+ } else { -+ continue; -+ } -+ -+ LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); -+ LLVM_DEBUG(Base->dump(CurDAG)); -+ LLVM_DEBUG(dbgs() << "\nN: "); -+ LLVM_DEBUG(N->dump(CurDAG)); -+ LLVM_DEBUG(dbgs() << "\n"); -+ -+ // Modify the offset operand of the load/store. -+ if (BaseOpIdx == 0) // Load -+ CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, -+ N->getOperand(2)); -+ else // Store -+ CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), -+ ImmOperand, N->getOperand(3)); -+ -+ // The add-immediate may now be dead, in which case remove it. -+ if (Base.getNode()->use_empty()) -+ CurDAG->RemoveDeadNode(Base.getNode()); -+ } -+} -+ -+FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM, -+ CodeGenOpt::Level OptLevel) { -+ return new LoongArchDAGToDAGISel(TM, OptLevel); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h -index 8c9357d75..765497318 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h -@@ -1,4 +1,4 @@ --//=- LoongArchISelDAGToDAG.h - A dag to dag inst selector for LoongArch ---===// -+//===---- LoongArchISelDAGToDAG.h - A Dag to Dag Inst Selector for LoongArch --------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -14,47 +14,138 @@ - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H - - #include "LoongArch.h" -+#include "LoongArchSubtarget.h" - #include "LoongArchTargetMachine.h" - #include "llvm/CodeGen/SelectionDAGISel.h" - --// LoongArch-specific code to select LoongArch machine instructions for --// SelectionDAG operations. -+//===----------------------------------------------------------------------===// -+// Instruction Selector Implementation -+//===----------------------------------------------------------------------===// -+ -+//===----------------------------------------------------------------------===// -+// LoongArchDAGToDAGISel - LoongArch specific code to select LoongArch machine -+// instructions for SelectionDAG operations. -+//===----------------------------------------------------------------------===// - namespace llvm { --class LoongArchDAGToDAGISel : public SelectionDAGISel { -- const LoongArchSubtarget *Subtarget = nullptr; - -+class LoongArchDAGToDAGISel : public SelectionDAGISel { - public: -- explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM) -- : SelectionDAGISel(TM) {} -+ explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM, CodeGenOpt::Level OL) -+ : SelectionDAGISel(TM, OL), Subtarget(nullptr) {} - -+ // Pass Name - StringRef getPassName() const override { - return "LoongArch DAG->DAG Pattern Instruction Selection"; - } - -- bool runOnMachineFunction(MachineFunction &MF) override { -- Subtarget = &MF.getSubtarget(); -- return SelectionDAGISel::runOnMachineFunction(MF); -- } -+ bool runOnMachineFunction(MachineFunction &MF) override; - -- void Select(SDNode *Node) override; -+ void PostprocessISelDAG() override; - -- bool SelectBaseAddr(SDValue Addr, SDValue &Base); -+ void getAnalysisUsage(AnalysisUsage &AU) const override; - -- bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); -- bool selectShiftMaskGRLen(SDValue N, SDValue &ShAmt) { -- return selectShiftMask(N, Subtarget->getGRLen(), ShAmt); -- } -- bool selectShiftMask32(SDValue N, SDValue &ShAmt) { -- return selectShiftMask(N, 32, ShAmt); -- } -+private: -+ /// Keep a pointer to the LoongArchSubtarget around so that we can make the right -+ /// decision when generating code for different targets. -+ const LoongArchSubtarget *Subtarget; -+ // Include the pieces autogenerated from the target description. -+ #include "LoongArchGenDAGISel.inc" -+ -+ void doPeepholeLoadStoreADDI(); -+ -+ bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const; -+ -+ bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, -+ unsigned OffsetBits, -+ unsigned ShiftAmount) const; -+ -+ // Complex Pattern. -+ /// (reg + imm). -+ bool selectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) const; -+ -+ /// Fall back on this function if all else fails. -+ bool selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const; - -- bool selectSExti32(SDValue N, SDValue &Val); -- bool selectZExti32(SDValue N, SDValue &Val); -+ /// Match integer address pattern. -+ bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const; -+ -+ bool selectAddrRegImm12(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ /// Match addr+simm12 and addr -+ bool selectIntAddrSImm12(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm10(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm9Lsl3(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm11Lsl1(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm14Lsl2(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ bool selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, -+ SDValue &Offset) const; -+ -+ /// Select constant vector splats. -+ bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const; -+ /// Select constant vector splats whose value fits in a given integer. -+ bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, -+ unsigned ImmBitSize) const; -+ /// Select constant vector splats whose value fits in a uimm1. -+ bool selectVSplatUimm1(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm2. -+ bool selectVSplatUimm2(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm3. -+ bool selectVSplatUimm3(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm4. -+ bool selectVSplatUimm4(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm5. -+ bool selectVSplatUimm5(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm6. -+ bool selectVSplatUimm6(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a uimm8. -+ bool selectVSplatUimm8(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value fits in a simm5. -+ bool selectVSplatSimm5(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value is a power of 2. -+ bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value is the inverse of a -+ /// power of 2. -+ bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value is a run of set bits -+ /// ending at the most significant bit -+ bool selectVSplatMaskL(SDValue N, SDValue &Imm) const; -+ /// Select constant vector splats whose value is a run of set bits -+ /// starting at bit zero. -+ bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; -+ -+ void Select(SDNode *N) override; -+ -+ bool trySelect(SDNode *Node); -+ -+ // getImm - Return a target constant with the specified value. -+ inline SDValue getImm(const SDNode *Node, uint64_t Imm) { -+ return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0)); -+ } - --// Include the pieces autogenerated from the target description. --#include "LoongArchGenDAGISel.inc" -+ bool SelectInlineAsmMemoryOperand(const SDValue &Op, -+ unsigned ConstraintID, -+ std::vector &OutOps) override; - }; - --} // end namespace llvm -+FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM, -+ CodeGenOpt::Level OptLevel); -+} - --#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp -index 93c886434..6b258813b 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp -@@ -1,4 +1,4 @@ --//=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ---===// -+//===- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,1094 +6,8213 @@ - // - //===----------------------------------------------------------------------===// - // --// This file defines the interfaces that LoongArch uses to lower LLVM code into --// a selection DAG. -+// This file defines the interfaces that LoongArch uses to lower LLVM code into a -+// selection DAG. - // - //===----------------------------------------------------------------------===// - - #include "LoongArchISelLowering.h" --#include "LoongArch.h" --#include "LoongArchMachineFunctionInfo.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchInstPrinter.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "LoongArchCCState.h" -+#include "LoongArchInstrInfo.h" -+#include "LoongArchMachineFunction.h" - #include "LoongArchRegisterInfo.h" - #include "LoongArchSubtarget.h" - #include "LoongArchTargetMachine.h" --#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "LoongArchTargetObjectFile.h" -+#include "llvm/ADT/APFloat.h" -+#include "llvm/ADT/APInt.h" -+#include "llvm/ADT/ArrayRef.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/ADT/SmallVector.h" - #include "llvm/ADT/Statistic.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/ADT/StringSwitch.h" -+#include "llvm/ADT/Triple.h" -+#include "llvm/CodeGen/CallingConvLower.h" -+#include "llvm/CodeGen/FunctionLoweringInfo.h" - #include "llvm/CodeGen/ISDOpcodes.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" -+#include "llvm/CodeGen/MachineFrameInfo.h" -+#include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineInstr.h" -+#include "llvm/CodeGen/MachineInstrBuilder.h" -+#include "llvm/CodeGen/MachineJumpTableInfo.h" -+#include "llvm/CodeGen/MachineMemOperand.h" -+#include "llvm/CodeGen/MachineOperand.h" -+#include "llvm/CodeGen/MachineRegisterInfo.h" -+#include "llvm/CodeGen/RuntimeLibcalls.h" -+#include "llvm/CodeGen/SelectionDAG.h" -+#include "llvm/CodeGen/SelectionDAGNodes.h" -+#include "llvm/CodeGen/TargetFrameLowering.h" -+#include "llvm/CodeGen/TargetInstrInfo.h" -+#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "llvm/CodeGen/TargetSubtargetInfo.h" -+#include "llvm/CodeGen/ValueTypes.h" -+#include "llvm/IR/CallingConv.h" -+#include "llvm/IR/Constants.h" -+#include "llvm/IR/DataLayout.h" -+#include "llvm/IR/DebugLoc.h" -+#include "llvm/IR/DerivedTypes.h" -+#include "llvm/IR/Function.h" -+#include "llvm/IR/GlobalValue.h" -+#include "llvm/IR/Intrinsics.h" -+#include "llvm/IR/IntrinsicsLoongArch.h" -+#include "llvm/IR/Type.h" -+#include "llvm/IR/Value.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCRegisterInfo.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/CodeGen.h" -+#include "llvm/Support/CommandLine.h" -+#include "llvm/Support/Compiler.h" - #include "llvm/Support/Debug.h" --#include "llvm/Support/KnownBits.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MachineValueType.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Support/raw_ostream.h" -+#include "llvm/Target/TargetMachine.h" -+#include "llvm/Target/TargetOptions.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - - using namespace llvm; - --#define DEBUG_TYPE "loongarch-isel-lowering" -+#define DEBUG_TYPE "loongarch-lower" - --static cl::opt ZeroDivCheck( -- "loongarch-check-zero-division", cl::Hidden, -- cl::desc("Trap on integer division by zero."), -- cl::init(false)); -+STATISTIC(NumTailCalls, "Number of tail calls"); - --LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, -- const LoongArchSubtarget &STI) -- : TargetLowering(TM), Subtarget(STI) { -+static cl::opt -+NoZeroDivCheck("mnocheck-zero-division", cl::Hidden, -+ cl::desc("LoongArch: Don't trap on integer division by zero."), -+ cl::init(false)); - -- MVT GRLenVT = Subtarget.getGRLenVT(); -- // Set up the register classes. -- addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); -- if (Subtarget.hasBasicF()) -- addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass); -- if (Subtarget.hasBasicD()) -- addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass); -+static const MCPhysReg LoongArch64DPRegs[8] = { -+ LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, -+ LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64 -+}; - -- setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT, -- MVT::i1, Promote); -+// If I is a shifted mask, set the size (SMSize) and the first bit of the -+// mask (SMLsb), and return true. -+// For example, if I is 0x003ff800, (SMLsb, SMSize) = (11, 11). -+static bool isShiftedMask(uint64_t I, uint64_t &SMLsb, uint64_t &SMSize) { -+ if (!isShiftedMask_64(I)) -+ return false; - -- // TODO: add necessary setOperationAction calls later. -- setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); -- setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); -- setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); -- setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); -+ SMSize = countPopulation(I); -+ SMLsb = countTrailingZeros(I); -+ return true; -+} - -- setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); -+SDValue LoongArchTargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty, -+ SelectionDAG &DAG, -+ unsigned Flag) const { -+ return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty, 0, Flag); -+} - -- if (Subtarget.is64Bit()) { -- setOperationAction(ISD::SHL, MVT::i32, Custom); -- setOperationAction(ISD::SRA, MVT::i32, Custom); -- setOperationAction(ISD::SRL, MVT::i32, Custom); -- setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); -- setOperationAction(ISD::BITCAST, MVT::i32, Custom); -- if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) -- setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); -+SDValue LoongArchTargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty, -+ SelectionDAG &DAG, -+ unsigned Flag) const { -+ return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag); -+} -+ -+SDValue LoongArchTargetLowering::getTargetNode(BlockAddressSDNode *N, EVT Ty, -+ SelectionDAG &DAG, -+ unsigned Flag) const { -+ return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(), Flag); -+} -+ -+SDValue LoongArchTargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty, -+ SelectionDAG &DAG, -+ unsigned Flag) const { -+ return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag); -+} -+ -+SDValue LoongArchTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, -+ SelectionDAG &DAG, -+ unsigned Flag) const { -+ return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(), -+ N->getOffset(), Flag); -+} -+ -+const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { -+ switch ((LoongArchISD::NodeType)Opcode) { -+ case LoongArchISD::FIRST_NUMBER: break; -+ case LoongArchISD::JmpLink: return "LoongArchISD::JmpLink"; -+ case LoongArchISD::TailCall: return "LoongArchISD::TailCall"; -+ case LoongArchISD::GlobalAddress: return "LoongArchISD::GlobalAddress"; -+ case LoongArchISD::Ret: return "LoongArchISD::Ret"; -+ case LoongArchISD::ERet: return "LoongArchISD::ERet"; -+ case LoongArchISD::EH_RETURN: return "LoongArchISD::EH_RETURN"; -+ case LoongArchISD::FPBrcond: return "LoongArchISD::FPBrcond"; -+ case LoongArchISD::FPCmp: return "LoongArchISD::FPCmp"; -+ case LoongArchISD::CMovFP_T: return "LoongArchISD::CMovFP_T"; -+ case LoongArchISD::CMovFP_F: return "LoongArchISD::CMovFP_F"; -+ case LoongArchISD::TruncIntFP: return "LoongArchISD::TruncIntFP"; -+ case LoongArchISD::DBAR: return "LoongArchISD::DBAR"; -+ case LoongArchISD::BSTRPICK: return "LoongArchISD::BSTRPICK"; -+ case LoongArchISD::BSTRINS: return "LoongArchISD::BSTRINS"; -+ case LoongArchISD::VALL_ZERO: -+ return "LoongArchISD::VALL_ZERO"; -+ case LoongArchISD::VANY_ZERO: -+ return "LoongArchISD::VANY_ZERO"; -+ case LoongArchISD::VALL_NONZERO: -+ return "LoongArchISD::VALL_NONZERO"; -+ case LoongArchISD::VANY_NONZERO: -+ return "LoongArchISD::VANY_NONZERO"; -+ case LoongArchISD::VEXTRACT_SEXT_ELT: -+ return "LoongArchISD::VEXTRACT_SEXT_ELT"; -+ case LoongArchISD::VEXTRACT_ZEXT_ELT: -+ return "LoongArchISD::VEXTRACT_ZEXT_ELT"; -+ case LoongArchISD::VNOR: -+ return "LoongArchISD::VNOR"; -+ case LoongArchISD::VSHF: -+ return "LoongArchISD::VSHF"; -+ case LoongArchISD::SHF: -+ return "LoongArchISD::SHF"; -+ case LoongArchISD::VPACKEV: -+ return "LoongArchISD::VPACKEV"; -+ case LoongArchISD::VPACKOD: -+ return "LoongArchISD::VPACKOD"; -+ case LoongArchISD::VILVH: -+ return "LoongArchISD::VILVH"; -+ case LoongArchISD::VILVL: -+ return "LoongArchISD::VILVL"; -+ case LoongArchISD::VPICKEV: -+ return "LoongArchISD::VPICKEV"; -+ case LoongArchISD::VPICKOD: -+ return "LoongArchISD::VPICKOD"; -+ case LoongArchISD::INSVE: -+ return "LoongArchISD::INSVE"; -+ case LoongArchISD::VROR: -+ return "LoongArchISD::VROR"; -+ case LoongArchISD::VRORI: -+ return "LoongArchISD::VRORI"; -+ case LoongArchISD::XVBROADCAST: -+ return "LoongArchISD::XVBROADCAST"; -+ case LoongArchISD::VBROADCAST: -+ return "LoongArchISD::VBROADCAST"; -+ case LoongArchISD::VABSD: -+ return "LoongArchISD::VABSD"; -+ case LoongArchISD::UVABSD: -+ return "LoongArchISD::UVABSD"; -+ case LoongArchISD::XVPICKVE: -+ return "LoongArchISD::XVPICKVE"; -+ case LoongArchISD::XVPERMI: -+ return "LoongArchISD::XVPERMI"; -+ case LoongArchISD::XVSHUF4I: -+ return "LoongArchISD::XVSHUF4I"; -+ case LoongArchISD::REVBD: -+ return "LoongArchISD::REVBD"; -+ case LoongArchISD::FSEL: -+ return "LoongArchISD::FSEL"; - } -+ return nullptr; -+} -+ -+LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &TM, -+ const LoongArchSubtarget &STI) -+ : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { -+ // Set up the register classes -+ addRegisterClass(MVT::i32, &LoongArch::GPR32RegClass); - -- static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE, -- ISD::SETUGT, ISD::SETUGE}; -+ if (Subtarget.is64Bit()) -+ addRegisterClass(MVT::i64, &LoongArch::GPR64RegClass); - -- if (Subtarget.hasBasicF()) { -- setCondCodeAction(FPCCToExpand, MVT::f32, Expand); -- setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); -+ // LoongArch does not have i1 type, so use i32 for -+ // setcc operations results (slt, sgt, ...). -+ setBooleanContents(ZeroOrOneBooleanContent); -+ setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); -+ -+ // Load extented operations for i1 types must be promoted -+ for (MVT VT : MVT::integer_valuetypes()) { -+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); -+ setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); -+ setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); - } -- if (Subtarget.hasBasicD()) { -- setCondCodeAction(FPCCToExpand, MVT::f64, Expand); -- setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); -- setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); -- setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); -+ -+ // LoongArch doesn't have extending float->double load/store. Set LoadExtAction -+ // for f32, f16 -+ for (MVT VT : MVT::fp_valuetypes()) { -+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); -+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); - } - -- setOperationAction(ISD::BR_CC, GRLenVT, Expand); -- setOperationAction(ISD::SELECT_CC, GRLenVT, Expand); -- setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); -- setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, GRLenVT, Expand); -- if (!Subtarget.is64Bit()) -- setLibcallName(RTLIB::MUL_I128, nullptr); -+ // Set LoadExtAction for f16 vectors to Expand -+ for (MVT VT : MVT::fp_fixedlen_vector_valuetypes()) { -+ MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements()); -+ if (F16VT.isValid()) -+ setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand); -+ } - -- setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom); -- setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom); -+ setTruncStoreAction(MVT::f32, MVT::f16, Expand); -+ setTruncStoreAction(MVT::f64, MVT::f16, Expand); -+ -+ setTruncStoreAction(MVT::f64, MVT::f32, Expand); -+ -+ // Used by legalize types to correctly generate the setcc result. -+ // Without this, every float setcc comes with a AND/OR with the result, -+ // we don't want this, since the fpcmp result goes to a flag register, -+ // which is used implicitly by brcond and select operations. -+ AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); -+ -+ // LoongArch Custom Operations -+ setOperationAction(ISD::BR_JT, MVT::Other, Expand); -+ setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); -+ setOperationAction(ISD::BlockAddress, MVT::i32, Custom); -+ setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); -+ setOperationAction(ISD::JumpTable, MVT::i32, Custom); -+ setOperationAction(ISD::ConstantPool, MVT::i32, Custom); -+ setOperationAction(ISD::SELECT, MVT::f32, Custom); -+ setOperationAction(ISD::SELECT, MVT::f64, Custom); -+ setOperationAction(ISD::SELECT, MVT::i32, Custom); -+ setOperationAction(ISD::SETCC, MVT::f32, Custom); -+ setOperationAction(ISD::SETCC, MVT::f64, Custom); -+ setOperationAction(ISD::BRCOND, MVT::Other, Custom); -+ setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - -- // Compute derived properties from the register classes. -- computeRegisterProperties(STI.getRegisterInfo()); -+ if (Subtarget.is64Bit()) { -+ setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); -+ setOperationAction(ISD::BlockAddress, MVT::i64, Custom); -+ setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); -+ setOperationAction(ISD::JumpTable, MVT::i64, Custom); -+ setOperationAction(ISD::ConstantPool, MVT::i64, Custom); -+ setOperationAction(ISD::SELECT, MVT::i64, Custom); -+ setOperationAction(ISD::LOAD, MVT::i64, Legal); -+ setOperationAction(ISD::STORE, MVT::i64, Legal); -+ setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); -+ setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); -+ setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); -+ setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); -+ } - -- setStackPointerRegisterToSaveRestore(LoongArch::R3); -+ if (!Subtarget.is64Bit()) { -+ setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); -+ setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); -+ setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); -+ } - -- setBooleanContents(ZeroOrOneBooleanContent); -+ setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom); -+ if (Subtarget.is64Bit()) -+ setOperationAction(ISD::EH_DWARF_CFA, MVT::i64, Custom); -+ -+ setOperationAction(ISD::SDIV, MVT::i32, Expand); -+ setOperationAction(ISD::SREM, MVT::i32, Expand); -+ setOperationAction(ISD::UDIV, MVT::i32, Expand); -+ setOperationAction(ISD::UREM, MVT::i32, Expand); -+ setOperationAction(ISD::SDIV, MVT::i64, Expand); -+ setOperationAction(ISD::SREM, MVT::i64, Expand); -+ setOperationAction(ISD::UDIV, MVT::i64, Expand); -+ setOperationAction(ISD::UREM, MVT::i64, Expand); -+ -+ // Operations not directly supported by LoongArch. -+ setOperationAction(ISD::BR_CC, MVT::f32, Expand); -+ setOperationAction(ISD::BR_CC, MVT::f64, Expand); -+ setOperationAction(ISD::BR_CC, MVT::i32, Expand); -+ setOperationAction(ISD::BR_CC, MVT::i64, Expand); -+ setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); -+ setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); -+ setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); -+ setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); -+ setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); -+ setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); -+ setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); -+ setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); -+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); -+ setOperationAction(ISD::CTPOP, MVT::i32, Expand); -+ setOperationAction(ISD::CTPOP, MVT::i64, Expand); -+ setOperationAction(ISD::ROTL, MVT::i32, Expand); -+ setOperationAction(ISD::ROTL, MVT::i64, Expand); -+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); -+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); -+ -+ setOperationAction(ISD::FSIN, MVT::f32, Expand); -+ setOperationAction(ISD::FSIN, MVT::f64, Expand); -+ setOperationAction(ISD::FCOS, MVT::f32, Expand); -+ setOperationAction(ISD::FCOS, MVT::f64, Expand); -+ setOperationAction(ISD::FSINCOS, MVT::f32, Expand); -+ setOperationAction(ISD::FSINCOS, MVT::f64, Expand); -+ setOperationAction(ISD::FPOW, MVT::f32, Expand); -+ setOperationAction(ISD::FPOW, MVT::f64, Expand); -+ setOperationAction(ISD::FLOG, MVT::f32, Expand); -+ setOperationAction(ISD::FRINT, MVT::f32, Legal); -+ setOperationAction(ISD::FRINT, MVT::f64, Legal); -+ -+ setOperationAction(ISD::FLOG10, MVT::f32, Expand); -+ setOperationAction(ISD::FEXP, MVT::f32, Expand); -+ setOperationAction(ISD::FMA, MVT::f32, Legal); -+ setOperationAction(ISD::FMA, MVT::f64, Legal); -+ setOperationAction(ISD::FREM, MVT::f32, Expand); -+ setOperationAction(ISD::FREM, MVT::f64, Expand); -+ -+ setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal); -+ setOperationAction(ISD::FMINNUM_IEEE, MVT::f64, Legal); -+ setOperationAction(ISD::FMAXNUM_IEEE, MVT::f32, Legal); -+ setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal); -+ -+ // Lower f16 conversion operations into library calls -+ setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); -+ setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); -+ setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); -+ setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); -+ -+ setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); -+ -+ setOperationAction(ISD::VASTART, MVT::Other, Custom); -+ setOperationAction(ISD::VAARG, MVT::Other, Custom); -+ setOperationAction(ISD::VACOPY, MVT::Other, Expand); -+ setOperationAction(ISD::VAEND, MVT::Other, Expand); -+ -+ // Use the default for now -+ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); -+ setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); -+ -+ if (!Subtarget.is64Bit()) { -+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); -+ setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); -+ } - -- setMaxAtomicSizeInBitsSupported(Subtarget.getGRLen()); -+ if (Subtarget.is64Bit()) { -+ setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); -+ setTruncStoreAction(MVT::i64, MVT::i32, Custom); -+ } - -- // Function alignments. -- const Align FunctionAlignment(4); -- setMinFunctionAlignment(FunctionAlignment); -+ setOperationAction(ISD::TRAP, MVT::Other, Legal); -+ setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); -+ setOperationAction(ISD::BITREVERSE, MVT::i64, Legal); - -+ setTargetDAGCombine(ISD::SELECT); - setTargetDAGCombine(ISD::AND); - setTargetDAGCombine(ISD::OR); -+ setTargetDAGCombine(ISD::AssertZext); -+ setTargetDAGCombine(ISD::SHL); -+ setTargetDAGCombine(ISD::SIGN_EXTEND); -+ setTargetDAGCombine(ISD::ZERO_EXTEND); -+ setTargetDAGCombine(ISD::ADD); -+ setTargetDAGCombine(ISD::SUB); -+ setTargetDAGCombine(ISD::MUL); - setTargetDAGCombine(ISD::SRL); --} -+ setTargetDAGCombine(ISD::SRA); - --SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, -- SelectionDAG &DAG) const { -- switch (Op.getOpcode()) { -- default: -- report_fatal_error("unimplemented operand"); -- case ISD::GlobalAddress: -- return lowerGlobalAddress(Op, DAG); -- case ISD::SHL_PARTS: -- return lowerShiftLeftParts(Op, DAG); -- case ISD::SRA_PARTS: -- return lowerShiftRightParts(Op, DAG, true); -- case ISD::SRL_PARTS: -- return lowerShiftRightParts(Op, DAG, false); -- case ISD::SHL: -- case ISD::SRA: -- case ISD::SRL: -- // This can be called for an i32 shift amount that needs to be promoted. -- assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && -- "Unexpected custom legalisation"); -- return SDValue(); -- case ISD::ConstantPool: -- return lowerConstantPool(Op, DAG); -- case ISD::FP_TO_SINT: -- return lowerFP_TO_SINT(Op, DAG); -- case ISD::BITCAST: -- return lowerBITCAST(Op, DAG); -- case ISD::FP_TO_UINT: -- return SDValue(); -- case ISD::UINT_TO_FP: -- return lowerUINT_TO_FP(Op, DAG); -+ if (ABI.IsLP32()) { -+ // These libcalls are not available in 32-bit. -+ setLibcallName(RTLIB::SHL_I128, nullptr); -+ setLibcallName(RTLIB::SRL_I128, nullptr); -+ setLibcallName(RTLIB::SRA_I128, nullptr); - } --} - --SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, -- SelectionDAG &DAG) const { -+ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { -+ // Expand all truncating stores and extending loads. -+ for (MVT VT0 : MVT::vector_valuetypes()) { -+ for (MVT VT1 : MVT::vector_valuetypes()) { -+ setTruncStoreAction(VT0, VT1, Expand); -+ setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand); -+ setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand); -+ setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand); -+ } -+ } -+ } - -- SDLoc DL(Op); -- auto &TLI = DAG.getTargetLoweringInfo(); -- SDValue Tmp1, Tmp2; -- SDValue Op1 = Op.getOperand(0); -- if (Op1->getOpcode() == ISD::AssertZext || -- Op1->getOpcode() == ISD::AssertSext) -- return Op; -- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0)); -- SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc); -- SDNode *N = Res.getNode(); -- TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG); -- return Tmp1; --} -+ if (Subtarget.hasLSX()) { -+ addLSXIntType(MVT::v16i8, &LoongArch::LSX128BRegClass); -+ addLSXIntType(MVT::v8i16, &LoongArch::LSX128HRegClass); -+ addLSXIntType(MVT::v4i32, &LoongArch::LSX128WRegClass); -+ addLSXIntType(MVT::v2i64, &LoongArch::LSX128DRegClass); -+ addLSXFloatType(MVT::v4f32, &LoongArch::LSX128WRegClass); -+ addLSXFloatType(MVT::v2f64, &LoongArch::LSX128DRegClass); -+ -+ // f16 is a storage-only type, always promote it to f32. -+ setOperationAction(ISD::SETCC, MVT::f16, Promote); -+ setOperationAction(ISD::BR_CC, MVT::f16, Promote); -+ setOperationAction(ISD::SELECT_CC, MVT::f16, Promote); -+ setOperationAction(ISD::SELECT, MVT::f16, Promote); -+ setOperationAction(ISD::FADD, MVT::f16, Promote); -+ setOperationAction(ISD::FSUB, MVT::f16, Promote); -+ setOperationAction(ISD::FMUL, MVT::f16, Promote); -+ setOperationAction(ISD::FDIV, MVT::f16, Promote); -+ setOperationAction(ISD::FREM, MVT::f16, Promote); -+ setOperationAction(ISD::FMA, MVT::f16, Promote); -+ setOperationAction(ISD::FNEG, MVT::f16, Promote); -+ setOperationAction(ISD::FABS, MVT::f16, Promote); -+ setOperationAction(ISD::FCEIL, MVT::f16, Promote); -+ setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote); -+ setOperationAction(ISD::FCOS, MVT::f16, Promote); -+ setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote); -+ setOperationAction(ISD::FFLOOR, MVT::f16, Promote); -+ setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote); -+ setOperationAction(ISD::FPOW, MVT::f16, Promote); -+ setOperationAction(ISD::FPOWI, MVT::f16, Promote); -+ setOperationAction(ISD::FRINT, MVT::f16, Promote); -+ setOperationAction(ISD::FSIN, MVT::f16, Promote); -+ setOperationAction(ISD::FSINCOS, MVT::f16, Promote); -+ setOperationAction(ISD::FSQRT, MVT::f16, Promote); -+ setOperationAction(ISD::FEXP, MVT::f16, Promote); -+ setOperationAction(ISD::FEXP2, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG2, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG10, MVT::f16, Promote); -+ setOperationAction(ISD::FROUND, MVT::f16, Promote); -+ setOperationAction(ISD::FTRUNC, MVT::f16, Promote); -+ setOperationAction(ISD::FMINNUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMAXNUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMINIMUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote); -+ -+ setTargetDAGCombine(ISD::AND); -+ setTargetDAGCombine(ISD::OR); -+ setTargetDAGCombine(ISD::SRA); -+ setTargetDAGCombine(ISD::VSELECT); -+ setTargetDAGCombine(ISD::XOR); -+ } - --SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op, -- SelectionDAG &DAG) const { -+ if (Subtarget.hasLASX()) { -+ addLASXIntType(MVT::v32i8, &LoongArch::LASX256BRegClass); -+ addLASXIntType(MVT::v16i16, &LoongArch::LASX256HRegClass); -+ addLASXIntType(MVT::v8i32, &LoongArch::LASX256WRegClass); -+ addLASXIntType(MVT::v4i64, &LoongArch::LASX256DRegClass); -+ addLASXFloatType(MVT::v8f32, &LoongArch::LASX256WRegClass); -+ addLASXFloatType(MVT::v4f64, &LoongArch::LASX256DRegClass); -+ -+ // f16 is a storage-only type, always promote it to f32. -+ setOperationAction(ISD::SETCC, MVT::f16, Promote); -+ setOperationAction(ISD::BR_CC, MVT::f16, Promote); -+ setOperationAction(ISD::SELECT_CC, MVT::f16, Promote); -+ setOperationAction(ISD::SELECT, MVT::f16, Promote); -+ setOperationAction(ISD::FADD, MVT::f16, Promote); -+ setOperationAction(ISD::FSUB, MVT::f16, Promote); -+ setOperationAction(ISD::FMUL, MVT::f16, Promote); -+ setOperationAction(ISD::FDIV, MVT::f16, Promote); -+ setOperationAction(ISD::FREM, MVT::f16, Promote); -+ setOperationAction(ISD::FMA, MVT::f16, Promote); -+ setOperationAction(ISD::FNEG, MVT::f16, Promote); -+ setOperationAction(ISD::FABS, MVT::f16, Promote); -+ setOperationAction(ISD::FCEIL, MVT::f16, Promote); -+ setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote); -+ setOperationAction(ISD::FCOS, MVT::f16, Promote); -+ setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote); -+ setOperationAction(ISD::FFLOOR, MVT::f16, Promote); -+ setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote); -+ setOperationAction(ISD::FPOW, MVT::f16, Promote); -+ setOperationAction(ISD::FPOWI, MVT::f16, Promote); -+ setOperationAction(ISD::FRINT, MVT::f16, Promote); -+ setOperationAction(ISD::FSIN, MVT::f16, Promote); -+ setOperationAction(ISD::FSINCOS, MVT::f16, Promote); -+ setOperationAction(ISD::FSQRT, MVT::f16, Promote); -+ setOperationAction(ISD::FEXP, MVT::f16, Promote); -+ setOperationAction(ISD::FEXP2, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG2, MVT::f16, Promote); -+ setOperationAction(ISD::FLOG10, MVT::f16, Promote); -+ setOperationAction(ISD::FROUND, MVT::f16, Promote); -+ setOperationAction(ISD::FTRUNC, MVT::f16, Promote); -+ setOperationAction(ISD::FMINNUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMAXNUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMINIMUM, MVT::f16, Promote); -+ setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote); -+ -+ setTargetDAGCombine(ISD::AND); -+ setTargetDAGCombine(ISD::OR); -+ setTargetDAGCombine(ISD::SRA); -+ setTargetDAGCombine(ISD::VSELECT); -+ setTargetDAGCombine(ISD::XOR); -+ } - -- SDLoc DL(Op); -- SDValue Op0 = Op.getOperand(0); -+ if (!Subtarget.useSoftFloat()) { -+ addRegisterClass(MVT::f32, &LoongArch::FGR32RegClass); - -- if (Op.getValueType() == MVT::f32 && Op0.getValueType() == MVT::i32 && -- Subtarget.is64Bit() && Subtarget.hasBasicF()) { -- SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0); -- return DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, NewOp0); -+ // When dealing with single precision only, use libcalls -+ if (!Subtarget.isSingleFloat()) { -+ if (Subtarget.isFP64bit()) -+ addRegisterClass(MVT::f64, &LoongArch::FGR64RegClass); -+ } - } -- return Op; --} - --SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, -- SelectionDAG &DAG) const { -+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); -+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); - -- SDLoc DL(Op); -+ if (Subtarget.is64Bit()) -+ setOperationAction(ISD::MUL, MVT::i64, Custom); -+ -+ if (Subtarget.is64Bit()) { -+ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); -+ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); -+ setOperationAction(ISD::SDIVREM, MVT::i64, Custom); -+ setOperationAction(ISD::UDIVREM, MVT::i64, Custom); -+ } - -- if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() && -- !Subtarget.hasBasicD()) { -- SDValue Dst = -- DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op.getOperand(0)); -- return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst); -+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); -+ setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); -+ -+ setOperationAction(ISD::SDIVREM, MVT::i32, Custom); -+ setOperationAction(ISD::UDIVREM, MVT::i32, Custom); -+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); -+ setOperationAction(ISD::LOAD, MVT::i32, Legal); -+ setOperationAction(ISD::STORE, MVT::i32, Legal); -+ -+ setTargetDAGCombine(ISD::MUL); -+ -+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); -+ setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); -+ setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); -+ -+ // Replace the accumulator-based multiplies with a -+ // three register instruction. -+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); -+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); -+ setOperationAction(ISD::MUL, MVT::i32, Legal); -+ setOperationAction(ISD::MULHS, MVT::i32, Legal); -+ setOperationAction(ISD::MULHU, MVT::i32, Legal); -+ -+ // Replace the accumulator-based division/remainder with separate -+ // three register division and remainder instructions. -+ setOperationAction(ISD::SDIVREM, MVT::i32, Expand); -+ setOperationAction(ISD::UDIVREM, MVT::i32, Expand); -+ setOperationAction(ISD::SDIV, MVT::i32, Legal); -+ setOperationAction(ISD::UDIV, MVT::i32, Legal); -+ setOperationAction(ISD::SREM, MVT::i32, Legal); -+ setOperationAction(ISD::UREM, MVT::i32, Legal); -+ -+ // Replace the accumulator-based multiplies with a -+ // three register instruction. -+ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); -+ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); -+ setOperationAction(ISD::MUL, MVT::i64, Legal); -+ setOperationAction(ISD::MULHS, MVT::i64, Legal); -+ setOperationAction(ISD::MULHU, MVT::i64, Legal); -+ -+ // Replace the accumulator-based division/remainder with separate -+ // three register division and remainder instructions. -+ setOperationAction(ISD::SDIVREM, MVT::i64, Expand); -+ setOperationAction(ISD::UDIVREM, MVT::i64, Expand); -+ setOperationAction(ISD::SDIV, MVT::i64, Legal); -+ setOperationAction(ISD::UDIV, MVT::i64, Legal); -+ setOperationAction(ISD::SREM, MVT::i64, Legal); -+ setOperationAction(ISD::UREM, MVT::i64, Legal); -+ -+ MaxGluedStoresPerMemcpy = 4; -+ -+ setMinFunctionAlignment(Align(4)); -+ -+ // The arguments on the stack are defined in terms of 4-byte slots on LP32 -+ // and 8-byte slots on LPX32/LP64. -+ setMinStackArgumentAlignment((ABI.IsLPX32() || ABI.IsLP64()) ? Align(8) -+ : Align(4)); -+ -+ setStackPointerRegisterToSaveRestore(ABI.IsLP64() ? LoongArch::SP_64 : LoongArch::SP); -+ -+ if (Subtarget.hasLASX()) { -+ // = 16*32/2; the smallest memcpy; -+ MaxStoresPerMemcpy = 16; -+ } else if (Subtarget.hasLSX()) { -+ MaxStoresPerMemcpy = 65535; -+ } else { -+ MaxStoresPerMemcpy = 16; - } - -- EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); -- SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op.getOperand(0)); -- return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc); -+ computeRegisterProperties(Subtarget.getRegisterInfo()); - } - --SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op, -- SelectionDAG &DAG) const { -- SDLoc DL(Op); -- EVT Ty = Op.getValueType(); -- ConstantPoolSDNode *N = cast(Op); -+// Enable LSX support for the given integer type and Register class. -+void LoongArchTargetLowering::addLSXIntType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC) { -+ addRegisterClass(Ty, RC); -+ -+ // Expand all builtin opcodes. -+ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) -+ setOperationAction(Opc, Ty, Expand); -+ -+ setOperationAction(ISD::BITCAST, Ty, Legal); -+ setOperationAction(ISD::LOAD, Ty, Legal); -+ setOperationAction(ISD::STORE, Ty, Legal); -+ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom); -+ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); -+ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); -+ setOperationAction(ISD::ABS, Ty, Legal); -+ setOperationAction(ISD::UNDEF, Ty, Legal); -+ setOperationAction(ISD::EXTRACT_SUBVECTOR, Ty, Legal); -+ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); -+ -+ if (Ty == MVT::v4i32 || Ty == MVT::v2i64) { -+ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); -+ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); -+ } - -- // FIXME: Only support PC-relative addressing to access the symbol. -- // Target flags will be added later. -- if (!isPositionIndependent()) { -- SDValue ConstantN = DAG.getTargetConstantPool( -- N->getConstVal(), Ty, N->getAlign(), N->getOffset()); -- SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN), -- 0); -- SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D -- : LoongArch::ADDI_W, -- DL, Ty, AddrHi, ConstantN), -- 0); -- return Addr; -+ setOperationAction(ISD::ADD, Ty, Legal); -+ setOperationAction(ISD::AND, Ty, Legal); -+ setOperationAction(ISD::CTLZ, Ty, Legal); -+ setOperationAction(ISD::CTPOP, Ty, Legal); -+ setOperationAction(ISD::MUL, Ty, Legal); -+ setOperationAction(ISD::OR, Ty, Legal); -+ setOperationAction(ISD::SDIV, Ty, Legal); -+ setOperationAction(ISD::SREM, Ty, Legal); -+ setOperationAction(ISD::SHL, Ty, Legal); -+ setOperationAction(ISD::SRA, Ty, Legal); -+ setOperationAction(ISD::SRL, Ty, Legal); -+ setOperationAction(ISD::SUB, Ty, Legal); -+ setOperationAction(ISD::SMAX, Ty, Legal); -+ setOperationAction(ISD::SMIN, Ty, Legal); -+ setOperationAction(ISD::UDIV, Ty, Legal); -+ setOperationAction(ISD::UREM, Ty, Legal); -+ setOperationAction(ISD::UMAX, Ty, Legal); -+ setOperationAction(ISD::UMIN, Ty, Legal); -+ setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); -+ setOperationAction(ISD::VSELECT, Ty, Legal); -+ setOperationAction(ISD::XOR, Ty, Legal); -+ setOperationAction(ISD::MULHS, Ty, Legal); -+ setOperationAction(ISD::MULHU, Ty, Legal); -+ -+ if (Ty == MVT::v4i32 || Ty == MVT::v2i64) { -+ setOperationAction(ISD::SINT_TO_FP, Ty, Custom); -+ setOperationAction(ISD::UINT_TO_FP, Ty, Custom); - } -- report_fatal_error("Unable to lower ConstantPool"); --} - --SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, -- SelectionDAG &DAG) const { -- SDLoc DL(Op); -- EVT Ty = getPointerTy(DAG.getDataLayout()); -- const GlobalValue *GV = cast(Op)->getGlobal(); -- unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; -+ setOperationAction(ISD::SETCC, Ty, Legal); -+ setCondCodeAction(ISD::SETNE, Ty, Expand); -+ setCondCodeAction(ISD::SETGE, Ty, Expand); -+ setCondCodeAction(ISD::SETGT, Ty, Expand); -+ setCondCodeAction(ISD::SETUGE, Ty, Expand); -+ setCondCodeAction(ISD::SETUGT, Ty, Expand); -+} - -- // TODO: Support dso_preemptable and target flags. -- if (GV->isDSOLocal()) { -- SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty); -- SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0); -- SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0); -- return Addr; -+// Enable LASX support for the given integer type and Register class. -+void LoongArchTargetLowering::addLASXIntType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC) { -+ addRegisterClass(Ty, RC); -+ -+ // Expand all builtin opcodes. -+ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) -+ setOperationAction(Opc, Ty, Expand); -+ -+ // FIXME -+ setOperationAction(ISD::BITCAST, Ty, Legal); -+ setOperationAction(ISD::LOAD, Ty, Legal); -+ setOperationAction(ISD::STORE, Ty, Legal); -+ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom); -+ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Custom); -+ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); -+ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); -+ setOperationAction(ISD::UNDEF, Ty, Legal); -+ setOperationAction(ISD::UADDSAT, Ty, Legal); -+ setOperationAction(ISD::SADDSAT, Ty, Legal); -+ setOperationAction(ISD::USUBSAT, Ty, Legal); -+ setOperationAction(ISD::SSUBSAT, Ty, Legal); -+ setOperationAction(ISD::ABS, Ty, Legal); -+ -+ setOperationAction(ISD::ADD, Ty, Legal); -+ setOperationAction(ISD::AND, Ty, Legal); -+ setOperationAction(ISD::CTLZ, Ty, Legal); -+ setOperationAction(ISD::CTPOP, Ty, Legal); -+ setOperationAction(ISD::MUL, Ty, Legal); -+ setOperationAction(ISD::OR, Ty, Legal); -+ setOperationAction(ISD::SDIV, Ty, Legal); -+ setOperationAction(ISD::SREM, Ty, Legal); -+ setOperationAction(ISD::SHL, Ty, Legal); -+ setOperationAction(ISD::SRA, Ty, Legal); -+ setOperationAction(ISD::SRL, Ty, Legal); -+ setOperationAction(ISD::SUB, Ty, Legal); -+ setOperationAction(ISD::SMAX, Ty, Legal); -+ setOperationAction(ISD::SMIN, Ty, Legal); -+ setOperationAction(ISD::UDIV, Ty, Legal); -+ setOperationAction(ISD::UREM, Ty, Legal); -+ setOperationAction(ISD::UMAX, Ty, Legal); -+ setOperationAction(ISD::UMIN, Ty, Legal); -+ setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); -+ setOperationAction(ISD::VSELECT, Ty, Legal); -+ setOperationAction(ISD::XOR, Ty, Legal); -+ setOperationAction(ISD::INSERT_SUBVECTOR, Ty, Legal); -+ setOperationAction(ISD::MULHS, Ty, Legal); -+ setOperationAction(ISD::MULHU, Ty, Legal); -+ -+ setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, Ty, Legal); -+ setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, Ty, Legal); -+ -+ setOperationAction(ISD::SIGN_EXTEND, Ty, Legal); -+ setOperationAction(ISD::ZERO_EXTEND, Ty, Legal); -+ -+ if (Ty == MVT::v8i32 || Ty == MVT::v4i64) { -+ setOperationAction(ISD::SINT_TO_FP, Ty, Custom); -+ setOperationAction(ISD::UINT_TO_FP, Ty, Custom); - } -- report_fatal_error("Unable to lowerGlobalAddress"); -+ -+ setTargetDAGCombine(ISD::CONCAT_VECTORS); -+ -+ setOperationAction(ISD::SETCC, Ty, Legal); -+ setCondCodeAction(ISD::SETNE, Ty, Expand); -+ setCondCodeAction(ISD::SETGE, Ty, Expand); -+ setCondCodeAction(ISD::SETGT, Ty, Expand); -+ setCondCodeAction(ISD::SETUGE, Ty, Expand); -+ setCondCodeAction(ISD::SETUGT, Ty, Expand); - } - --SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, -- SelectionDAG &DAG) const { -- SDLoc DL(Op); -- SDValue Lo = Op.getOperand(0); -- SDValue Hi = Op.getOperand(1); -- SDValue Shamt = Op.getOperand(2); -- EVT VT = Lo.getValueType(); -+// Enable LSX support for the given floating-point type and Register class. -+void LoongArchTargetLowering::addLSXFloatType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC) { -+ addRegisterClass(Ty, RC); -+ -+ // Expand all builtin opcodes. -+ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) -+ setOperationAction(Opc, Ty, Expand); -+ -+ setOperationAction(ISD::LOAD, Ty, Legal); -+ setOperationAction(ISD::STORE, Ty, Legal); -+ setOperationAction(ISD::BITCAST, Ty, Legal); -+ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal); -+ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); -+ setOperationAction(ISD::UNDEF, Ty, Legal); -+ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); -+ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); -+ -+ if (Ty == MVT::v4f32 || Ty == MVT::v2f64) { -+ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); -+ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); -+ } - -- // if Shamt-GRLen < 0: // Shamt < GRLen -- // Lo = Lo << Shamt -- // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt)) -- // else: -- // Lo = 0 -- // Hi = Lo << (Shamt-GRLen) -- -- SDValue Zero = DAG.getConstant(0, DL, VT); -- SDValue One = DAG.getConstant(1, DL, VT); -- SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); -- SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); -- SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); -- SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); -- -- SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); -- SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); -- SDValue ShiftRightLo = -- DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt); -- SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); -- SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); -- SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen); -+ setOperationAction(ISD::FADD, Ty, Legal); -+ setOperationAction(ISD::FDIV, Ty, Legal); -+ setOperationAction(ISD::FMA, Ty, Legal); -+ setOperationAction(ISD::FMUL, Ty, Legal); -+ setOperationAction(ISD::FSQRT, Ty, Legal); -+ setOperationAction(ISD::FSUB, Ty, Legal); -+ setOperationAction(ISD::VSELECT, Ty, Legal); -+ setOperationAction(ISD::FNEG, Ty, Legal); -+ setOperationAction(ISD::FRINT, Ty, Legal); -+ -+ setOperationAction(ISD::SETCC, Ty, Legal); -+ setCondCodeAction(ISD::SETOGE, Ty, Expand); -+ setCondCodeAction(ISD::SETOGT, Ty, Expand); -+ setCondCodeAction(ISD::SETUGE, Ty, Expand); -+ setCondCodeAction(ISD::SETUGT, Ty, Expand); -+ setCondCodeAction(ISD::SETGE, Ty, Expand); -+ setCondCodeAction(ISD::SETGT, Ty, Expand); -+} - -- SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); -+// Enable LASX support for the given floating-point type and Register class. -+void LoongArchTargetLowering::addLASXFloatType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC) { -+ addRegisterClass(Ty, RC); -+ -+ // Expand all builtin opcodes. -+ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) -+ setOperationAction(Opc, Ty, Expand); -+ -+ setOperationAction(ISD::LOAD, Ty, Legal); -+ setOperationAction(ISD::STORE, Ty, Legal); -+ setOperationAction(ISD::BITCAST, Ty, Legal); -+ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal); -+ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); -+ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); -+ setOperationAction(ISD::UNDEF, Ty, Legal); -+ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); -+ -+ setOperationAction(ISD::FADD, Ty, Legal); -+ setOperationAction(ISD::FDIV, Ty, Legal); -+ setOperationAction(ISD::FMA, Ty, Legal); -+ setOperationAction(ISD::FMUL, Ty, Legal); -+ setOperationAction(ISD::FSQRT, Ty, Legal); -+ setOperationAction(ISD::FSUB, Ty, Legal); -+ setOperationAction(ISD::VSELECT, Ty, Legal); -+ setOperationAction(ISD::FNEG, Ty, Legal); -+ setOperationAction(ISD::FRINT, Ty, Legal); -+ -+ if (Ty == MVT::v8f32 || Ty == MVT::v4f64) { -+ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); -+ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); -+ } - -- Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); -- Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); -+ setOperationAction(ISD::SETCC, Ty, Legal); -+ setCondCodeAction(ISD::SETOGE, Ty, Expand); -+ setCondCodeAction(ISD::SETOGT, Ty, Expand); -+ setCondCodeAction(ISD::SETUGE, Ty, Expand); -+ setCondCodeAction(ISD::SETUGT, Ty, Expand); -+ setCondCodeAction(ISD::SETGE, Ty, Expand); -+ setCondCodeAction(ISD::SETGT, Ty, Expand); -+} - -- SDValue Parts[2] = {Lo, Hi}; -- return DAG.getMergeValues(Parts, DL); -+bool LoongArchTargetLowering::allowsMisalignedMemoryAccesses( -+ EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, -+ bool *Fast) const { -+ if (!Subtarget.allowUnalignedAccess()) -+ return false; -+ if (Fast) -+ *Fast = true; -+ return true; - } - --SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, -- SelectionDAG &DAG, -- bool IsSRA) const { -- SDLoc DL(Op); -- SDValue Lo = Op.getOperand(0); -- SDValue Hi = Op.getOperand(1); -- SDValue Shamt = Op.getOperand(2); -- EVT VT = Lo.getValueType(); -- -- // SRA expansion: -- // if Shamt-GRLen < 0: // Shamt < GRLen -- // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) -- // Hi = Hi >>s Shamt -- // else: -- // Lo = Hi >>s (Shamt-GRLen); -- // Hi = Hi >>s (GRLen-1) -- // -- // SRL expansion: -- // if Shamt-GRLen < 0: // Shamt < GRLen -- // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) -- // Hi = Hi >>u Shamt -- // else: -- // Lo = Hi >>u (Shamt-GRLen); -- // Hi = 0; -- -- unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; -- -- SDValue Zero = DAG.getConstant(0, DL, VT); -- SDValue One = DAG.getConstant(1, DL, VT); -- SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); -- SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); -- SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); -- SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); -+EVT LoongArchTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, -+ EVT VT) const { -+ if (!VT.isVector()) -+ return MVT::i32; -+ return VT.changeVectorElementTypeToInteger(); -+} - -- SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); -- SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); -- SDValue ShiftLeftHi = -- DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt); -- SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); -- SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); -- SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen); -- SDValue HiFalse = -- IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero; -+static LoongArch::CondCode condCodeToFCC(ISD::CondCode CC) { -+ switch (CC) { -+ default: llvm_unreachable("Unknown fp condition code!"); -+ case ISD::SETEQ: -+ case ISD::SETOEQ: return LoongArch::FCOND_OEQ; -+ case ISD::SETUNE: return LoongArch::FCOND_UNE; -+ case ISD::SETLT: -+ case ISD::SETOLT: return LoongArch::FCOND_OLT; -+ case ISD::SETGT: -+ case ISD::SETOGT: return LoongArch::FCOND_OGT; -+ case ISD::SETLE: -+ case ISD::SETOLE: return LoongArch::FCOND_OLE; -+ case ISD::SETGE: -+ case ISD::SETOGE: return LoongArch::FCOND_OGE; -+ case ISD::SETULT: return LoongArch::FCOND_ULT; -+ case ISD::SETULE: return LoongArch::FCOND_ULE; -+ case ISD::SETUGT: return LoongArch::FCOND_UGT; -+ case ISD::SETUGE: return LoongArch::FCOND_UGE; -+ case ISD::SETUO: return LoongArch::FCOND_UN; -+ case ISD::SETO: return LoongArch::FCOND_OR; -+ case ISD::SETNE: -+ case ISD::SETONE: return LoongArch::FCOND_ONE; -+ case ISD::SETUEQ: return LoongArch::FCOND_UEQ; -+ } -+} - -- SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); -+/// This function returns true if the floating point conditional branches and -+/// conditional moves which use condition code CC should be inverted. -+static bool invertFPCondCodeUser(LoongArch::CondCode CC) { -+ if (CC >= LoongArch::FCOND_F && CC <= LoongArch::FCOND_SUNE) -+ return false; - -- Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); -- Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); -+ assert((CC >= LoongArch::FCOND_T && CC <= LoongArch::FCOND_GT) && -+ "Illegal Condition Code"); - -- SDValue Parts[2] = {Lo, Hi}; -- return DAG.getMergeValues(Parts, DL); -+ return true; - } - --// Returns the opcode of the target-specific SDNode that implements the 32-bit --// form of the given Opcode. --static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { -- switch (Opcode) { -- default: -- llvm_unreachable("Unexpected opcode"); -- case ISD::SHL: -- return LoongArchISD::SLL_W; -- case ISD::SRA: -- return LoongArchISD::SRA_W; -- case ISD::SRL: -- return LoongArchISD::SRL_W; -- } -+// Creates and returns an FPCmp node from a setcc node. -+// Returns Op if setcc is not a floating point comparison. -+static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { -+ // must be a SETCC node -+ if (Op.getOpcode() != ISD::SETCC) -+ return Op; -+ -+ SDValue LHS = Op.getOperand(0); -+ -+ if (!LHS.getValueType().isFloatingPoint()) -+ return Op; -+ -+ SDValue RHS = Op.getOperand(1); -+ SDLoc DL(Op); -+ -+ // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of -+ // node if necessary. -+ ISD::CondCode CC = cast(Op.getOperand(2))->get(); -+ -+ return DAG.getNode(LoongArchISD::FPCmp, DL, MVT::Glue, LHS, RHS, -+ DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32)); - } - --// Converts the given i8/i16/i32 operation to a target-specific SelectionDAG --// node. Because i8/i16/i32 isn't a legal type for LA64, these operations would --// otherwise be promoted to i64, making it difficult to select the --// SLL_W/.../*W later one because the fact the operation was originally of --// type i8/i16/i32 is lost. --static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, -- unsigned ExtOpc = ISD::ANY_EXTEND) { -- SDLoc DL(N); -- LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode()); -- SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0)); -- SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1)); -- SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1); -- // ReplaceNodeResults requires we maintain the same type for the return value. -- return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes); -+// Creates and returns a CMovFPT/F node. -+static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, -+ SDValue False, const SDLoc &DL) { -+ ConstantSDNode *CC = cast(Cond.getOperand(2)); -+ bool invert = invertFPCondCodeUser((LoongArch::CondCode)CC->getSExtValue()); -+ SDValue FCC0 = DAG.getRegister(LoongArch::FCC0, MVT::i32); -+ -+ return DAG.getNode((invert ? LoongArchISD::CMovFP_F : LoongArchISD::CMovFP_T), DL, -+ True.getValueType(), True, FCC0, False, Cond); -+ - } - --void LoongArchTargetLowering::ReplaceNodeResults( -- SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { -- SDLoc DL(N); -- switch (N->getOpcode()) { -- default: -- llvm_unreachable("Don't know how to legalize this operation"); -- case ISD::SHL: -- case ISD::SRA: -- case ISD::SRL: -- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && -- "Unexpected custom legalisation"); -- if (N->getOperand(1).getOpcode() != ISD::Constant) { -- Results.push_back(customLegalizeToWOp(N, DAG)); -- break; -- } -- break; -- case ISD::FP_TO_SINT: { -- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && -- "Unexpected custom legalisation"); -- SDValue Src = N->getOperand(0); -- EVT VT = EVT::getFloatingPointVT(N->getValueSizeInBits(0)); -- SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src); -- Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst)); -- break; -- } -- case ISD::BITCAST: { -- EVT VT = N->getValueType(0); -- SDValue Src = N->getOperand(0); -- EVT SrcVT = Src.getValueType(); -- if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() && -- Subtarget.hasBasicF()) { -- SDValue Dst = -- DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Src); -- Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Dst)); -- } -- break; -- } -- case ISD::FP_TO_UINT: { -- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && -- "Unexpected custom legalisation"); -- auto &TLI = DAG.getTargetLoweringInfo(); -- SDValue Tmp1, Tmp2; -- TLI.expandFP_TO_UINT(N, Tmp1, Tmp2, DAG); -- Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Tmp1)); -- break; -+static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ if (DCI.isBeforeLegalizeOps()) -+ return SDValue(); -+ -+ SDValue SetCC = N->getOperand(0); -+ -+ if ((SetCC.getOpcode() != ISD::SETCC) || -+ !SetCC.getOperand(0).getValueType().isInteger()) -+ return SDValue(); -+ -+ SDValue False = N->getOperand(2); -+ EVT FalseTy = False.getValueType(); -+ -+ if (!FalseTy.isInteger()) -+ return SDValue(); -+ -+ ConstantSDNode *FalseC = dyn_cast(False); -+ -+ // If the RHS (False) is 0, we swap the order of the operands -+ // of ISD::SELECT (obviously also inverting the condition) so that we can -+ // take advantage of conditional moves using the $0 register. -+ // Example: -+ // return (a != 0) ? x : 0; -+ // load $reg, x -+ // movz $reg, $0, a -+ if (!FalseC) -+ return SDValue(); -+ -+ const SDLoc DL(N); -+ -+ if (!FalseC->getZExtValue()) { -+ ISD::CondCode CC = cast(SetCC.getOperand(2))->get(); -+ SDValue True = N->getOperand(1); -+ -+ SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), -+ SetCC.getOperand(1), -+ ISD::getSetCCInverse(CC, SetCC.getValueType())); -+ -+ return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); - } -+ -+ // If both operands are integer constants there's a possibility that we -+ // can do some interesting optimizations. -+ SDValue True = N->getOperand(1); -+ ConstantSDNode *TrueC = dyn_cast(True); -+ -+ if (!TrueC || !True.getValueType().isInteger()) -+ return SDValue(); -+ -+ // We'll also ignore MVT::i64 operands as this optimizations proves -+ // to be ineffective because of the required sign extensions as the result -+ // of a SETCC operator is always MVT::i32 for non-vector types. -+ if (True.getValueType() == MVT::i64) -+ return SDValue(); -+ -+ int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue(); -+ -+ // 1) (a < x) ? y : y-1 -+ // slti $reg1, a, x -+ // addiu $reg2, $reg1, y-1 -+ if (Diff == 1) -+ return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False); -+ -+ // 2) (a < x) ? y-1 : y -+ // slti $reg1, a, x -+ // xor $reg1, $reg1, 1 -+ // addiu $reg2, $reg1, y-1 -+ if (Diff == -1) { -+ ISD::CondCode CC = cast(SetCC.getOperand(2))->get(); -+ SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), -+ SetCC.getOperand(1), -+ ISD::getSetCCInverse(CC, SetCC.getValueType())); -+ return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); - } -+ -+ // Could not optimize. -+ return SDValue(); - } - - static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const LoongArchSubtarget &Subtarget) { -+ -+ if (Subtarget.hasLSX()) { -+ -+ // Fold zero extensions into LoongArchISD::VEXTRACT_[SZ]EXT_ELT -+ // -+ // Performs the following transformations: -+ // - Changes LoongArchISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its -+ // sign/zero-extension is completely overwritten by the new one performed -+ // by the ISD::AND. -+ // - Removes redundant zero extensions performed by an ISD::AND. -+ SDValue Op0 = N->getOperand(0); -+ SDValue Op1 = N->getOperand(1); -+ unsigned Op0Opcode = Op0->getOpcode(); -+ -+ // (and (LoongArchVExtract[SZ]Ext $a, $b, $c), imm:$d) -+ // where $d + 1 == 2^n and n == 32 -+ // or $d + 1 == 2^n and n <= 32 and ZExt -+ // -> (LoongArchVExtractZExt $a, $b, $c) -+ if (Op0Opcode == LoongArchISD::VEXTRACT_SEXT_ELT || -+ Op0Opcode == LoongArchISD::VEXTRACT_ZEXT_ELT) { -+ ConstantSDNode *Mask = dyn_cast(Op1); -+ -+ if (Mask) { -+ -+ int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2(); -+ -+ if (Log2IfPositive > 0) { -+ SDValue Op0Op2 = Op0->getOperand(2); -+ EVT ExtendTy = cast(Op0Op2)->getVT(); -+ unsigned ExtendTySize = ExtendTy.getSizeInBits(); -+ unsigned Log2 = Log2IfPositive; -+ -+ if ((Op0Opcode == LoongArchISD::VEXTRACT_ZEXT_ELT && -+ Log2 >= ExtendTySize) || -+ Log2 == ExtendTySize) { -+ SDValue Ops[] = {Op0->getOperand(0), Op0->getOperand(1), Op0Op2}; -+ return DAG.getNode(LoongArchISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0), -+ Op0->getVTList(), -+ makeArrayRef(Ops, Op0->getNumOperands())); -+ } -+ } -+ } -+ } -+ } -+ - if (DCI.isBeforeLegalizeOps()) - return SDValue(); - - SDValue FirstOperand = N->getOperand(0); -- SDValue SecondOperand = N->getOperand(1); - unsigned FirstOperandOpc = FirstOperand.getOpcode(); -+ SDValue Mask = N->getOperand(1); - EVT ValTy = N->getValueType(0); - SDLoc DL(N); -- uint64_t lsb, msb; -- unsigned SMIdx, SMLen; -+ -+ uint64_t Lsb = 0, SMLsb, SMSize; - ConstantSDNode *CN; - SDValue NewOperand; -- MVT GRLenVT = Subtarget.getGRLenVT(); -+ unsigned Opc; - - // Op's second operand must be a shifted mask. -- if (!(CN = dyn_cast(SecondOperand)) || -- !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen)) -+ if (!(CN = dyn_cast(Mask)) || -+ !isShiftedMask(CN->getZExtValue(), SMLsb, SMSize)) - return SDValue(); - - if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { - // Pattern match BSTRPICK. -- // $dst = and ((sra or srl) $src , lsb), (2**len - 1) -- // => BSTRPICK $dst, $src, msb, lsb -- // where msb = lsb + len - 1 -+ // $dst = and ((sra or srl) $src , lsb), (2**size - 1) -+ // => bstrpick $dst, $src, lsb+size-1, lsb - - // The second operand of the shift must be an immediate. - if (!(CN = dyn_cast(FirstOperand.getOperand(1)))) - return SDValue(); - -- lsb = CN->getZExtValue(); -+ Lsb = CN->getZExtValue(); - -- // Return if the shifted mask does not start at bit 0 or the sum of its -- // length and lsb exceeds the word's size. -- if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits()) -+ // Return if the shifted mask does not start at bit 0 or the sum of its size -+ // and Lsb exceeds the word's size. -+ if (SMLsb != 0 || Lsb + SMSize > ValTy.getSizeInBits()) - return SDValue(); - -+ Opc = LoongArchISD::BSTRPICK; - NewOperand = FirstOperand.getOperand(0); - } else { - // Pattern match BSTRPICK. -- // $dst = and $src, (2**len- 1) , if len > 12 -- // => BSTRPICK $dst, $src, msb, lsb -- // where lsb = 0 and msb = len - 1 -+ // $dst = and $src, (2**size - 1) , if size > 12 -+ // => bstrpick $dst, $src, lsb+size-1, lsb , lsb = 0 - - // If the mask is <= 0xfff, andi can be used instead. - if (CN->getZExtValue() <= 0xfff) - return SDValue(); -- - // Return if the mask doesn't start at position 0. -- if (SMIdx) -+ if (SMLsb) - return SDValue(); - -- lsb = 0; -+ Opc = LoongArchISD::BSTRPICK; - NewOperand = FirstOperand; - } -- msb = lsb + SMLen - 1; -- return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, -- DAG.getConstant(msb, DL, GRLenVT), -- DAG.getConstant(lsb, DL, GRLenVT)); -+ return DAG.getNode(Opc, DL, ValTy, NewOperand, -+ DAG.getConstant((Lsb + SMSize - 1), DL, MVT::i32), -+ DAG.getConstant(Lsb, DL, MVT::i32)); - } - --static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, -- TargetLowering::DAGCombinerInfo &DCI, -- const LoongArchSubtarget &Subtarget) { -- if (DCI.isBeforeLegalizeOps()) -- return SDValue(); -+// Determine if the specified node is a constant vector splat. -+// -+// Returns true and sets Imm if: -+// * N is a ISD::BUILD_VECTOR representing a constant splat -+static bool isVSplat(SDValue N, APInt &Imm) { -+ BuildVectorSDNode *Node = dyn_cast(N.getNode()); - -- // $dst = srl (and $src, Mask), Shamt -- // => -- // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt -- // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1 -- // -+ if (!Node) -+ return false; - -- SDValue FirstOperand = N->getOperand(0); -- ConstantSDNode *CN; -- EVT ValTy = N->getValueType(0); -- SDLoc DL(N); -- MVT GRLenVT = Subtarget.getGRLenVT(); -- unsigned MaskIdx, MaskLen; -- uint64_t Shamt; -+ APInt SplatValue, SplatUndef; -+ unsigned SplatBitSize; -+ bool HasAnyUndefs; -+ -+ if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, -+ 8)) -+ return false; -+ -+ Imm = SplatValue; -+ -+ return true; -+} -+ -+// Test whether the given node is an all-ones build_vector. -+static bool isVectorAllOnes(SDValue N) { -+ // Look through bitcasts. Endianness doesn't matter because we are looking -+ // for an all-ones value. -+ if (N->getOpcode() == ISD::BITCAST) -+ N = N->getOperand(0); - -- // The first operand must be an AND and the second operand of the AND must be -- // a shifted mask. -- if (FirstOperand.getOpcode() != ISD::AND || -- !(CN = dyn_cast(FirstOperand.getOperand(1))) || -- !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen)) -+ BuildVectorSDNode *BVN = dyn_cast(N); -+ -+ if (!BVN) -+ return false; -+ -+ APInt SplatValue, SplatUndef; -+ unsigned SplatBitSize; -+ bool HasAnyUndefs; -+ -+ // Endianness doesn't matter in this context because we are looking for -+ // an all-ones value. -+ if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs)) -+ return SplatValue.isAllOnesValue(); -+ -+ return false; -+} -+ -+// Test whether N is the bitwise inverse of OfNode. -+static bool isBitwiseInverse(SDValue N, SDValue OfNode) { -+ if (N->getOpcode() != ISD::XOR) -+ return false; -+ -+ if (isVectorAllOnes(N->getOperand(0))) -+ return N->getOperand(1) == OfNode; -+ -+ if (isVectorAllOnes(N->getOperand(1))) -+ return N->getOperand(0) == OfNode; -+ -+ return false; -+} -+ -+static SDValue performSet(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ SDValue Op0 = N->getOperand(0); -+ SDValue Op1 = N->getOperand(1); -+ SDValue N1, N2; -+ if (Op0->getOpcode() == ISD::BUILD_VECTOR && -+ (Op1->getValueType(0).is128BitVector() || -+ Op1->getValueType(0).is256BitVector())) { -+ N1 = Op0; -+ N2 = Op1; -+ } else if (Op1->getOpcode() == ISD::BUILD_VECTOR && -+ (Op0->getValueType(0).is128BitVector() || -+ Op0->getValueType(0).is256BitVector())) { -+ N1 = Op1; -+ N2 = Op0; -+ } else - return SDValue(); - -- // The second operand (shift amount) must be an immediate. -- if (!(CN = dyn_cast(N->getOperand(1)))) -+ APInt Mask1, Mask2; -+ if (!isVSplat(N1, Mask1)) - return SDValue(); - -- Shamt = CN->getZExtValue(); -- if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1) -- return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, -- FirstOperand->getOperand(0), -- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), -- DAG.getConstant(Shamt, DL, GRLenVT)); -+ if (!N1->getValueType(0).isSimple()) -+ return SDValue(); - -- return SDValue(); -+ ConstantSDNode *C1; -+ uint64_t Imm; -+ unsigned ImmL; -+ if (!(C1 = dyn_cast(N1.getOperand(0))) || -+ !isPowerOf2_64(C1->getZExtValue())) -+ return SDValue(); -+ -+ Imm = C1->getZExtValue(); -+ ImmL = Log2_64(Imm); -+ MVT VT = N1->getSimpleValueType(0).SimpleTy; -+ -+ SDNode *Res; -+ -+ if (Subtarget.hasLASX() && N->getValueType(0).is256BitVector()) { -+ if (VT == MVT::v32i8 && ImmL < 8) -+ Res = DAG.getMachineNode(LoongArch::XVBITSETI_B, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v16i16 && ImmL < 16) -+ Res = DAG.getMachineNode(LoongArch::XVBITSETI_H, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v8i32 && ImmL < 32) -+ Res = DAG.getMachineNode(LoongArch::XVBITSETI_W, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v4i64 && ImmL < 64) -+ Res = DAG.getMachineNode(LoongArch::XVBITSETI_D, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else -+ return SDValue(); -+ } else if (N->getValueType(0).is128BitVector()) { -+ if (VT == MVT::v16i8 && ImmL < 8) -+ Res = DAG.getMachineNode(LoongArch::VBITSETI_B, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v8i16 && ImmL < 16) -+ Res = DAG.getMachineNode(LoongArch::VBITSETI_H, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v4i32 && ImmL < 32) -+ Res = DAG.getMachineNode(LoongArch::VBITSETI_W, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else if (VT == MVT::v2i64 && ImmL < 64) -+ Res = DAG.getMachineNode(LoongArch::VBITSETI_D, SDLoc(N), VT, N2, -+ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); -+ else -+ return SDValue(); -+ -+ } else -+ return SDValue(); -+ -+ return SDValue(Res, 0); - } - - static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const LoongArchSubtarget &Subtarget) { -- MVT GRLenVT = Subtarget.getGRLenVT(); -- EVT ValTy = N->getValueType(0); -- SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); -- ConstantSDNode *CN0, *CN1; -- SDLoc DL(N); -- unsigned ValBits = ValTy.getSizeInBits(); -- unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1; -- unsigned Shamt; -- bool SwapAndRetried = false; - -+ SDValue Res; -+ if (Subtarget.hasLSX() && (N->getValueType(0).is128BitVector() || -+ N->getValueType(0).is256BitVector())) { -+ SDValue Op0 = N->getOperand(0); -+ SDValue Op1 = N->getOperand(1); -+ -+ if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) { -+ SDValue Op0Op0 = Op0->getOperand(0); -+ SDValue Op0Op1 = Op0->getOperand(1); -+ SDValue Op1Op0 = Op1->getOperand(0); -+ SDValue Op1Op1 = Op1->getOperand(1); -+ -+ SDValue IfSet, IfClr, Cond; -+ bool IsConstantMask = false; -+ APInt Mask, InvMask; -+ -+ // If Op0Op0 is an appropriate mask, try to find it's inverse in either -+ // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, -+ // while looking. IfClr will be set if we find a valid match. -+ if (isVSplat(Op0Op0, Mask)) { -+ Cond = Op0Op0; -+ IfSet = Op0Op1; -+ -+ if (isVSplat(Op1Op0, InvMask) && -+ Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) -+ IfClr = Op1Op1; -+ else if (isVSplat(Op1Op1, InvMask) && -+ Mask.getBitWidth() == InvMask.getBitWidth() && -+ Mask == ~InvMask) -+ IfClr = Op1Op0; -+ -+ IsConstantMask = true; -+ } -+ -+ // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the -+ // same thing again using this mask. IfClr will be set if we find a valid -+ // match. -+ if (!IfClr.getNode() && isVSplat(Op0Op1, Mask)) { -+ Cond = Op0Op1; -+ IfSet = Op0Op0; -+ -+ if (isVSplat(Op1Op0, InvMask) && -+ Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) -+ IfClr = Op1Op1; -+ else if (isVSplat(Op1Op1, InvMask) && -+ Mask.getBitWidth() == InvMask.getBitWidth() && -+ Mask == ~InvMask) -+ IfClr = Op1Op0; -+ -+ IsConstantMask = true; -+ } -+ -+ // If IfClr is not yet set, try looking for a non-constant match. -+ // IfClr will be set if we find a valid match amongst the eight -+ // possibilities. -+ if (!IfClr.getNode()) { -+ if (isBitwiseInverse(Op0Op0, Op1Op0)) { -+ Cond = Op1Op0; -+ IfSet = Op1Op1; -+ IfClr = Op0Op1; -+ } else if (isBitwiseInverse(Op0Op1, Op1Op0)) { -+ Cond = Op1Op0; -+ IfSet = Op1Op1; -+ IfClr = Op0Op0; -+ } else if (isBitwiseInverse(Op0Op0, Op1Op1)) { -+ Cond = Op1Op1; -+ IfSet = Op1Op0; -+ IfClr = Op0Op1; -+ } else if (isBitwiseInverse(Op0Op1, Op1Op1)) { -+ Cond = Op1Op1; -+ IfSet = Op1Op0; -+ IfClr = Op0Op0; -+ } else if (isBitwiseInverse(Op1Op0, Op0Op0)) { -+ Cond = Op0Op0; -+ IfSet = Op0Op1; -+ IfClr = Op1Op1; -+ } else if (isBitwiseInverse(Op1Op1, Op0Op0)) { -+ Cond = Op0Op0; -+ IfSet = Op0Op1; -+ IfClr = Op1Op0; -+ } else if (isBitwiseInverse(Op1Op0, Op0Op1)) { -+ Cond = Op0Op1; -+ IfSet = Op0Op0; -+ IfClr = Op1Op1; -+ } else if (isBitwiseInverse(Op1Op1, Op0Op1)) { -+ Cond = Op0Op1; -+ IfSet = Op0Op0; -+ IfClr = Op1Op0; -+ } -+ } -+ -+ // At this point, IfClr will be set if we have a valid match. -+ if (IfClr.getNode()) { -+ assert(Cond.getNode() && IfSet.getNode()); -+ -+ // Fold degenerate cases. -+ if (IsConstantMask) { -+ if (Mask.isAllOnesValue()) -+ return IfSet; -+ else if (Mask == 0) -+ return IfClr; -+ } -+ -+ // Transform the DAG into an equivalent VSELECT. -+ return DAG.getNode(ISD::VSELECT, SDLoc(N), N->getValueType(0), Cond, -+ IfSet, IfClr); -+ } -+ } -+ -+ if (Res = performSet(N, DAG, DCI, Subtarget)) -+ return Res; -+ } -+ -+ // Pattern match BSTRINS. -+ // $dst = or (and $src1 , mask0), (and (shl $src, lsb), mask1), -+ // where mask1 = (2**size - 1) << lsb, mask0 = ~mask1 -+ // => bstrins $dst, $src, lsb+size-1, lsb, $src1 - if (DCI.isBeforeLegalizeOps()) - return SDValue(); - -- if (ValBits != 32 && ValBits != 64) -+ SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); -+ uint64_t SMLsb0, SMSize0, SMLsb1, SMSize1; -+ ConstantSDNode *CN, *CN1; -+ -+ // See if Op's first operand matches (and $src1 , mask0). -+ if (And0.getOpcode() != ISD::AND) - return SDValue(); - --Retry: -- // 1st pattern to match BSTRINS: -- // R = or (and X, mask0), (and (shl Y, lsb), mask1) -- // where mask1 = (2**size - 1) << lsb, mask0 = ~mask1 -- // => -- // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) -- if (N0.getOpcode() == ISD::AND && -- (CN0 = dyn_cast(N0.getOperand(1))) && -- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && -- N1.getOpcode() == ISD::AND && N1.getOperand(0).getOpcode() == ISD::SHL && -- (CN1 = dyn_cast(N1.getOperand(1))) && -- isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && -- MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 && -- (CN1 = dyn_cast(N1.getOperand(0).getOperand(1))) && -- (Shamt = CN1->getZExtValue()) == MaskIdx0 && -- (MaskIdx0 + MaskLen0 <= ValBits)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 1\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), -- N1.getOperand(0).getOperand(0), -- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), -- DAG.getConstant(MaskIdx0, DL, GRLenVT)); -- } -- -- // 2nd pattern to match BSTRINS: -- // R = or (and X, mask0), (shl (and Y, mask1), lsb) -- // where mask1 = (2**size - 1), mask0 = ~(mask1 << lsb) -- // => -- // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) -- if (N0.getOpcode() == ISD::AND && -- (CN0 = dyn_cast(N0.getOperand(1))) && -- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && -- N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && -- (CN1 = dyn_cast(N1.getOperand(1))) && -- (Shamt = CN1->getZExtValue()) == MaskIdx0 && -- (CN1 = dyn_cast(N1.getOperand(0).getOperand(1))) && -- isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && -- MaskLen0 == MaskLen1 && MaskIdx1 == 0 && -- (MaskIdx0 + MaskLen0 <= ValBits)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 2\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), -- N1.getOperand(0).getOperand(0), -- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), -- DAG.getConstant(MaskIdx0, DL, GRLenVT)); -- } -- -- // 3rd pattern to match BSTRINS: -- // R = or (and X, mask0), (and Y, mask1) -- // where ~mask0 = (2**size - 1) << lsb, mask0 & mask1 = 0 -- // => -- // R = BSTRINS X, (shr (and Y, mask1), lsb), msb, lsb -- // where msb = lsb + size - 1 -- if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::AND && -- (CN0 = dyn_cast(N0.getOperand(1))) && -- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && -- (MaskIdx0 + MaskLen0 <= 64) && -- (CN1 = dyn_cast(N1->getOperand(1))) && -- (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 3\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), -- DAG.getNode(ISD::SRL, DL, N1->getValueType(0), N1, -- DAG.getConstant(MaskIdx0, DL, GRLenVT)), -- DAG.getConstant(ValBits == 32 -- ? (MaskIdx0 + (MaskLen0 & 31) - 1) -- : (MaskIdx0 + MaskLen0 - 1), -- DL, GRLenVT), -- DAG.getConstant(MaskIdx0, DL, GRLenVT)); -- } -- -- // 4th pattern to match BSTRINS: -- // R = or (and X, mask), (shl Y, shamt) -- // where mask = (2**shamt - 1) -- // => -- // R = BSTRINS X, Y, ValBits - 1, shamt -- // where ValBits = 32 or 64 -- if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::SHL && -- (CN0 = dyn_cast(N0.getOperand(1))) && -- isShiftedMask_64(CN0->getZExtValue(), MaskIdx0, MaskLen0) && -- MaskIdx0 == 0 && (CN1 = dyn_cast(N1.getOperand(1))) && -- (Shamt = CN1->getZExtValue()) == MaskLen0 && -- (MaskIdx0 + MaskLen0 <= ValBits)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 4\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), -- N1.getOperand(0), -- DAG.getConstant((ValBits - 1), DL, GRLenVT), -- DAG.getConstant(Shamt, DL, GRLenVT)); -- } -- -- // 5th pattern to match BSTRINS: -- // R = or (and X, mask), const -- // where ~mask = (2**size - 1) << lsb, mask & const = 0 -- // => -- // R = BSTRINS X, (const >> lsb), msb, lsb -- // where msb = lsb + size - 1 -- if (N0.getOpcode() == ISD::AND && -- (CN0 = dyn_cast(N0.getOperand(1))) && -- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && -- (CN1 = dyn_cast(N1)) && -- (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n"); -- return DAG.getNode( -- LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), -- DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy), -- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), -- DAG.getConstant(MaskIdx0, DL, GRLenVT)); -- } -- -- // 6th pattern. -- // a = b | ((c & mask) << shamt), where all positions in b to be overwritten -- // by the incoming bits are known to be zero. -- // => -- // a = BSTRINS b, c, shamt + MaskLen - 1, shamt -- // -- // Note that the 1st pattern is a special situation of the 6th, i.e. the 6th -- // pattern is more common than the 1st. So we put the 1st before the 6th in -- // order to match as many nodes as possible. -- ConstantSDNode *CNMask, *CNShamt; -- unsigned MaskIdx, MaskLen; -- if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && -- (CNMask = dyn_cast(N1.getOperand(0).getOperand(1))) && -- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && -- MaskIdx == 0 && (CNShamt = dyn_cast(N1.getOperand(1))) && -- CNShamt->getZExtValue() + MaskLen <= ValBits) { -- Shamt = CNShamt->getZExtValue(); -- APInt ShMask(ValBits, CNMask->getZExtValue() << Shamt); -- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 6\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, -- N1.getOperand(0).getOperand(0), -- DAG.getConstant(Shamt + MaskLen - 1, DL, GRLenVT), -- DAG.getConstant(Shamt, DL, GRLenVT)); -+ if (!(CN = dyn_cast(And0.getOperand(1))) || -+ !isShiftedMask(~CN->getSExtValue(), SMLsb0, SMSize0)) -+ return SDValue(); -+ -+ // See if Op's second operand matches (and (shl $src, lsb), mask1). -+ if (And1.getOpcode() == ISD::AND && -+ And1.getOperand(0).getOpcode() == ISD::SHL) { -+ -+ if (!(CN = dyn_cast(And1.getOperand(1))) || -+ !isShiftedMask(CN->getZExtValue(), SMLsb1, SMSize1)) -+ return SDValue(); -+ -+ // The shift masks must have the same least significant bit and size. -+ if (SMLsb0 != SMLsb1 || SMSize0 != SMSize1) -+ return SDValue(); -+ -+ SDValue Shl = And1.getOperand(0); -+ -+ if (!(CN = dyn_cast(Shl.getOperand(1)))) -+ return SDValue(); -+ -+ unsigned Shamt = CN->getZExtValue(); -+ -+ // Return if the shift amount and the first bit position of mask are not the -+ // same. -+ EVT ValTy = N->getValueType(0); -+ if ((Shamt != SMLsb0) || (SMLsb0 + SMSize0 > ValTy.getSizeInBits())) -+ return SDValue(); -+ -+ SDLoc DL(N); -+ return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, Shl.getOperand(0), -+ DAG.getConstant((SMLsb0 + SMSize0 - 1), DL, MVT::i32), -+ DAG.getConstant(SMLsb0, DL, MVT::i32), -+ And0.getOperand(0)); -+ } else { -+ // Pattern match BSTRINS. -+ // $dst = or (and $src, mask0), mask1 -+ // where mask0 = ((1 << SMSize0) -1) << SMLsb0 -+ // => bstrins $dst, $src, SMLsb0+SMSize0-1, SMLsb0 -+ if (~CN->getSExtValue() == ((((int64_t)1 << SMSize0) - 1) << SMLsb0) && -+ (SMSize0 + SMLsb0 <= 64)) { -+ // Check if AND instruction has constant as argument -+ bool isConstCase = And1.getOpcode() != ISD::AND; -+ if (And1.getOpcode() == ISD::AND) { -+ if (!(CN1 = dyn_cast(And1->getOperand(1)))) -+ return SDValue(); -+ } else { -+ if (!(CN1 = dyn_cast(N->getOperand(1)))) -+ return SDValue(); -+ } -+ // Don't generate BSTRINS if constant OR operand doesn't fit into bits -+ // cleared by constant AND operand. -+ if (CN->getSExtValue() & CN1->getSExtValue()) -+ return SDValue(); -+ -+ SDLoc DL(N); -+ EVT ValTy = N->getOperand(0)->getValueType(0); -+ SDValue Const1; -+ SDValue SrlX; -+ if (!isConstCase) { -+ Const1 = DAG.getConstant(SMLsb0, DL, MVT::i32); -+ SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1); -+ } -+ return DAG.getNode( -+ LoongArchISD::BSTRINS, DL, N->getValueType(0), -+ isConstCase -+ ? DAG.getConstant(CN1->getSExtValue() >> SMLsb0, DL, ValTy) -+ : SrlX, -+ DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? (SMLsb0 + (SMSize0 & 31) - 1) -+ : (SMLsb0 + SMSize0 - 1), -+ DL, MVT::i32), -+ DAG.getConstant(SMLsb0, DL, MVT::i32), -+ And0->getOperand(0)); -+ - } -+ return SDValue(); - } -+} - -- // 7th pattern. -- // a = b | ((c << shamt) & shifted_mask), where all positions in b to be -- // overwritten by the incoming bits are known to be zero. -- // => -- // a = BSTRINS b, c, MaskIdx + MaskLen - 1, MaskIdx -+static bool -+shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, -+ SelectionDAG &DAG, -+ const LoongArchSubtarget &Subtarget) { -+ // Estimate the number of operations the below transform will turn a -+ // constant multiply into. The number is approximately equal to the minimal -+ // number of powers of two that constant can be broken down to by adding -+ // or subtracting them. -+ // -+ // If we have taken more than 10[1] / 8[2] steps to attempt the -+ // optimization for a native sized value, it is more than likely that this -+ // optimization will make things worse. -+ // -+ // [1] LA64 requires 4 instructions at most to materialize any constant, -+ // multiplication requires at least 4 cycles, but another cycle (or two) -+ // to retrieve the result from corresponding registers. -+ // -+ // [2] LA32 requires 2 instructions at most to materialize any constant, -+ // multiplication requires at least 4 cycles, but another cycle (or two) -+ // to retrieve the result from corresponding registers. - // -- // Similarly, the 7th pattern is more common than the 2nd. So we put the 2nd -- // before the 7th in order to match as many nodes as possible. -- if (N1.getOpcode() == ISD::AND && -- (CNMask = dyn_cast(N1.getOperand(1))) && -- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && -- N1.getOperand(0).getOpcode() == ISD::SHL && -- (CNShamt = dyn_cast(N1.getOperand(0).getOperand(1))) && -- CNShamt->getZExtValue() == MaskIdx) { -- APInt ShMask(ValBits, CNMask->getZExtValue()); -- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 7\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, -- N1.getOperand(0).getOperand(0), -- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), -- DAG.getConstant(MaskIdx, DL, GRLenVT)); -+ // TODO: -+ // - MaxSteps needs to consider the `VT` of the constant for the current -+ // target. -+ // - Consider to perform this optimization after type legalization. -+ // That allows to remove a workaround for types not supported natively. -+ // - Take in account `-Os, -Oz` flags because this optimization -+ // increases code size. -+ unsigned MaxSteps = Subtarget.isABI_LP32() ? 8 : 10; -+ -+ SmallVector WorkStack(1, C); -+ unsigned Steps = 0; -+ unsigned BitWidth = C.getBitWidth(); -+ -+ while (!WorkStack.empty()) { -+ APInt Val = WorkStack.pop_back_val(); -+ -+ if (Val == 0 || Val == 1) -+ continue; -+ -+ if (Steps >= MaxSteps) -+ return false; -+ -+ if (Val.isPowerOf2()) { -+ ++Steps; -+ continue; - } -- } - -- // (or a, b) and (or b, a) are equivalent, so swap the operands and retry. -- if (!SwapAndRetried) { -- std::swap(N0, N1); -- SwapAndRetried = true; -- goto Retry; -- } -+ APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); -+ APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) -+ : APInt(BitWidth, 1) << C.ceilLogBase2(); - -- SwapAndRetried = false; --Retry2: -- // 8th pattern. -- // a = b | (c & shifted_mask), where all positions in b to be overwritten by -- // the incoming bits are known to be zero. -- // => -- // a = BSTRINS b, c >> MaskIdx, MaskIdx + MaskLen - 1, MaskIdx -- // -- // Similarly, the 8th pattern is more common than the 4th and 5th patterns. So -- // we put it here in order to match as many nodes as possible or generate less -- // instructions. -- if (N1.getOpcode() == ISD::AND && -- (CNMask = dyn_cast(N1.getOperand(1))) && -- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen)) { -- APInt ShMask(ValBits, CNMask->getZExtValue()); -- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { -- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 8\n"); -- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, -- DAG.getNode(ISD::SRL, DL, N1->getValueType(0), -- N1->getOperand(0), -- DAG.getConstant(MaskIdx, DL, GRLenVT)), -- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), -- DAG.getConstant(MaskIdx, DL, GRLenVT)); -+ if ((Val - Floor).ule(Ceil - Val)) { -+ WorkStack.push_back(Floor); -+ WorkStack.push_back(Val - Floor); -+ } else { -+ WorkStack.push_back(Ceil); -+ WorkStack.push_back(Ceil - Val); - } -- } -- // Swap N0/N1 and retry. -- if (!SwapAndRetried) { -- std::swap(N0, N1); -- SwapAndRetried = true; -- goto Retry2; -+ -+ ++Steps; - } - -- return SDValue(); --} -+ // If the value being multiplied is not supported natively, we have to pay -+ // an additional legalization cost, conservatively assume an increase in the -+ // cost of 3 instructions per step. This values for this heuristic were -+ // determined experimentally. -+ unsigned RegisterSize = DAG.getTargetLoweringInfo() -+ .getRegisterType(*DAG.getContext(), VT) -+ .getSizeInBits(); -+ Steps *= (VT.getSizeInBits() != RegisterSize) * 3; -+ if (Steps > 27) -+ return false; - --SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N, -- DAGCombinerInfo &DCI) const { -- SelectionDAG &DAG = DCI.DAG; -- switch (N->getOpcode()) { -+ return true; -+} -+ -+static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT, -+ EVT ShiftTy, SelectionDAG &DAG) { -+ // Return 0. -+ if (C == 0) -+ return DAG.getConstant(0, DL, VT); -+ -+ // Return x. -+ if (C == 1) -+ return X; -+ -+ // If c is power of 2, return (shl x, log2(c)). -+ if (C.isPowerOf2()) -+ return DAG.getNode(ISD::SHL, DL, VT, X, -+ DAG.getConstant(C.logBase2(), DL, ShiftTy)); -+ -+ unsigned BitWidth = C.getBitWidth(); -+ APInt Floor = APInt(BitWidth, 1) << C.logBase2(); -+ APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) : -+ APInt(BitWidth, 1) << C.ceilLogBase2(); -+ -+ // If |c - floor_c| <= |c - ceil_c|, -+ // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))), -+ // return (add constMult(x, floor_c), constMult(x, c - floor_c)). -+ if ((C - Floor).ule(Ceil - C)) { -+ SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG); -+ SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG); -+ return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1); -+ } -+ -+ // If |c - floor_c| > |c - ceil_c|, -+ // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)). -+ SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG); -+ SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG); -+ return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1); -+} -+ -+static SDValue performLogicCombine(SDNode *N, SelectionDAG &DAG, -+ const LoongArchSubtarget &Subtarget) { -+ -+ SDLoc DL(N); -+ SDValue N0 = N->getOperand(0); -+ SDValue N1 = N->getOperand(1); -+ -+ if (!(N0->getOpcode() == ISD::TRUNCATE && N1->getOpcode() == ISD::TRUNCATE)) -+ return SDValue(); -+ -+ if (!(N->getValueType(0).isSimple() && N0->getValueType(0).isSimple() && -+ N1->getValueType(0).isSimple() && -+ N0->getOperand(0)->getValueType(0).isSimple() && -+ N1->getOperand(0)->getValueType(0).isSimple())) -+ return SDValue(); -+ -+ if (!(N->getValueType(0).isSimple() && N0->getValueType(0).isSimple() && -+ N1->getValueType(0).isSimple() && -+ N0->getOperand(0)->getValueType(0).isSimple() && -+ N1->getOperand(0)->getValueType(0).isSimple())) -+ return SDValue(); -+ -+ if (!(N->getSimpleValueType(0).SimpleTy == MVT::i32 && -+ N0->getSimpleValueType(0).SimpleTy == MVT::i32 && -+ N1->getSimpleValueType(0).SimpleTy == MVT::i32)) -+ return SDValue(); -+ -+ if (!(N0->getOperand(0)->getSimpleValueType(0).SimpleTy == MVT::i64 && -+ N1->getOperand(0)->getSimpleValueType(0).SimpleTy == MVT::i64)) -+ return SDValue(); -+ -+ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); -+ SDValue Val0 = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, -+ N0->getValueType(0), -+ N0->getOperand(0), SubReg), -+ 0); -+ SDValue Val1 = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, -+ N1->getValueType(0), -+ N1->getOperand(0), SubReg), -+ 0); -+ -+ return DAG.getNode(N->getOpcode(), DL, N0->getValueType(0), Val0, Val1); -+} -+ -+static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, -+ const TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchTargetLowering *TL, -+ const LoongArchSubtarget &Subtarget) { -+ EVT VT = N->getValueType(0); -+ -+ SDValue Res; -+ if ((Res = performLogicCombine(N, DAG, Subtarget))) -+ return Res; -+ -+ if (ConstantSDNode *C = dyn_cast(N->getOperand(1))) -+ if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs( -+ C->getAPIntValue(), VT, DAG, Subtarget)) -+ return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT, -+ TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT), -+ DAG); -+ -+ return SDValue(N, 0); -+} -+ -+// Fold sign-extensions into LoongArchISD::VEXTRACT_[SZ]EXT_ELT for LSX. -+// -+// Performs the following transformations: -+// - Changes LoongArchISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its -+// sign/zero-extension is completely overwritten by the new one performed by -+// the ISD::SRA and ISD::SHL nodes. -+// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL -+// sequence. -+static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ SDValue Res; -+ if ((Res = performLogicCombine(N, DAG, Subtarget))) -+ return Res; -+ -+ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { -+ SDValue Op0 = N->getOperand(0); -+ SDValue Op1 = N->getOperand(1); -+ -+ // (sra (shl (LoongArchVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d) -+ // where $d + sizeof($c) == 32 -+ // or $d + sizeof($c) <= 32 and SExt -+ // -> (LoongArchVExtractSExt $a, $b, $c) -+ if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) { -+ SDValue Op0Op0 = Op0->getOperand(0); -+ ConstantSDNode *ShAmount = dyn_cast(Op1); -+ -+ if (!ShAmount) -+ return SDValue(); -+ -+ if (Op0Op0->getOpcode() != LoongArchISD::VEXTRACT_SEXT_ELT && -+ Op0Op0->getOpcode() != LoongArchISD::VEXTRACT_ZEXT_ELT) -+ return SDValue(); -+ -+ EVT ExtendTy = cast(Op0Op0->getOperand(2))->getVT(); -+ unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits(); -+ -+ if (TotalBits == 32 || -+ (Op0Op0->getOpcode() == LoongArchISD::VEXTRACT_SEXT_ELT && -+ TotalBits <= 32)) { -+ SDValue Ops[] = {Op0Op0->getOperand(0), Op0Op0->getOperand(1), -+ Op0Op0->getOperand(2)}; -+ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0), -+ Op0Op0->getVTList(), -+ makeArrayRef(Ops, Op0Op0->getNumOperands())); -+ } -+ } -+ } -+ -+ return SDValue(); -+} -+ -+// combine vsub/vslt/vbitsel.v to vabsd -+static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { -+ assert((N->getOpcode() == ISD::VSELECT) && "Need ISD::VSELECT"); -+ -+ SDLoc dl(N); -+ SDValue Cond = N->getOperand(0); -+ SDValue TrueOpnd = N->getOperand(1); -+ SDValue FalseOpnd = N->getOperand(2); -+ -+ if (Cond.getOpcode() != ISD::SETCC || TrueOpnd.getOpcode() != ISD::SUB || -+ FalseOpnd.getOpcode() != ISD::SUB) -+ return SDValue(); -+ -+ if (!(Cond.hasOneUse() || TrueOpnd.hasOneUse() || FalseOpnd.hasOneUse())) -+ return SDValue(); -+ -+ ISD::CondCode CC = cast(Cond.getOperand(2))->get(); -+ -+ switch (CC) { - default: -+ return SDValue(); -+ case ISD::SETUGT: -+ case ISD::SETUGE: -+ case ISD::SETGT: -+ case ISD::SETGE: -+ break; -+ case ISD::SETULT: -+ case ISD::SETULE: -+ case ISD::SETLT: -+ case ISD::SETLE: -+ std::swap(TrueOpnd, FalseOpnd); - break; -+ } -+ -+ SDValue Op1 = Cond.getOperand(0); -+ SDValue Op2 = Cond.getOperand(1); -+ -+ if (TrueOpnd.getOperand(0) == Op1 && TrueOpnd.getOperand(1) == Op2 && -+ FalseOpnd.getOperand(0) == Op2 && FalseOpnd.getOperand(1) == Op1) { -+ if (ISD::isSignedIntSetCC(CC)) { -+ return DAG.getNode(LoongArchISD::VABSD, dl, -+ N->getOperand(1).getValueType(), Op1, Op2, -+ DAG.getTargetConstant(0, dl, MVT::i32)); -+ } else { -+ return DAG.getNode(LoongArchISD::UVABSD, dl, -+ N->getOperand(1).getValueType(), Op1, Op2, -+ DAG.getTargetConstant(0, dl, MVT::i32)); -+ } -+ } -+ return SDValue(); -+} -+ -+static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, -+ const LoongArchSubtarget &Subtarget) { -+ -+ EVT Ty = N->getValueType(0); -+ -+ if ((Subtarget.hasLSX() && Ty.is128BitVector() && Ty.isInteger()) || -+ (Subtarget.hasLASX() && Ty.is256BitVector() && Ty.isInteger())) { -+ // Try the following combines: -+ // (xor (or $a, $b), (build_vector allones)) -+ // (xor (or $a, $b), (bitcast (build_vector allones))) -+ SDValue Op0 = N->getOperand(0); -+ SDValue Op1 = N->getOperand(1); -+ SDValue NotOp; -+ -+ if (ISD::isBuildVectorAllOnes(Op0.getNode())) -+ NotOp = Op1; -+ else if (ISD::isBuildVectorAllOnes(Op1.getNode())) -+ NotOp = Op0; -+ else -+ return SDValue(); -+ -+ if (NotOp->getOpcode() == ISD::OR) -+ return DAG.getNode(LoongArchISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0), -+ NotOp->getOperand(1)); -+ } -+ -+ return SDValue(); -+} -+ -+// When using a 256-bit vector is less expensive than using a 128-bit vector, -+// use this function to convert a 128-bit vector to a 256-bit vector. -+static SDValue -+performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ assert((N->getOpcode() == ISD::CONCAT_VECTORS) && "Need ISD::CONCAT_VECTORS"); -+ if (DCI.isAfterLegalizeDAG()) -+ return SDValue(); -+ -+ SDLoc DL(N); -+ SDValue Top0 = N->getOperand(0); -+ SDValue Top1 = N->getOperand(1); -+ -+ // Check for cheaper optimizations. -+ if (!((Top0->getOpcode() == ISD::SIGN_EXTEND) && -+ (Top1->getOpcode() == ISD::SIGN_EXTEND))) -+ return SDValue(); -+ if (!((Top0->getOperand(0)->getOpcode() == ISD::ADD) && -+ (Top1->getOperand(0)->getOpcode() == ISD::ADD))) -+ return SDValue(); -+ -+ SDValue Op_a0 = Top0->getOperand(0); -+ SDValue Op_a1 = Top1->getOperand(0); -+ for (int i = 0; i < 2; i++) { -+ if (!((Op_a0->getOperand(i)->getOpcode() == ISD::BUILD_VECTOR) && -+ (Op_a1->getOperand(i)->getOpcode() == ISD::BUILD_VECTOR))) -+ return SDValue(); -+ } -+ -+ SDValue Ops_b[] = {Op_a0->getOperand(0), Op_a0->getOperand(1), -+ Op_a1->getOperand(0), Op_a1->getOperand(1)}; -+ for (int i = 0; i < 4; i++) { -+ if (Ops_b[i]->getNumOperands() != 2) -+ return SDValue(); -+ } -+ -+ // Currently only a single case is handled, and more optimization scenarios -+ // will be added in the future. -+ SDValue Ops_e[] = {Ops_b[0]->getOperand(0), Ops_b[0]->getOperand(1), -+ Ops_b[2]->getOperand(0), Ops_b[2]->getOperand(1), -+ Ops_b[1]->getOperand(0), Ops_b[1]->getOperand(1), -+ Ops_b[3]->getOperand(0), Ops_b[3]->getOperand(1)}; -+ for (int i = 0; i < 8; i++) { -+ if (dyn_cast(Ops_e[i])) -+ return SDValue(); -+ if (i < 4) { -+ if (cast(Ops_e[i]->getOperand(1))->getSExtValue() != -+ (2 * i)) -+ return SDValue(); -+ } else { -+ if (cast(Ops_e[i]->getOperand(1))->getSExtValue() != -+ (2 * i - 7)) -+ return SDValue(); -+ } -+ } -+ -+ for (int i = 0; i < 5; i = i + 4) { -+ if (!((Ops_e[i]->getOperand(0) == Ops_e[i + 1]->getOperand(0)) && -+ (Ops_e[i + 1]->getOperand(0) == Ops_e[i + 2]->getOperand(0)) && -+ (Ops_e[i + 2]->getOperand(0) == Ops_e[i + 3]->getOperand(0)))) -+ return SDValue(); -+ } -+ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_D_W, DL, MVT::v4i64, -+ Ops_e[6]->getOperand(0), -+ Ops_e[0]->getOperand(0)), -+ 0); -+} -+ -+static SDValue performParity(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ SDLoc DL(N); -+ SDValue T = N->getOperand(0); -+ if (!(N->getValueType(0).isSimple() && T->getValueType(0).isSimple())) -+ return SDValue(); -+ -+ if (DCI.isAfterLegalizeDAG()) -+ return SDValue(); -+ -+ SDValue Ops[4]; -+ bool pos_e = false; -+ bool pos_o = false; -+ -+ for (int i = 0; i < 4; i++) { -+ Ops[i] = T->getOperand(i); -+ if (!Ops[i]->getValueType(0).isSimple()) -+ return SDValue(); -+ if (Ops[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT) -+ return SDValue(); -+ -+ if (!dyn_cast(Ops[i]->getOperand(1))) -+ return SDValue(); -+ -+ if (cast(Ops[i]->getOperand(1))->getSExtValue() == -+ (2 * i)) { -+ pos_e = true; -+ } else if (cast(Ops[i]->getOperand(1))->getSExtValue() == -+ (2 * i + 1)) { -+ pos_o = true; -+ } else -+ return SDValue(); -+ } -+ -+ if (!(N->getSimpleValueType(0).SimpleTy == MVT::v4i64 && -+ T->getSimpleValueType(0).SimpleTy == MVT::v4i32)) -+ return SDValue(); -+ -+ for (int j = 0; j < 3; j++) { -+ if (Ops[j]->getOperand(0) != Ops[j + 1]->getOperand(0)) -+ return SDValue(); -+ } -+ if (pos_e) { -+ if (N->getOpcode() == ISD::SIGN_EXTEND) { -+ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVADDWEV_D_W, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(1), -+ Ops[0]->getOperand(0)->getOperand(0)), -+ 0); -+ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWEV_D_W, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(0), -+ Ops[0]->getOperand(0)->getOperand(1)), -+ 0); -+ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { -+ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVADDWEV_D_WU, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(1), -+ Ops[0]->getOperand(0)->getOperand(0)), -+ 0); -+ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWEV_D_WU, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(0), -+ Ops[0]->getOperand(0)->getOperand(1)), -+ 0); -+ } -+ } else if (pos_o) { -+ if (N->getOpcode() == ISD::SIGN_EXTEND) { -+ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVADDWOD_D_W, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(1), -+ Ops[0]->getOperand(0)->getOperand(0)), -+ 0); -+ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWOD_D_W, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(0), -+ Ops[0]->getOperand(0)->getOperand(1)), -+ 0); -+ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { -+ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVADDWOD_D_WU, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(1), -+ Ops[0]->getOperand(0)->getOperand(0)), -+ 0); -+ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWOD_D_WU, DL, -+ MVT::v4i64, -+ Ops[0]->getOperand(0)->getOperand(0), -+ Ops[0]->getOperand(0)->getOperand(1)), -+ 0); -+ } -+ } else -+ return SDValue(); -+ -+ return SDValue(); -+} -+ -+// Optimize zero extension and sign extension of data -+static SDValue performExtend(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ if (!Subtarget.hasLASX()) -+ return SDValue(); -+ -+ SDLoc DL(N); -+ SDValue T = N->getOperand(0); -+ -+ if (T->getOpcode() == ISD::BUILD_VECTOR) -+ return performParity(N, DAG, DCI, Subtarget); -+ -+ if (T->getOpcode() != ISD::ADD && T->getOpcode() != ISD::SUB) -+ return SDValue(); -+ -+ SDValue T0 = T->getOperand(0); -+ SDValue T1 = T->getOperand(1); -+ -+ if (!(T0->getOpcode() == ISD::BUILD_VECTOR && -+ T1->getOpcode() == ISD::BUILD_VECTOR)) -+ return SDValue(); -+ -+ if (DCI.isAfterLegalizeDAG()) -+ return SDValue(); -+ -+ if (!(T->getValueType(0).isSimple() && T0->getValueType(0).isSimple() && -+ T1->getValueType(0).isSimple() && N->getValueType(0).isSimple())) -+ return SDValue(); -+ -+ if (!(N->getSimpleValueType(0).SimpleTy == MVT::v4i64 && -+ T->getSimpleValueType(0).SimpleTy == MVT::v4i32 && -+ T0->getSimpleValueType(0).SimpleTy == MVT::v4i32 && -+ T1->getSimpleValueType(0).SimpleTy == MVT::v4i32)) -+ return SDValue(); -+ -+ SDValue Opse0[4]; -+ SDValue Opse1[4]; -+ -+ for (int i = 0; i < 4; i++) { -+ if (T->getOpcode() == ISD::ADD) { -+ Opse0[i] = T1->getOperand(i); -+ Opse1[i] = T0->getOperand(i); -+ } else if (T->getOpcode() == ISD::SUB) { -+ Opse0[i] = T0->getOperand(i); -+ Opse1[i] = T1->getOperand(i); -+ } -+ -+ if (Opse0[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT || -+ Opse1[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT) -+ return SDValue(); -+ -+ if (!(dyn_cast(Opse0[i]->getOperand(1)) && -+ dyn_cast(Opse1[i]->getOperand(1)))) -+ return SDValue(); -+ -+ if (cast(Opse0[i]->getOperand(1))->getSExtValue() != -+ (2 * i + 1) || -+ cast(Opse1[i]->getOperand(1))->getSExtValue() != -+ (2 * i)) -+ return SDValue(); -+ -+ if (i > 0 && (Opse0[i]->getOperand(0) != Opse0[i - 1]->getOperand(0) || -+ Opse1[i]->getOperand(0) != Opse1[i - 1]->getOperand(0))) -+ return SDValue(); -+ } -+ -+ if (N->getOpcode() == ISD::SIGN_EXTEND) { -+ if (T->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_D_W, DL, MVT::v4i64, -+ Opse0[0]->getOperand(0), -+ Opse1[0]->getOperand(0)), -+ 0); -+ else if (T->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVHSUBW_D_W, DL, MVT::v4i64, -+ Opse0[0]->getOperand(0), -+ Opse1[0]->getOperand(0)), -+ 0); -+ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { -+ if (T->getOpcode() == ISD::ADD) -+ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_DU_WU, DL, -+ MVT::v4i64, Opse0[0]->getOperand(0), -+ Opse1[0]->getOperand(0)), -+ 0); -+ else if (T->getOpcode() == ISD::SUB) -+ return SDValue(DAG.getMachineNode(LoongArch::XVHSUBW_DU_WU, DL, -+ MVT::v4i64, Opse0[0]->getOperand(0), -+ Opse1[0]->getOperand(0)), -+ 0); -+ } -+ -+ return SDValue(); -+} -+ -+static SDValue performSIGN_EXTENDCombine(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ assert((N->getOpcode() == ISD::SIGN_EXTEND) && "Need ISD::SIGN_EXTEND"); -+ -+ SDLoc DL(N); -+ SDValue Top = N->getOperand(0); -+ -+ SDValue Res; -+ if (Res = performExtend(N, DAG, DCI, Subtarget)) -+ return Res; -+ -+ if (!(Top->getOpcode() == ISD::CopyFromReg)) -+ return SDValue(); -+ -+ if ((Top->getOperand(0)->getOpcode() == ISD::EntryToken) && -+ (N->getValueType(0) == MVT::i64)) { -+ -+ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); -+ SDNode *Res = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64); -+ -+ Res = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::i64, -+ SDValue(Res, 0), Top, SubReg); -+ -+ return SDValue(Res, 0); -+ } -+ -+ return SDValue(); -+} -+ -+static SDValue performZERO_EXTENDCombine(SDNode *N, SelectionDAG &DAG, -+ TargetLowering::DAGCombinerInfo &DCI, -+ const LoongArchSubtarget &Subtarget) { -+ -+ assert((N->getOpcode() == ISD::ZERO_EXTEND) && "Need ISD::ZERO_EXTEND"); -+ -+ SDLoc DL(N); -+ -+ SDValue Res; -+ if (Res = performExtend(N, DAG, DCI, Subtarget)) -+ return Res; -+ -+ return SDValue(); -+} -+ -+SDValue LoongArchTargetLowering:: -+PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { -+ SelectionDAG &DAG = DCI.DAG; -+ SDValue Val; -+ -+ switch (N->getOpcode()) { -+ default: break; - case ISD::AND: - return performANDCombine(N, DAG, DCI, Subtarget); - case ISD::OR: - return performORCombine(N, DAG, DCI, Subtarget); -+ case ISD::XOR: -+ return performXORCombine(N, DAG, Subtarget); -+ case ISD::MUL: -+ return performMULCombine(N, DAG, DCI, this, Subtarget); -+ case ISD::SRA: -+ return performSRACombine(N, DAG, DCI, Subtarget); -+ case ISD::SELECT: -+ return performSELECTCombine(N, DAG, DCI, Subtarget); -+ case ISD::VSELECT: -+ return performVSELECTCombine(N, DAG); -+ case ISD::CONCAT_VECTORS: -+ return performCONCAT_VECTORSCombine(N, DAG, DCI, Subtarget); -+ case ISD::SIGN_EXTEND: -+ return performSIGN_EXTENDCombine(N, DAG, DCI, Subtarget); -+ case ISD::ZERO_EXTEND: -+ return performZERO_EXTENDCombine(N, DAG, DCI, Subtarget); -+ case ISD::ADD: -+ case ISD::SUB: -+ case ISD::SHL: - case ISD::SRL: -- return performSRLCombine(N, DAG, DCI, Subtarget); -+ return performLogicCombine(N, DAG, Subtarget); -+ } -+ return SDValue(); -+} -+ -+static SDValue lowerLSXSplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { -+ EVT ResVecTy = Op->getValueType(0); -+ EVT ViaVecTy = ResVecTy; -+ SDLoc DL(Op); -+ -+ // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and -+ // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating -+ // lanes. -+ SDValue LaneA = Op->getOperand(OpNr); -+ SDValue LaneB; -+ -+ if (ResVecTy == MVT::v2i64) { -+ // In case of the index being passed as an immediate value, set the upper -+ // lane to 0 so that the splati.d instruction can be matched. -+ if (isa(LaneA)) -+ LaneB = DAG.getConstant(0, DL, MVT::i32); -+ // Having the index passed in a register, set the upper lane to the same -+ // value as the lower - this results in the BUILD_VECTOR node not being -+ // expanded through stack. This way we are able to pattern match the set of -+ // nodes created here to splat.d. -+ else -+ LaneB = LaneA; -+ ViaVecTy = MVT::v4i32; -+ } else -+ LaneB = LaneA; -+ -+ SDValue Ops[16] = {LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, -+ LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB}; -+ -+ SDValue Result = DAG.getBuildVector( -+ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); -+ -+ if (ViaVecTy != ResVecTy) { -+ SDValue One = DAG.getConstant(1, DL, ViaVecTy); -+ Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, -+ DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One)); -+ } -+ -+ return Result; -+} -+ -+static SDValue lowerLSXSplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, -+ bool IsSigned = false) { -+ return DAG.getConstant( -+ APInt(Op->getValueType(0).getScalarType().getSizeInBits(), -+ Op->getConstantOperandVal(ImmOp), IsSigned), -+ SDLoc(Op), Op->getValueType(0)); -+} -+ -+static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, -+ SelectionDAG &DAG) { -+ EVT ViaVecTy = VecTy; -+ SDValue SplatValueA = SplatValue; -+ SDValue SplatValueB = SplatValue; -+ SDLoc DL(SplatValue); -+ -+ if (VecTy == MVT::v2i64) { -+ // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's. -+ ViaVecTy = MVT::v4i32; -+ -+ SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue); -+ SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue, -+ DAG.getConstant(32, DL, MVT::i32)); -+ SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB); -+ } -+ -+ SDValue Ops[32] = {SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB, -+ SplatValueA, SplatValueB, SplatValueA, SplatValueB}; -+ -+ SDValue Result = DAG.getBuildVector( -+ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); -+ -+ if (VecTy != ViaVecTy) -+ Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result); -+ -+ return Result; -+} -+ -+static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) { -+ SDLoc DL(Op); -+ EVT ResTy = Op->getValueType(0); -+ SDValue Vec = Op->getOperand(2); -+ MVT ResEltTy = -+ (ResTy == MVT::v2i64 || ResTy == MVT::v4i64) ? MVT::i64 : MVT::i32; -+ SDValue ConstValue = -+ DAG.getConstant(Vec.getScalarValueSizeInBits() - 1, DL, ResEltTy); -+ SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, DAG); -+ -+ return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec); -+} -+ -+static SDValue lowerLSXBitClear(SDValue Op, SelectionDAG &DAG) { -+ EVT ResTy = Op->getValueType(0); -+ SDLoc DL(Op); -+ SDValue One = DAG.getConstant(1, DL, ResTy); -+ SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG)); -+ -+ return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), -+ DAG.getNOT(DL, Bit, ResTy)); -+} -+ -+static SDValue lowerLSXLoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Address = Op->getOperand(2); -+ SDValue Offset = Op->getOperand(3); -+ EVT ResTy = Op->getValueType(0); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), -+ /* Alignment = */ 16); -+} -+ -+static SDValue lowerLASXLoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Address = Op->getOperand(2); -+ SDValue Offset = Op->getOperand(3); -+ EVT ResTy = Op->getValueType(0); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), -+ /* Alignment = */ 32); -+} -+ -+static SDValue lowerLASXVLDRIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Address = Op->getOperand(2); -+ SDValue Offset = Op->getOperand(3); -+ EVT ResTy = Op->getValueType(0); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ SDValue Load = DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), -+ /* Alignment = */ 32); -+ return DAG.getNode(LoongArchISD::XVBROADCAST, DL, -+ DAG.getVTList(ResTy, MVT::Other), Load); -+} -+ -+static SDValue lowerLSXVLDRIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Address = Op->getOperand(2); -+ SDValue Offset = Op->getOperand(3); -+ EVT ResTy = Op->getValueType(0); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ SDValue Load = DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), -+ /* Alignment = */ 16); -+ return DAG.getNode(LoongArchISD::VBROADCAST, DL, -+ DAG.getVTList(ResTy, MVT::Other), Load); -+} -+ -+static SDValue lowerLSXStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Value = Op->getOperand(2); -+ SDValue Address = Op->getOperand(3); -+ SDValue Offset = Op->getOperand(4); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ -+ return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), -+ /* Alignment = */ 16); -+} -+ -+static SDValue lowerLASXStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, -+ const LoongArchSubtarget &Subtarget) { -+ SDLoc DL(Op); -+ SDValue ChainIn = Op->getOperand(0); -+ SDValue Value = Op->getOperand(2); -+ SDValue Address = Op->getOperand(3); -+ SDValue Offset = Op->getOperand(4); -+ EVT PtrTy = Address->getValueType(0); -+ -+ // For LP64 addresses have the underlying type MVT::i64. This intrinsic -+ // however takes an i32 signed constant offset. The actual type of the -+ // intrinsic is a scaled signed i12. -+ if (Subtarget.isABI_LP64()) -+ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); -+ -+ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); -+ -+ return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), -+ /* Alignment = */ 32); -+} -+ -+static SDValue LowerSUINT_TO_FP(unsigned ExtOpcode, SDValue Op, SelectionDAG &DAG) { -+ -+ EVT ResTy = Op->getValueType(0); -+ SDValue Op0 = Op->getOperand(0); -+ EVT ViaTy = Op0->getValueType(0); -+ SDLoc DL(Op); -+ -+ if (!ResTy.isVector()) { -+ if(ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) -+ return DAG.getNode(ISD::BITCAST, DL, ResTy, Op0); -+ else if(ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { -+ Op0 = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Op0); -+ return DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, Op0); -+ } else { -+ Op0 = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Op0); -+ return DAG.getNode(ISD::TRUNCATE, DL, MVT::f32, Op0); -+ } -+ -+ } -+ -+ if (ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) { -+ // v4i32 => v4f32 v8i32 => v8f32 -+ // v2i64 => v2f64 v4i64 => v4f64 -+ // do nothing -+ } else if (ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { -+ // v4i32 => v4i64 => v4f64 -+ Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i32, {Op0, Op0}); -+ Op0 = DAG.getNode(ExtOpcode, DL, MVT::v4i64, Op0); -+ } else { -+ // v4i64 => v4f32 -+ SDValue Ops[4]; -+ for (unsigned i = 0; i < 4; i++) { -+ SDValue I64 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op0, -+ DAG.getConstant(i, DL, MVT::i32)); -+ Ops[i] = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, I64); -+ } -+ Op0 = DAG.getBuildVector(MVT::v4i32, DL, makeArrayRef(Ops, 4)); -+ } -+ -+ return Op0; -+} -+ -+static SDValue LowerFP_TO_SUINT(unsigned FPToSUI, unsigned ExtOpcode, -+ SDValue Op, SelectionDAG &DAG) { -+ -+ EVT ResTy = Op->getValueType(0); -+ SDValue Op0 = Op->getOperand(0); -+ EVT ViaTy = Op0->getValueType(0); -+ SDLoc DL(Op); -+ -+ if (ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) { -+ // v4f32 => v4i32 v8f32 => v8i32 -+ // v2f64 => v2i64 v4f64 => v4i64 -+ // do nothing -+ Op0 = DAG.getNode(FPToSUI, DL, ResTy, Op0); -+ } else if (ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { -+ // v4f32 => v4i32 => v4i64 -+ Op0 = DAG.getNode(FPToSUI, DL, MVT::v4i32, Op0); -+ Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i32, {Op0, Op0}); -+ Op0 = DAG.getNode(ExtOpcode, DL, MVT::v4i64, Op0); -+ } else { -+ SDValue Ops[4]; -+ Ops[0] = DAG.getNode(FPToSUI, DL, MVT::i32, -+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, -+ DAG.getConstant(0, DL, MVT::i64))); -+ Ops[1] = DAG.getNode(FPToSUI, DL, MVT::i32, -+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, -+ DAG.getConstant(1, DL, MVT::i64))); -+ Ops[2] = DAG.getNode(FPToSUI, DL, MVT::i32, -+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, -+ DAG.getConstant(2, DL, MVT::i64))); -+ Ops[3] = DAG.getNode(FPToSUI, DL, MVT::i32, -+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, -+ DAG.getConstant(3, DL, MVT::i64))); -+ -+ Op0 = DAG.getBuildVector(MVT::v4i32, DL, makeArrayRef(Ops, 4)); -+ } -+ -+ return Op0; -+} -+ -+// Lower VECTOR_SHUFFLE into SHF (if possible). -+// -+// SHF splits the vector into blocks of four elements, then shuffles these -+// elements according to a <4 x i2> constant (encoded as an integer immediate). -+// -+// It is therefore possible to lower into SHF when the mask takes the form: -+// -+// When undef's appear they are treated as if they were whatever value is -+// necessary in order to fit the above forms. -+// -+// For example: -+// %2 = shufflevector <8 x i16> %0, <8 x i16> undef, -+// <8 x i32> -+// is lowered to: -+// (VSHUF4I_H $v0, $v1, 27) -+// where the 27 comes from: -+// 3 + (2 << 2) + (1 << 4) + (0 << 6) -+static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ int SHFIndices[4] = {-1, -1, -1, -1}; -+ -+ if (Indices.size() < 4) -+ return SDValue(); -+ -+ for (unsigned i = 0; i < 4; ++i) { -+ for (unsigned j = i; j < Indices.size(); j += 4) { -+ int Idx = Indices[j]; -+ -+ // Convert from vector index to 4-element subvector index -+ // If an index refers to an element outside of the subvector then give up -+ if (Idx != -1) { -+ Idx -= 4 * (j / 4); -+ if (Idx < 0 || Idx >= 4) -+ return SDValue(); -+ } -+ -+ // If the mask has an undef, replace it with the current index. -+ // Note that it might still be undef if the current index is also undef -+ if (SHFIndices[i] == -1) -+ SHFIndices[i] = Idx; -+ -+ // Check that non-undef values are the same as in the mask. If they -+ // aren't then give up -+ if (!(Idx == -1 || Idx == SHFIndices[i])) -+ return SDValue(); -+ } -+ } -+ -+ // Calculate the immediate. Replace any remaining undefs with zero -+ APInt Imm(32, 0); -+ for (int i = 3; i >= 0; --i) { -+ int Idx = SHFIndices[i]; -+ -+ if (Idx == -1) -+ Idx = 0; -+ -+ Imm <<= 2; -+ Imm |= Idx & 0x3; -+ } -+ -+ SDLoc DL(Op); -+ return DAG.getNode(LoongArchISD::SHF, DL, ResTy, -+ DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); -+} -+ -+/// Determine whether a range fits a regular pattern of values. -+/// This function accounts for the possibility of jumping over the End iterator. -+template -+static bool -+fitsRegularPattern(typename SmallVectorImpl::const_iterator Begin, -+ unsigned CheckStride, -+ typename SmallVectorImpl::const_iterator End, -+ ValType ExpectedIndex, unsigned ExpectedIndexStride) { -+ auto &I = Begin; -+ -+ while (I != End) { -+ if (*I != -1 && *I != ExpectedIndex) -+ return false; -+ ExpectedIndex += ExpectedIndexStride; -+ -+ // Incrementing past End is undefined behaviour so we must increment one -+ // step at a time and check for End at each step. -+ for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I) -+ ; // Empty loop body. -+ } -+ return true; -+} -+ -+// Determine whether VECTOR_SHUFFLE is a VREPLVEI. -+// -+// It is a VREPLVEI when the mask is: -+// -+// where x is any valid index. -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above form. -+static bool isVECTOR_SHUFFLE_VREPLVEI(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ int SplatIndex = -1; -+ for (const auto &V : Indices) { -+ if (V != -1) { -+ SplatIndex = V; -+ break; -+ } -+ } -+ -+ return fitsRegularPattern(Indices.begin(), 1, Indices.end(), SplatIndex, -+ 0); -+} -+ -+// Lower VECTOR_SHUFFLE into VPACKEV (if possible). -+// -+// VPACKEV interleaves the even elements from each vector. -+// -+// It is possible to lower into VPACKEV when the mask consists of two of the -+// following forms interleaved: -+// <0, 2, 4, ...> -+// -+// where n is the number of elements in the vector. -+// For example: -+// <0, 0, 2, 2, 4, 4, ...> -+// <0, n, 2, n+2, 4, n+4, ...> -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VPACKEV(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ -+ // Check even elements are taken from the even elements of one half or the -+ // other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin, 2, End, 0, 2)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 2)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ // Check odd elements are taken from the even elements of one half or the -+ // other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin + 1, 2, End, 0, 2)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 2)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPACKEV, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VPACKOD (if possible). -+// -+// VPACKOD interleaves the odd elements from each vector. -+// -+// It is possible to lower into VPACKOD when the mask consists of two of the -+// following forms interleaved: -+// <1, 3, 5, ...> -+// -+// where n is the number of elements in the vector. -+// For example: -+// <1, 1, 3, 3, 5, 5, ...> -+// <1, n+1, 3, n+3, 5, n+5, ...> -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VPACKOD(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ -+ // Check even elements are taken from the odd elements of one half or the -+ // other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin, 2, End, 1, 2)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + 1, 2)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ // Check odd elements are taken from the odd elements of one half or the -+ // other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin + 1, 2, End, 1, 2)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + 1, 2)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPACKOD, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VILVL (if possible). -+// -+// VILVL interleaves consecutive elements from the right (lowest-indexed) half -+// of each vector. -+// -+// It is possible to lower into VILVL when the mask consists of two of the -+// following forms interleaved: -+// <0, 1, 2, ...> -+// -+// where n is the number of elements in the vector. -+// For example: -+// <0, 0, 1, 1, 2, 2, ...> -+// <0, n, 1, n+1, 2, n+2, ...> -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VILVL(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ -+ // Check even elements are taken from the right (lowest-indexed) elements of -+ // one half or the other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin, 2, End, 0, 1)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 1)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ // Check odd elements are taken from the right (lowest-indexed) elements of -+ // one half or the other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin + 1, 2, End, 0, 1)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 1)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VILVL, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VILVH (if possible). -+// -+// VILVH interleaves consecutive elements from the left (highest-indexed) half -+// of each vector. -+// -+// It is possible to lower into VILVH when the mask consists of two of the -+// following forms interleaved: -+// -+// -+// where n is the number of elements in the vector and x is half n. -+// For example: -+// -+// -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VILVH(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ unsigned HalfSize = Indices.size() / 2; -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ -+ // Check even elements are taken from the left (highest-indexed) elements of -+ // one half or the other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin, 2, End, HalfSize, 1)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + HalfSize, 1)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ // Check odd elements are taken from the left (highest-indexed) elements of -+ // one half or the other and pick an operand accordingly. -+ if (fitsRegularPattern(Begin + 1, 2, End, HalfSize, 1)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + HalfSize, -+ 1)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VILVH, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VPICKEV (if possible). -+// -+// VPICKEV copies the even elements of each vector into the result vector. -+// -+// It is possible to lower into VPICKEV when the mask consists of two of the -+// following forms concatenated: -+// <0, 2, 4, ...> -+// -+// where n is the number of elements in the vector. -+// For example: -+// <0, 2, 4, ..., 0, 2, 4, ...> -+// <0, 2, 4, ..., n, n+2, n+4, ...> -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VPICKEV(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &Mid = Indices.begin() + Indices.size() / 2; -+ const auto &End = Indices.end(); -+ -+ if (fitsRegularPattern(Begin, 1, Mid, 0, 2)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 1, Mid, Indices.size(), 2)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Mid, 1, End, 0, 2)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Mid, 1, End, Indices.size(), 2)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPICKEV, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VPICKOD (if possible). -+// -+// VPICKOD copies the odd elements of each vector into the result vector. -+// -+// It is possible to lower into VPICKOD when the mask consists of two of the -+// following forms concatenated: -+// <1, 3, 5, ...> -+// -+// where n is the number of elements in the vector. -+// For example: -+// <1, 3, 5, ..., 1, 3, 5, ...> -+// <1, 3, 5, ..., n+1, n+3, n+5, ...> -+// -+// When undef's appear in the mask they are treated as if they were whatever -+// value is necessary in order to fit the above forms. -+static SDValue lowerVECTOR_SHUFFLE_VPICKOD(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Vj; -+ SDValue Vk; -+ const auto &Begin = Indices.begin(); -+ const auto &Mid = Indices.begin() + Indices.size() / 2; -+ const auto &End = Indices.end(); -+ -+ if (fitsRegularPattern(Begin, 1, Mid, 1, 2)) -+ Vj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 1, Mid, Indices.size() + 1, 2)) -+ Vj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Mid, 1, End, 1, 2)) -+ Vk = Op->getOperand(0); -+ else if (fitsRegularPattern(Mid, 1, End, Indices.size() + 1, 2)) -+ Vk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPICKOD, SDLoc(Op), ResTy, Vk, Vj); -+} -+ -+// Lower VECTOR_SHUFFLE into VSHF. -+// -+// This mostly consists of converting the shuffle indices in Indices into a -+// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is -+// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example, -+// if the type is v8i16 and all the indices are less than 8 then the second -+// operand is unused and can be replaced with anything. We choose to replace it -+// with the used operand since this reduces the number of instructions overall. -+static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ SmallVector Ops; -+ SDValue Op0; -+ SDValue Op1; -+ EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger(); -+ EVT MaskEltTy = MaskVecTy.getVectorElementType(); -+ bool Using1stVec = false; -+ bool Using2ndVec = false; -+ SDLoc DL(Op); -+ int ResTyNumElts = ResTy.getVectorNumElements(); -+ -+ for (int i = 0; i < ResTyNumElts; ++i) { -+ // Idx == -1 means UNDEF -+ int Idx = Indices[i]; -+ -+ if (0 <= Idx && Idx < ResTyNumElts) -+ Using1stVec = true; -+ if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2) -+ Using2ndVec = true; -+ } -+ -+ for (SmallVector::iterator I = Indices.begin(); I != Indices.end(); -+ ++I) -+ Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy)); -+ -+ SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops); -+ -+ if (Using1stVec && Using2ndVec) { -+ Op0 = Op->getOperand(0); -+ Op1 = Op->getOperand(1); -+ } else if (Using1stVec) -+ Op0 = Op1 = Op->getOperand(0); -+ else if (Using2ndVec) -+ Op0 = Op1 = Op->getOperand(1); -+ else -+ llvm_unreachable("shuffle vector mask references neither vector operand?"); -+ -+ // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion. -+ // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11> -+ // VSHF concatenates the vectors in a bitwise fashion: -+ // <0b00, 0b01> + <0b10, 0b11> -> -+ // 0b0100 + 0b1110 -> 0b01001110 -+ // <0b10, 0b11, 0b00, 0b01> -+ // We must therefore swap the operands to get the correct result. -+ return DAG.getNode(LoongArchISD::VSHF, DL, ResTy, MaskVec, Op1, Op0); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVILVL(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ unsigned HalfSize = Indices.size() / 2; -+ -+ if (fitsRegularPattern(Begin, 2, End - HalfSize, 0, 1) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize, 1)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End - HalfSize, Indices.size(), -+ 1) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, -+ Indices.size() + HalfSize, 1)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, 0, 1) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize, 1)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, Indices.size(), -+ 1) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, -+ Indices.size() + HalfSize, 1)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VILVL, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVILVH(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ unsigned HalfSize = Indices.size() / 2; -+ unsigned LeftSize = HalfSize / 2; -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ -+ if (fitsRegularPattern(Begin, 2, End - HalfSize, HalfSize - LeftSize, -+ 1) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize + LeftSize, 1)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End - HalfSize, -+ Indices.size() + HalfSize - LeftSize, 1) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, -+ Indices.size() + HalfSize + LeftSize, 1)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, HalfSize - LeftSize, -+ 1) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize + LeftSize, -+ 1)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, -+ Indices.size() + HalfSize - LeftSize, 1) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, -+ Indices.size() + HalfSize + LeftSize, 1)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VILVH, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ unsigned HalfSize = Indices.size() / 2; -+ -+ if (fitsRegularPattern(Begin, 2, End, 0, 2) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize, 2)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 2) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, -+ Indices.size() + HalfSize, 2)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Begin + 1, 2, End, 0, 2) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize, 2)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 2) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, -+ Indices.size() + HalfSize, 2)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPACKEV, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &End = Indices.end(); -+ unsigned HalfSize = Indices.size() / 2; -+ -+ if (fitsRegularPattern(Begin, 2, End, 1, 2) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize + 1, 2)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + 1, 2) && -+ fitsRegularPattern(Begin + HalfSize, 2, End, -+ Indices.size() + HalfSize + 1, 2)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(Begin + 1, 2, End, 1, 2) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize + 1, 2)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + 1, 2) && -+ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, -+ Indices.size() + HalfSize + 1, 2)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPACKOD, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static bool isVECTOR_SHUFFLE_XVREPLVEI(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ unsigned HalfSize = Indices.size() / 2; -+ -+ for (unsigned i = 0; i < HalfSize; i++) { -+ if (Indices[i] == -1 || Indices[HalfSize + i] == -1) -+ return false; -+ if (Indices[0] != Indices[i] || Indices[HalfSize] != Indices[HalfSize + i]) -+ return false; -+ } -+ return true; -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &LeftMid = Indices.begin() + Indices.size() / 4; -+ const auto &End = Indices.end(); -+ const auto &RightMid = Indices.end() - Indices.size() / 4; -+ const auto &Mid = Indices.begin() + Indices.size() / 2; -+ unsigned HalfSize = Indices.size() / 2; -+ -+ if (fitsRegularPattern(Begin, 1, LeftMid, 0, 2) && -+ fitsRegularPattern(Mid, 1, RightMid, HalfSize, 2)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 1, LeftMid, Indices.size(), 2) && -+ fitsRegularPattern(Mid, 1, RightMid, Indices.size() + HalfSize, -+ 2)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(LeftMid, 1, Mid, 0, 2) && -+ fitsRegularPattern(RightMid, 1, End, HalfSize, 2)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(LeftMid, 1, Mid, Indices.size(), 2) && -+ fitsRegularPattern(RightMid, 1, End, Indices.size() + HalfSize, -+ 2)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPICKEV, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ assert((Indices.size() % 2) == 0); -+ -+ SDValue Xj; -+ SDValue Xk; -+ const auto &Begin = Indices.begin(); -+ const auto &LeftMid = Indices.begin() + Indices.size() / 4; -+ const auto &Mid = Indices.begin() + Indices.size() / 2; -+ const auto &RightMid = Indices.end() - Indices.size() / 4; -+ const auto &End = Indices.end(); -+ unsigned HalfSize = Indices.size() / 2; -+ -+ if (fitsRegularPattern(Begin, 1, LeftMid, 1, 2) && -+ fitsRegularPattern(Mid, 1, RightMid, HalfSize + 1, 2)) -+ Xj = Op->getOperand(0); -+ else if (fitsRegularPattern(Begin, 1, LeftMid, Indices.size() + 1, 2) && -+ fitsRegularPattern(Mid, 1, RightMid, -+ Indices.size() + HalfSize + 1, 2)) -+ Xj = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ if (fitsRegularPattern(LeftMid, 1, Mid, 1, 2) && -+ fitsRegularPattern(RightMid, 1, End, HalfSize + 1, 2)) -+ Xk = Op->getOperand(0); -+ else if (fitsRegularPattern(LeftMid, 1, Mid, Indices.size() + 1, 2) && -+ fitsRegularPattern(RightMid, 1, End, -+ Indices.size() + HalfSize + 1, 2)) -+ Xk = Op->getOperand(1); -+ else -+ return SDValue(); -+ -+ return DAG.getNode(LoongArchISD::VPICKOD, SDLoc(Op), ResTy, Xk, Xj); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XSHF(SDValue Op, EVT ResTy, -+ SmallVector Indices, -+ SelectionDAG &DAG) { -+ int SHFIndices[4] = {-1, -1, -1, -1}; -+ -+ // If the size of the mask is 4, it should not be converted to SHF node, -+ // because SHF only corresponds to type b/h/w instruction but no type d. -+ if (Indices.size() <= 4) -+ return SDValue(); -+ -+ int HalfSize = Indices.size() / 2; -+ for (int i = 0; i < 4; ++i) { -+ for (int j = i; j < HalfSize; j += 4) { -+ int Idx = Indices[j]; -+ // check mxshf -+ if (Idx + HalfSize != Indices[j + HalfSize]) -+ return SDValue(); -+ -+ // Convert from vector index to 4-element subvector index -+ // If an index refers to an element outside of the subvector then give up -+ if (Idx != -1) { -+ Idx -= 4 * (j / 4); -+ if (Idx < 0 || Idx >= 4) -+ return SDValue(); -+ } -+ -+ // If the mask has an undef, replace it with the current index. -+ // Note that it might still be undef if the current index is also undef -+ if (SHFIndices[i] == -1) -+ SHFIndices[i] = Idx; -+ -+ // Check that non-undef values are the same as in the mask. If they -+ // aren't then give up -+ if (!(Idx == -1 || Idx == SHFIndices[i])) -+ return SDValue(); -+ } -+ } -+ -+ // Calculate the immediate. Replace any remaining undefs with zero -+ APInt Imm(32, 0); -+ for (int i = 3; i >= 0; --i) { -+ int Idx = SHFIndices[i]; -+ -+ if (Idx == -1) -+ Idx = 0; -+ -+ Imm <<= 2; -+ Imm |= Idx & 0x3; -+ } -+ SDLoc DL(Op); -+ return DAG.getNode(LoongArchISD::SHF, DL, ResTy, -+ DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); -+} -+ -+static bool isConstantOrUndef(const SDValue Op) { -+ if (Op->isUndef()) -+ return true; -+ if (isa(Op)) -+ return true; -+ if (isa(Op)) -+ return true; -+ return false; -+} -+ -+static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) { -+ for (unsigned i = 0; i < Op->getNumOperands(); ++i) -+ if (isConstantOrUndef(Op->getOperand(i))) -+ return true; -+ return false; -+} -+ -+static bool isLASXBySplatBitSize(unsigned SplatBitSize, EVT &ViaVecTy) { -+ switch (SplatBitSize) { -+ default: -+ return false; -+ case 8: -+ ViaVecTy = MVT::v32i8; -+ break; -+ case 16: -+ ViaVecTy = MVT::v16i16; -+ break; -+ case 32: -+ ViaVecTy = MVT::v8i32; -+ break; -+ case 64: -+ ViaVecTy = MVT::v4i64; -+ break; -+ case 128: -+ // There's no fill.q to fall back on for 64-bit values -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool isLSXBySplatBitSize(unsigned SplatBitSize, EVT &ViaVecTy) { -+ switch (SplatBitSize) { -+ default: -+ return false; -+ case 8: -+ ViaVecTy = MVT::v16i8; -+ break; -+ case 16: -+ ViaVecTy = MVT::v8i16; -+ break; -+ case 32: -+ ViaVecTy = MVT::v4i32; -+ break; -+ case 64: -+ // There's no fill.d to fall back on for 64-bit values -+ return false; -+ } -+ -+ return true; -+} -+ -+bool LoongArchTargetLowering::isCheapToSpeculateCttz() const { return true; } -+ -+bool LoongArchTargetLowering::isCheapToSpeculateCtlz() const { return true; } -+ -+void LoongArchTargetLowering::LowerOperationWrapper( -+ SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { -+ SDValue Res = LowerOperation(SDValue(N, 0), DAG); -+ -+ for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) -+ Results.push_back(Res.getValue(I)); -+} -+ -+void LoongArchTargetLowering::ReplaceNodeResults( -+ SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { -+ return LowerOperationWrapper(N, Results, DAG); -+} -+ -+SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, -+ SelectionDAG &DAG) const { -+ switch (Op.getOpcode()) { -+ case ISD::STORE: -+ return lowerSTORE(Op, DAG); -+ case ISD::INTRINSIC_WO_CHAIN: -+ return lowerINTRINSIC_WO_CHAIN(Op, DAG); -+ case ISD::INTRINSIC_W_CHAIN: -+ return lowerINTRINSIC_W_CHAIN(Op, DAG); -+ case ISD::INTRINSIC_VOID: -+ return lowerINTRINSIC_VOID(Op, DAG); -+ case ISD::EXTRACT_VECTOR_ELT: -+ return lowerEXTRACT_VECTOR_ELT(Op, DAG); -+ case ISD::INSERT_VECTOR_ELT: -+ return lowerINSERT_VECTOR_ELT(Op, DAG); -+ case ISD::BUILD_VECTOR: -+ return lowerBUILD_VECTOR(Op, DAG); -+ case ISD::VECTOR_SHUFFLE: -+ return lowerVECTOR_SHUFFLE(Op, DAG); -+ case ISD::UINT_TO_FP: -+ return lowerUINT_TO_FP(Op, DAG); -+ case ISD::SINT_TO_FP: -+ return lowerSINT_TO_FP(Op, DAG); -+ case ISD::FP_TO_UINT: -+ return lowerFP_TO_UINT(Op, DAG); -+ case ISD::FP_TO_SINT: -+ return lowerFP_TO_SINT(Op, DAG); -+ case ISD::BRCOND: -+ return lowerBRCOND(Op, DAG); -+ case ISD::ConstantPool: -+ return lowerConstantPool(Op, DAG); -+ case ISD::GlobalAddress: -+ return lowerGlobalAddress(Op, DAG); -+ case ISD::BlockAddress: -+ return lowerBlockAddress(Op, DAG); -+ case ISD::GlobalTLSAddress: -+ return lowerGlobalTLSAddress(Op, DAG); -+ case ISD::JumpTable: -+ return lowerJumpTable(Op, DAG); -+ case ISD::SELECT: -+ return lowerSELECT(Op, DAG); -+ case ISD::SETCC: -+ return lowerSETCC(Op, DAG); -+ case ISD::VASTART: -+ return lowerVASTART(Op, DAG); -+ case ISD::VAARG: -+ return lowerVAARG(Op, DAG); -+ case ISD::FRAMEADDR: -+ return lowerFRAMEADDR(Op, DAG); -+ case ISD::RETURNADDR: -+ return lowerRETURNADDR(Op, DAG); -+ case ISD::EH_RETURN: -+ return lowerEH_RETURN(Op, DAG); -+ case ISD::ATOMIC_FENCE: -+ return lowerATOMIC_FENCE(Op, DAG); -+ case ISD::SHL_PARTS: -+ return lowerShiftLeftParts(Op, DAG); -+ case ISD::SRA_PARTS: -+ return lowerShiftRightParts(Op, DAG, true); -+ case ISD::SRL_PARTS: -+ return lowerShiftRightParts(Op, DAG, false); -+ case ISD::EH_DWARF_CFA: -+ return lowerEH_DWARF_CFA(Op, DAG); -+ } -+ return SDValue(); -+} -+ -+//===----------------------------------------------------------------------===// -+// Lower helper functions -+//===----------------------------------------------------------------------===// -+ -+template -+SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG, -+ bool IsLocal) const { -+ SDLoc DL(N); -+ EVT Ty = getPointerTy(DAG.getDataLayout()); -+ -+ if (isPositionIndependent()) { -+ SDValue Addr = getTargetNode(N, Ty, DAG, 0U); -+ if (IsLocal) -+ // Use PC-relative addressing to access the symbol. -+ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrLocal, DL, Ty, Addr), -+ 0); -+ -+ // Use PC-relative addressing to access the GOT for this symbol, then load -+ // the address from the GOT. -+ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrGlobal, DL, Ty, Addr), -+ 0); -+ } -+ -+ SDValue Addr = getTargetNode(N, Ty, DAG, 0U); -+ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrLocal, DL, Ty, Addr), 0); -+} -+ -+// addLiveIn - This helper function adds the specified physical register to the -+// MachineFunction as a live in value. It also creates a corresponding -+// virtual register for it. -+static unsigned addLiveIn(MachineFunction &MF, unsigned PReg, -+ const TargetRegisterClass *RC) { -+ unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); -+ MF.getRegInfo().addLiveIn(PReg, VReg); -+ return VReg; -+} -+ -+static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, -+ MachineBasicBlock &MBB, -+ const TargetInstrInfo &TII, -+ bool Is64Bit) { -+ if (NoZeroDivCheck) -+ return &MBB; -+ -+ // Insert pseudo instruction(PseudoTEQ), will expand: -+ // beq $divisor_reg, $zero, 8 -+ // break 7 -+ MachineBasicBlock::iterator I(MI); -+ MachineInstrBuilder MIB; -+ MachineOperand &Divisor = MI.getOperand(2); -+ unsigned TeqOp = LoongArch::PseudoTEQ; -+ -+ MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(), TII.get(TeqOp)) -+ .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())); -+ -+ // Use the 32-bit sub-register if this is a 64-bit division. -+ //if (Is64Bit) -+ // MIB->getOperand(0).setSubReg(LoongArch::sub_32); -+ -+ // Clear Divisor's kill flag. -+ Divisor.setIsKill(false); -+ -+ // We would normally delete the original instruction here but in this case -+ // we only needed to inject an additional instruction rather than replace it. -+ -+ return &MBB; -+} -+ -+MachineBasicBlock * -+LoongArchTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ switch (MI.getOpcode()) { -+ default: -+ llvm_unreachable("Unexpected instr type to insert"); -+ case LoongArch::FILL_FW_PSEUDO: -+ return emitFILL_FW(MI, BB); -+ case LoongArch::FILL_FD_PSEUDO: -+ return emitFILL_FD(MI, BB); -+ case LoongArch::SNZ_B_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_B); -+ case LoongArch::SNZ_H_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_H); -+ case LoongArch::SNZ_W_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_W); -+ case LoongArch::SNZ_D_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_D); -+ case LoongArch::SNZ_V_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETNEZ_V); -+ case LoongArch::SZ_B_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_B); -+ case LoongArch::SZ_H_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_H); -+ case LoongArch::SZ_W_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_W); -+ case LoongArch::SZ_D_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_D); -+ case LoongArch::SZ_V_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETEQZ_V); -+ case LoongArch::XSNZ_B_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_B); -+ case LoongArch::XSNZ_H_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_H); -+ case LoongArch::XSNZ_W_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_W); -+ case LoongArch::XSNZ_D_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_D); -+ case LoongArch::XSNZ_V_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETNEZ_V); -+ case LoongArch::XSZ_B_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_B); -+ case LoongArch::XSZ_H_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_H); -+ case LoongArch::XSZ_W_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_W); -+ case LoongArch::XSZ_D_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_D); -+ case LoongArch::XSZ_V_PSEUDO: -+ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETEQZ_V); -+ case LoongArch::INSERT_FW_PSEUDO: -+ return emitINSERT_FW(MI, BB); -+ case LoongArch::INSERT_FD_PSEUDO: -+ return emitINSERT_FD(MI, BB); -+ case LoongArch::XINSERT_H_PSEUDO: -+ return emitXINSERT_BH(MI, BB, 2); -+ case LoongArch::XCOPY_FW_PSEUDO: -+ return emitXCOPY_FW(MI, BB); -+ case LoongArch::XCOPY_FD_PSEUDO: -+ return emitXCOPY_FD(MI, BB); -+ case LoongArch::XINSERT_FW_PSEUDO: -+ return emitXINSERT_FW(MI, BB); -+ case LoongArch::COPY_FW_PSEUDO: -+ return emitCOPY_FW(MI, BB); -+ case LoongArch::XFILL_FW_PSEUDO: -+ return emitXFILL_FW(MI, BB); -+ case LoongArch::XFILL_FD_PSEUDO: -+ return emitXFILL_FD(MI, BB); -+ case LoongArch::COPY_FD_PSEUDO: -+ return emitCOPY_FD(MI, BB); -+ case LoongArch::XINSERT_FD_PSEUDO: -+ return emitXINSERT_FD(MI, BB); -+ case LoongArch::XINSERT_B_PSEUDO: -+ return emitXINSERT_BH(MI, BB, 1); -+ case LoongArch::CONCAT_VECTORS_B_PSEUDO: -+ return emitCONCAT_VECTORS(MI, BB, 1); -+ case LoongArch::CONCAT_VECTORS_H_PSEUDO: -+ return emitCONCAT_VECTORS(MI, BB, 2); -+ case LoongArch::CONCAT_VECTORS_W_PSEUDO: -+ case LoongArch::CONCAT_VECTORS_FW_PSEUDO: -+ return emitCONCAT_VECTORS(MI, BB, 4); -+ case LoongArch::CONCAT_VECTORS_D_PSEUDO: -+ case LoongArch::CONCAT_VECTORS_FD_PSEUDO: -+ return emitCONCAT_VECTORS(MI, BB, 8); -+ case LoongArch::XCOPY_FW_GPR_PSEUDO: -+ return emitXCOPY_FW_GPR(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_ADD_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_ADD_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_ADD_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_ADD_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_AND_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_AND_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_AND_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_AND_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_OR_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_OR_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_OR_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_OR_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_XOR_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_XOR_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_XOR_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_XOR_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_NAND_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_NAND_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_NAND_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_NAND_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_SUB_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_SUB_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_SUB_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_SUB_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_SWAP_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_SWAP_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_SWAP_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_SWAP_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::XINSERT_B_VIDX_PSEUDO: -+ case LoongArch::XINSERT_B_VIDX64_PSEUDO: -+ return emitXINSERT_B(MI, BB); -+ case LoongArch::INSERT_H_VIDX64_PSEUDO: -+ return emitINSERT_H_VIDX(MI, BB); -+ case LoongArch::XINSERT_FW_VIDX_PSEUDO: -+ return emitXINSERT_DF_VIDX(MI, BB, false); -+ case LoongArch::XINSERT_FW_VIDX64_PSEUDO: -+ return emitXINSERT_DF_VIDX(MI, BB, true); -+ -+ case LoongArch::ATOMIC_LOAD_MAX_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_MAX_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_MAX_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_MAX_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_MIN_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_MIN_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_MIN_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_MIN_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_UMAX_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_UMAX_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_UMAX_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_UMAX_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_LOAD_UMIN_I8: -+ return emitAtomicBinaryPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_LOAD_UMIN_I16: -+ return emitAtomicBinaryPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_LOAD_UMIN_I32: -+ return emitAtomicBinary(MI, BB); -+ case LoongArch::ATOMIC_LOAD_UMIN_I64: -+ return emitAtomicBinary(MI, BB); -+ -+ case LoongArch::ATOMIC_CMP_SWAP_I8: -+ return emitAtomicCmpSwapPartword(MI, BB, 1); -+ case LoongArch::ATOMIC_CMP_SWAP_I16: -+ return emitAtomicCmpSwapPartword(MI, BB, 2); -+ case LoongArch::ATOMIC_CMP_SWAP_I32: -+ return emitAtomicCmpSwap(MI, BB); -+ case LoongArch::ATOMIC_CMP_SWAP_I64: -+ return emitAtomicCmpSwap(MI, BB); -+ -+ case LoongArch::PseudoSELECT_I: -+ case LoongArch::PseudoSELECT_I64: -+ case LoongArch::PseudoSELECT_S: -+ case LoongArch::PseudoSELECT_D64: -+ return emitPseudoSELECT(MI, BB, false, LoongArch::BNE32); -+ -+ case LoongArch::PseudoSELECTFP_T_I: -+ case LoongArch::PseudoSELECTFP_T_I64: -+ return emitPseudoSELECT(MI, BB, true, LoongArch::BCNEZ); -+ -+ case LoongArch::PseudoSELECTFP_F_I: -+ case LoongArch::PseudoSELECTFP_F_I64: -+ return emitPseudoSELECT(MI, BB, true, LoongArch::BCEQZ); -+ case LoongArch::DIV_W: -+ case LoongArch::DIV_WU: -+ case LoongArch::MOD_W: -+ case LoongArch::MOD_WU: -+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); -+ case LoongArch::DIV_D: -+ case LoongArch::DIV_DU: -+ case LoongArch::MOD_D: -+ case LoongArch::MOD_DU: -+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); -+ } -+} -+ -+MachineBasicBlock *LoongArchTargetLowering::emitXINSERT_DF_VIDX( -+ MachineInstr &MI, MachineBasicBlock *BB, bool IsGPR64) const { -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned insertOp; -+ insertOp = IsGPR64 ? LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA -+ : LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA; -+ -+ unsigned DstReg = MI.getOperand(0).getReg(); -+ unsigned SrcVecReg = MI.getOperand(1).getReg(); -+ unsigned LaneReg = MI.getOperand(2).getReg(); -+ unsigned SrcValReg = MI.getOperand(3).getReg(); -+ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); -+ -+ MachineBasicBlock::iterator II(MI); -+ -+ unsigned VecCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); -+ unsigned LaneCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); -+ unsigned ValCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); -+ -+ const TargetRegisterClass *RC = -+ IsGPR64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ unsigned RI = RegInfo.createVirtualRegister(RC); -+ -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) -+ .addImm(0) -+ .addReg(SrcValReg) -+ .addImm(LoongArch::sub_lo); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::XVPICKVE2GR_W), Rj) -+ .addReg(Xj) -+ .addImm(0); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); -+ -+ BuildMI(*BB, II, DL, TII->get(insertOp)) -+ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) -+ .addReg(VecCopy) -+ .addReg(LaneCopy) -+ .addReg(ValCopy) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(RI, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(Rj, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead); -+ -+ MI.eraseFromParent(); -+ -+ return BB; -+} -+ -+MachineBasicBlock * -+LoongArchTargetLowering::emitINSERT_H_VIDX(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned insertOp; -+ unsigned isGP64 = 0; -+ switch (MI.getOpcode()) { -+ case LoongArch::INSERT_H_VIDX64_PSEUDO: -+ isGP64 = 1; -+ insertOp = LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA; -+ break; -+ default: -+ llvm_unreachable("Unknown pseudo vector for replacement!"); -+ } -+ -+ unsigned DstReg = MI.getOperand(0).getReg(); -+ unsigned SrcVecReg = MI.getOperand(1).getReg(); -+ unsigned LaneReg = MI.getOperand(2).getReg(); -+ unsigned SrcValReg = MI.getOperand(3).getReg(); -+ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); -+ -+ MachineBasicBlock::iterator II(MI); -+ -+ unsigned VecCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); -+ unsigned LaneCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); -+ unsigned ValCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); -+ -+ const TargetRegisterClass *RC = -+ isGP64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ unsigned RI = RegInfo.createVirtualRegister(RC); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); -+ -+ BuildMI(*BB, II, DL, TII->get(insertOp)) -+ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) -+ .addReg(VecCopy) -+ .addReg(LaneCopy) -+ .addReg(ValCopy) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(RI, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead); -+ -+ MI.eraseFromParent(); -+ -+ return BB; -+} -+ -+MachineBasicBlock * -+LoongArchTargetLowering::emitXINSERT_B(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned insertOp; -+ unsigned isGP64 = 0; -+ switch (MI.getOpcode()) { -+ case LoongArch::XINSERT_B_VIDX64_PSEUDO: -+ isGP64 = 1; -+ insertOp = LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA; -+ break; -+ case LoongArch::XINSERT_B_VIDX_PSEUDO: -+ insertOp = LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA; -+ break; -+ default: -+ llvm_unreachable("Unknown pseudo vector for replacement!"); -+ } -+ -+ unsigned DstReg = MI.getOperand(0).getReg(); -+ unsigned SrcVecReg = MI.getOperand(1).getReg(); -+ unsigned LaneReg = MI.getOperand(2).getReg(); -+ unsigned SrcValReg = MI.getOperand(3).getReg(); -+ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); -+ -+ MachineBasicBlock::iterator II(MI); -+ -+ unsigned VecCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); -+ unsigned LaneCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); -+ unsigned ValCopy = -+ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); -+ const TargetRegisterClass *RC = -+ isGP64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ unsigned Rimm = RegInfo.createVirtualRegister(RC); -+ unsigned R4r = RegInfo.createVirtualRegister(RC); -+ unsigned Rib = RegInfo.createVirtualRegister(RC); -+ unsigned Ris = RegInfo.createVirtualRegister(RC); -+ unsigned R7b1 = RegInfo.createVirtualRegister(RC); -+ unsigned R7b2 = RegInfo.createVirtualRegister(RC); -+ unsigned R7b3 = RegInfo.createVirtualRegister(RC); -+ unsigned RI = RegInfo.createVirtualRegister(RC); -+ -+ unsigned R7r80_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R7r80l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R7r81_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R7r81l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R7r82_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R7r82l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned R70 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned tmp_Dst73 = -+ RegInfo.createVirtualRegister(&LoongArch::LASX256BRegClass); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); -+ -+ BuildMI(*BB, II, DL, TII->get(insertOp)) -+ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) -+ .addReg(VecCopy) -+ .addReg(LaneCopy) -+ .addReg(ValCopy) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R4r, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(Rib, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(Ris, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7b1, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7b2, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7b3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r80_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r80l_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r81_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r81l_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r82_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R7r82l_3, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(RI, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(tmp_Dst73, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(Rimm, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead) -+ .addReg(R70, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead); -+ -+ MI.eraseFromParent(); -+ -+ return BB; -+} -+ -+const TargetRegisterClass * -+LoongArchTargetLowering::getRepRegClassFor(MVT VT) const { -+ return TargetLowering::getRepRegClassFor(VT); -+} -+ -+// This function also handles LoongArch::ATOMIC_SWAP_I32 (when BinOpcode == 0), and -+// LoongArch::ATOMIC_LOAD_NAND_I32 (when Nand == true) -+MachineBasicBlock * -+LoongArchTargetLowering::emitAtomicBinary(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned AtomicOp; -+ switch (MI.getOpcode()) { -+ case LoongArch::ATOMIC_LOAD_ADD_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_NAND_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_SWAP_I32: -+ AtomicOp = LoongArch::ATOMIC_SWAP_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I32: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_ADD_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_NAND_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_SWAP_I64: -+ AtomicOp = LoongArch::ATOMIC_SWAP_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I64: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA; -+ break; -+ default: -+ llvm_unreachable("Unknown pseudo atomic for replacement!"); -+ } -+ -+ unsigned OldVal = MI.getOperand(0).getReg(); -+ unsigned Ptr = MI.getOperand(1).getReg(); -+ unsigned Incr = MI.getOperand(2).getReg(); -+ unsigned Scratch = RegInfo.createVirtualRegister(RegInfo.getRegClass(OldVal)); -+ -+ MachineBasicBlock::iterator II(MI); -+ -+ // The scratch registers here with the EarlyClobber | Define | Implicit -+ // flags is used to persuade the register allocator and the machine -+ // verifier to accept the usage of this register. This has to be a real -+ // register which has an UNDEF value but is dead after the instruction which -+ // is unique among the registers chosen for the instruction. -+ -+ // The EarlyClobber flag has the semantic properties that the operand it is -+ // attached to is clobbered before the rest of the inputs are read. Hence it -+ // must be unique among the operands to the instruction. -+ // The Define flag is needed to coerce the machine verifier that an Undef -+ // value isn't a problem. -+ // The Dead flag is needed as the value in scratch isn't used by any other -+ // instruction. Kill isn't used as Dead is more precise. -+ // The implicit flag is here due to the interaction between the other flags -+ // and the machine verifier. -+ -+ // For correctness purpose, a new pseudo is introduced here. We need this -+ // new pseudo, so that FastRegisterAllocator does not see an ll/sc sequence -+ // that is spread over >1 basic blocks. A register allocator which -+ // introduces (or any codegen infact) a store, can violate the expectations -+ // of the hardware. -+ // -+ // An atomic read-modify-write sequence starts with a linked load -+ // instruction and ends with a store conditional instruction. The atomic -+ // read-modify-write sequence fails if any of the following conditions -+ // occur between the execution of ll and sc: -+ // * A coherent store is completed by another process or coherent I/O -+ // module into the block of synchronizable physical memory containing -+ // the word. The size and alignment of the block is -+ // implementation-dependent. -+ // * A coherent store is executed between an LL and SC sequence on the -+ // same processor to the block of synchornizable physical memory -+ // containing the word. -+ // -+ -+ unsigned PtrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Ptr)); -+ unsigned IncrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Incr)); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), IncrCopy).addReg(Incr); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), PtrCopy).addReg(Ptr); -+ -+ BuildMI(*BB, II, DL, TII->get(AtomicOp)) -+ .addReg(OldVal, RegState::Define | RegState::EarlyClobber) -+ .addReg(PtrCopy) -+ .addReg(IncrCopy) -+ .addReg(Scratch, RegState::Define | RegState::EarlyClobber | -+ RegState::Implicit | RegState::Dead); -+ -+ if(MI.getOpcode() == LoongArch::ATOMIC_LOAD_NAND_I32 -+ || MI.getOpcode() == LoongArch::ATOMIC_LOAD_NAND_I64){ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); -+ } -+ -+ MI.eraseFromParent(); -+ -+ return BB; -+} -+ -+MachineBasicBlock *LoongArchTargetLowering::emitSignExtendToI32InReg( -+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, -+ unsigned SrcReg) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ const DebugLoc &DL = MI.getDebugLoc(); -+ if (Size == 1) { -+ BuildMI(BB, DL, TII->get(LoongArch::EXT_W_B32), DstReg).addReg(SrcReg); -+ return BB; -+ } -+ -+ if (Size == 2) { -+ BuildMI(BB, DL, TII->get(LoongArch::EXT_W_H32), DstReg).addReg(SrcReg); -+ return BB; -+ } -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); -+ unsigned ScrReg = RegInfo.createVirtualRegister(RC); -+ -+ assert(Size < 32); -+ int64_t ShiftImm = 32 - (Size * 8); -+ -+ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ScrReg).addReg(SrcReg).addImm(ShiftImm); -+ BuildMI(BB, DL, TII->get(LoongArch::SRAI_W), DstReg).addReg(ScrReg).addImm(ShiftImm); -+ -+ return BB; -+} -+ -+MachineBasicBlock *LoongArchTargetLowering::emitAtomicBinaryPartword( -+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { -+ assert((Size == 1 || Size == 2) && -+ "Unsupported size for EmitAtomicBinaryPartial."); -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); -+ const bool ArePtrs64bit = ABI.ArePtrs64bit(); -+ const TargetRegisterClass *RCp = -+ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned Dest = MI.getOperand(0).getReg(); -+ unsigned Ptr = MI.getOperand(1).getReg(); -+ unsigned Incr = MI.getOperand(2).getReg(); -+ -+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); -+ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); -+ unsigned Mask = RegInfo.createVirtualRegister(RC); -+ unsigned Mask2 = RegInfo.createVirtualRegister(RC); -+ unsigned Incr2 = RegInfo.createVirtualRegister(RC); -+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); -+ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); -+ unsigned MaskUpper = RegInfo.createVirtualRegister(RC); -+ unsigned MaskUppest = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch2 = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch3 = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch4 = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch5 = RegInfo.createVirtualRegister(RC); -+ -+ unsigned AtomicOp = 0; -+ switch (MI.getOpcode()) { -+ case LoongArch::ATOMIC_LOAD_NAND_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_NAND_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_SWAP_I8: -+ AtomicOp = LoongArch::ATOMIC_SWAP_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_SWAP_I16: -+ AtomicOp = LoongArch::ATOMIC_SWAP_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MAX_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_MIN_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMAX_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_UMIN_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_ADD_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_ADD_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_SUB_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_AND_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_OR_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I16_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I8: -+ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA; -+ break; -+ case LoongArch::ATOMIC_LOAD_XOR_I16: -+ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA; -+ break; -+ default: -+ llvm_unreachable("Unknown subword atomic pseudo for expansion!"); -+ } -+ -+ // insert new blocks after the current block -+ const BasicBlock *LLVM_BB = BB->getBasicBlock(); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB->getIterator(); -+ MF->insert(It, exitMBB); -+ -+ // Transfer the remainder of BB and its successor edges to exitMBB. -+ exitMBB->splice(exitMBB->begin(), BB, -+ std::next(MachineBasicBlock::iterator(MI)), BB->end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(BB); -+ -+ BB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ -+ // thisMBB: -+ // addiu masklsb2,$0,-4 # 0xfffffffc -+ // and alignedaddr,ptr,masklsb2 -+ // andi ptrlsb2,ptr,3 -+ // sll shiftamt,ptrlsb2,3 -+ // ori maskupper,$0,255 # 0xff -+ // sll mask,maskupper,shiftamt -+ // nor mask2,$0,mask -+ // sll incr2,incr,shiftamt -+ -+ int64_t MaskImm = (Size == 1) ? 255 : 4095; -+ BuildMI(BB, DL, TII->get(ABI.GetPtrAddiOp()), MaskLSB2) -+ .addReg(ABI.GetNullPtr()).addImm(-4); -+ BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr) -+ .addReg(Ptr).addReg(MaskLSB2); -+ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), PtrLSB2) -+ .addReg(Ptr, 0, ArePtrs64bit ? LoongArch::sub_32 : 0).addImm(3); -+ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ShiftAmt).addReg(PtrLSB2).addImm(3); -+ -+ if(MaskImm==4095){ -+ BuildMI(BB, DL, TII->get(LoongArch::LU12I_W32), MaskUppest).addImm(0xf); -+ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) -+ .addReg(MaskUppest).addImm(MaskImm); -+ } -+ else{ -+ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) -+ .addReg(LoongArch::ZERO).addImm(MaskImm); -+ } -+ -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Mask) -+ .addReg(MaskUpper).addReg(ShiftAmt); -+ BuildMI(BB, DL, TII->get(LoongArch::NOR32), Mask2).addReg(LoongArch::ZERO).addReg(Mask); -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Incr2).addReg(Incr).addReg(ShiftAmt); -+ -+ -+ // The purposes of the flags on the scratch registers is explained in -+ // emitAtomicBinary. In summary, we need a scratch register which is going to -+ // be undef, that is unique among registers chosen for the instruction. -+ -+ BuildMI(BB, DL, TII->get(LoongArch::DBAR)).addImm(0); -+ BuildMI(BB, DL, TII->get(AtomicOp)) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber) -+ .addReg(AlignedAddr) -+ .addReg(Incr2) -+ .addReg(Mask) -+ .addReg(Mask2) -+ .addReg(ShiftAmt) -+ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit) -+ .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit) -+ .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit) -+ .addReg(Scratch4, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit) -+ .addReg(Scratch5, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit); -+ -+ MI.eraseFromParent(); // The instruction is gone now. -+ -+ return exitMBB; -+} -+ -+// Lower atomic compare and swap to a pseudo instruction, taking care to -+// define a scratch register for the pseudo instruction's expansion. The -+// instruction is expanded after the register allocator as to prevent -+// the insertion of stores between the linked load and the store conditional. -+ -+MachineBasicBlock * -+LoongArchTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert((MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 || -+ MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I64) && -+ "Unsupported atomic psseudo for EmitAtomicCmpSwap."); -+ -+ const unsigned Size = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 ? 4 : 8; -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &MRI = MF->getRegInfo(); -+ const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned AtomicOp = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 -+ ? LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA -+ : LoongArch::ATOMIC_CMP_SWAP_I64_POSTRA; -+ unsigned Dest = MI.getOperand(0).getReg(); -+ unsigned Ptr = MI.getOperand(1).getReg(); -+ unsigned OldVal = MI.getOperand(2).getReg(); -+ unsigned NewVal = MI.getOperand(3).getReg(); -+ -+ unsigned Scratch = MRI.createVirtualRegister(RC); -+ MachineBasicBlock::iterator II(MI); -+ -+ // We need to create copies of the various registers and kill them at the -+ // atomic pseudo. If the copies are not made, when the atomic is expanded -+ // after fast register allocation, the spills will end up outside of the -+ // blocks that their values are defined in, causing livein errors. -+ -+ unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); -+ unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); -+ unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), PtrCopy).addReg(Ptr); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), OldValCopy).addReg(OldVal); -+ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), NewValCopy).addReg(NewVal); -+ -+ // The purposes of the flags on the scratch registers is explained in -+ // emitAtomicBinary. In summary, we need a scratch register which is going to -+ // be undef, that is unique among registers chosen for the instruction. -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(0); -+ BuildMI(*BB, II, DL, TII->get(AtomicOp)) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber) -+ .addReg(PtrCopy, RegState::Kill) -+ .addReg(OldValCopy, RegState::Kill) -+ .addReg(NewValCopy, RegState::Kill) -+ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit); -+ -+ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); -+ -+ MI.eraseFromParent(); // The instruction is gone now. -+ -+ return BB; -+} -+ -+MachineBasicBlock *LoongArchTargetLowering::emitAtomicCmpSwapPartword( -+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { -+ assert((Size == 1 || Size == 2) && -+ "Unsupported size for EmitAtomicCmpSwapPartial."); -+ -+ MachineFunction *MF = BB->getParent(); -+ MachineRegisterInfo &RegInfo = MF->getRegInfo(); -+ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); -+ const bool ArePtrs64bit = ABI.ArePtrs64bit(); -+ const TargetRegisterClass *RCp = -+ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned Dest = MI.getOperand(0).getReg(); -+ unsigned Ptr = MI.getOperand(1).getReg(); -+ unsigned CmpVal = MI.getOperand(2).getReg(); -+ unsigned NewVal = MI.getOperand(3).getReg(); -+ -+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); -+ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); -+ unsigned Mask = RegInfo.createVirtualRegister(RC); -+ unsigned Mask2 = RegInfo.createVirtualRegister(RC); -+ unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); -+ unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); -+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); -+ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); -+ unsigned MaskUpper = RegInfo.createVirtualRegister(RC); -+ unsigned MaskUppest = RegInfo.createVirtualRegister(RC); -+ unsigned Mask3 = RegInfo.createVirtualRegister(RC); -+ unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); -+ unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); -+ unsigned AtomicOp = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I8 -+ ? LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA -+ : LoongArch::ATOMIC_CMP_SWAP_I16_POSTRA; -+ -+ // The scratch registers here with the EarlyClobber | Define | Dead | Implicit -+ // flags are used to coerce the register allocator and the machine verifier to -+ // accept the usage of these registers. -+ // The EarlyClobber flag has the semantic properties that the operand it is -+ // attached to is clobbered before the rest of the inputs are read. Hence it -+ // must be unique among the operands to the instruction. -+ // The Define flag is needed to coerce the machine verifier that an Undef -+ // value isn't a problem. -+ // The Dead flag is needed as the value in scratch isn't used by any other -+ // instruction. Kill isn't used as Dead is more precise. -+ unsigned Scratch = RegInfo.createVirtualRegister(RC); -+ unsigned Scratch2 = RegInfo.createVirtualRegister(RC); -+ -+ // insert new blocks after the current block -+ const BasicBlock *LLVM_BB = BB->getBasicBlock(); -+ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); -+ MachineFunction::iterator It = ++BB->getIterator(); -+ MF->insert(It, exitMBB); -+ -+ // Transfer the remainder of BB and its successor edges to exitMBB. -+ exitMBB->splice(exitMBB->begin(), BB, -+ std::next(MachineBasicBlock::iterator(MI)), BB->end()); -+ exitMBB->transferSuccessorsAndUpdatePHIs(BB); -+ -+ BB->addSuccessor(exitMBB, BranchProbability::getOne()); -+ -+ // thisMBB: -+ // addiu masklsb2,$0,-4 # 0xfffffffc -+ // and alignedaddr,ptr,masklsb2 -+ // andi ptrlsb2,ptr,3 -+ // xori ptrlsb2,ptrlsb2,3 # Only for BE -+ // sll shiftamt,ptrlsb2,3 -+ // ori maskupper,$0,255 # 0xff -+ // sll mask,maskupper,shiftamt -+ // nor mask2,$0,mask -+ // andi maskedcmpval,cmpval,255 -+ // sll shiftedcmpval,maskedcmpval,shiftamt -+ // andi maskednewval,newval,255 -+ // sll shiftednewval,maskednewval,shiftamt -+ -+ int64_t MaskImm = (Size == 1) ? 255 : 4095; -+ BuildMI(BB, DL, TII->get(ArePtrs64bit ? LoongArch::ADDI_D : LoongArch::ADDI_W), MaskLSB2) -+ .addReg(ABI.GetNullPtr()).addImm(-4); -+ BuildMI(BB, DL, TII->get(ArePtrs64bit ? LoongArch::AND : LoongArch::AND32), AlignedAddr) -+ .addReg(Ptr).addReg(MaskLSB2); -+ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), PtrLSB2) -+ .addReg(Ptr, 0, ArePtrs64bit ? LoongArch::sub_32 : 0).addImm(3); -+ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ShiftAmt).addReg(PtrLSB2).addImm(3); -+ -+ if(MaskImm==4095){ -+ BuildMI(BB, DL, TII->get(LoongArch::LU12I_W32), MaskUppest).addImm(0xf); -+ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) -+ .addReg(MaskUppest).addImm(MaskImm); -+ } -+ else{ -+ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) -+ .addReg(LoongArch::ZERO).addImm(MaskImm); -+ } -+ -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Mask) -+ .addReg(MaskUpper).addReg(ShiftAmt); -+ BuildMI(BB, DL, TII->get(LoongArch::NOR32), Mask2).addReg(LoongArch::ZERO).addReg(Mask); -+ if(MaskImm==4095){ -+ BuildMI(BB, DL, TII->get(LoongArch::ORI32), Mask3) -+ .addReg(MaskUppest).addImm(MaskImm); -+ BuildMI(BB, DL, TII->get(LoongArch::AND32), MaskedCmpVal) -+ .addReg(CmpVal).addReg(Mask3); -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedCmpVal) -+ .addReg(MaskedCmpVal).addReg(ShiftAmt); -+ BuildMI(BB, DL, TII->get(LoongArch::AND32), MaskedNewVal) -+ .addReg(NewVal).addReg(Mask3); -+ } -+ else{ -+ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), MaskedCmpVal) -+ .addReg(CmpVal).addImm(MaskImm); -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedCmpVal) -+ .addReg(MaskedCmpVal).addReg(ShiftAmt); -+ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), MaskedNewVal) -+ .addReg(NewVal).addImm(MaskImm); -+ } -+ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedNewVal) -+ .addReg(MaskedNewVal).addReg(ShiftAmt); -+ -+ // The purposes of the flags on the scratch registers are explained in -+ // emitAtomicBinary. In summary, we need a scratch register which is going to -+ // be undef, that is unique among the register chosen for the instruction. -+ -+ BuildMI(BB, DL, TII->get(LoongArch::DBAR)).addImm(0); -+ BuildMI(BB, DL, TII->get(AtomicOp)) -+ .addReg(Dest, RegState::Define | RegState::EarlyClobber) -+ .addReg(AlignedAddr) -+ .addReg(Mask) -+ .addReg(ShiftedCmpVal) -+ .addReg(Mask2) -+ .addReg(ShiftedNewVal) -+ .addReg(ShiftAmt) -+ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit) -+ .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | -+ RegState::Dead | RegState::Implicit); -+ -+ MI.eraseFromParent(); // The instruction is gone now. -+ -+ return exitMBB; -+} -+ -+SDValue LoongArchTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { -+ // The first operand is the chain, the second is the condition, the third is -+ // the block to branch to if the condition is true. -+ SDValue Chain = Op.getOperand(0); -+ SDValue Dest = Op.getOperand(2); -+ SDLoc DL(Op); -+ -+ SDValue CondRes = createFPCmp(DAG, Op.getOperand(1)); -+ -+ // Return if flag is not set by a floating point comparison. -+ if (CondRes.getOpcode() != LoongArchISD::FPCmp) -+ return Op; -+ -+ SDValue CCNode = CondRes.getOperand(2); -+ LoongArch::CondCode CC = -+ (LoongArch::CondCode)cast(CCNode)->getZExtValue(); -+ unsigned Opc = invertFPCondCodeUser(CC) ? LoongArch::BRANCH_F : LoongArch::BRANCH_T; -+ SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32); -+ SDValue FCC0 = DAG.getRegister(LoongArch::FCC0, MVT::i32); -+ return DAG.getNode(LoongArchISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, -+ FCC0, Dest, CondRes); -+} -+ -+SDValue LoongArchTargetLowering::lowerSELECT(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDValue Cond = createFPCmp(DAG, Op.getOperand(0)); -+ -+ // Return if flag is not set by a floating point comparison. -+ if (Cond.getOpcode() != LoongArchISD::FPCmp) -+ return Op; -+ -+ SDValue N1 = Op.getOperand(1); -+ SDValue N2 = Op.getOperand(2); -+ SDLoc DL(Op); -+ -+ ConstantSDNode *CC = cast(Cond.getOperand(2)); -+ bool invert = invertFPCondCodeUser((LoongArch::CondCode)CC->getSExtValue()); -+ SDValue FCC = DAG.getRegister(LoongArch::FCC0, MVT::i32); -+ -+ if (Op->getSimpleValueType(0).SimpleTy == MVT::f64 || -+ Op->getSimpleValueType(0).SimpleTy == MVT::f32) { -+ if (invert) -+ return DAG.getNode(LoongArchISD::FSEL, DL, N1.getValueType(), N1, FCC, N2, -+ Cond); -+ else -+ return DAG.getNode(LoongArchISD::FSEL, DL, N1.getValueType(), N2, FCC, N1, -+ Cond); -+ -+ } else -+ return Op; -+} -+ -+SDValue LoongArchTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { -+ SDValue Cond = createFPCmp(DAG, Op); -+ -+ assert(Cond.getOpcode() == LoongArchISD::FPCmp && -+ "Floating point operand expected."); -+ -+ SDLoc DL(Op); -+ SDValue True = DAG.getConstant(1, DL, MVT::i32); -+ SDValue False = DAG.getConstant(0, DL, MVT::i32); -+ -+ return createCMovFP(DAG, Cond, True, False, DL); -+} -+ -+SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, -+ SelectionDAG &DAG) const { -+ GlobalAddressSDNode *N = cast(Op); -+ -+ const GlobalValue *GV = N->getGlobal(); -+ bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); -+ SDValue Addr = getAddr(N, DAG, IsLocal); -+ -+ return Addr; -+} -+ -+SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op, -+ SelectionDAG &DAG) const { -+ BlockAddressSDNode *N = cast(Op); -+ -+ return getAddr(N, DAG); -+} -+ -+SDValue LoongArchTargetLowering:: -+lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const -+{ -+ GlobalAddressSDNode *GA = cast(Op); -+ if (DAG.getTarget().useEmulatedTLS()) -+ return LowerToTLSEmulatedModel(GA, DAG); -+ -+ SDLoc DL(GA); -+ const GlobalValue *GV = GA->getGlobal(); -+ EVT PtrVT = getPointerTy(DAG.getDataLayout()); -+ -+ TLSModel::Model model = getTargetMachine().getTLSModel(GV); -+ -+ if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { -+ // General Dynamic TLS Model && Local Dynamic TLS Model -+ unsigned PtrSize = PtrVT.getSizeInBits(); -+ IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); -+ // SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrTy, 0, 0); -+ SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0U); -+ SDValue Load = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_GD , -+ DL, PtrVT, Addr), 0); -+ SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); -+ -+ ArgListTy Args; -+ ArgListEntry Entry; -+ Entry.Node = Load; -+ Entry.Ty = PtrTy; -+ Args.push_back(Entry); -+ -+ TargetLowering::CallLoweringInfo CLI(DAG); -+ CLI.setDebugLoc(DL) -+ .setChain(DAG.getEntryNode()) -+ .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); -+ std::pair CallResult = LowerCallTo(CLI); -+ -+ SDValue Ret = CallResult.first; -+ -+ return Ret; -+ } -+ -+ SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0U); -+ SDValue Offset; -+ if (model == TLSModel::InitialExec) { -+ // Initial Exec TLS Model -+ Offset = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_IE, DL, -+ PtrVT, Addr), 0); -+ } else { -+ // Local Exec TLS Model -+ assert(model == TLSModel::LocalExec); -+ Offset = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_LE, DL, -+ PtrVT, Addr), 0); -+ } -+ -+ SDValue ThreadPointer = DAG.getRegister((PtrVT == MVT::i32) -+ ? LoongArch::TP -+ : LoongArch::TP_64, PtrVT); -+ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Offset); -+} -+ -+SDValue LoongArchTargetLowering:: -+lowerJumpTable(SDValue Op, SelectionDAG &DAG) const -+{ -+ JumpTableSDNode *N = cast(Op); -+ -+ return getAddr(N, DAG); -+} -+ -+SDValue LoongArchTargetLowering:: -+lowerConstantPool(SDValue Op, SelectionDAG &DAG) const -+{ -+ ConstantPoolSDNode *N = cast(Op); -+ -+ return getAddr(N, DAG); -+} -+ -+SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { -+ MachineFunction &MF = DAG.getMachineFunction(); -+ LoongArchFunctionInfo *FuncInfo = MF.getInfo(); -+ -+ SDLoc DL(Op); -+ SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), -+ getPointerTy(MF.getDataLayout())); -+ -+ // vastart just stores the address of the VarArgsFrameIndex slot into the -+ // memory location argument. -+ const Value *SV = cast(Op.getOperand(2))->getValue(); -+ return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), -+ MachinePointerInfo(SV)); -+} -+ -+SDValue LoongArchTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { -+ SDNode *Node = Op.getNode(); -+ EVT VT = Node->getValueType(0); -+ SDValue Chain = Node->getOperand(0); -+ SDValue VAListPtr = Node->getOperand(1); -+ const Align Align = -+ llvm::MaybeAlign(Node->getConstantOperandVal(3)).valueOrOne(); -+ const Value *SV = cast(Node->getOperand(2))->getValue(); -+ SDLoc DL(Node); -+ unsigned ArgSlotSizeInBytes = (ABI.IsLPX32() || ABI.IsLP64()) ? 8 : 4; -+ -+ SDValue VAListLoad = DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, -+ VAListPtr, MachinePointerInfo(SV)); -+ SDValue VAList = VAListLoad; -+ -+ // Re-align the pointer if necessary. -+ // It should only ever be necessary for 64-bit types on LP32 since the minimum -+ // argument alignment is the same as the maximum type alignment for LPX32/LP64. -+ // -+ // FIXME: We currently align too often. The code generator doesn't notice -+ // when the pointer is still aligned from the last va_arg (or pair of -+ // va_args for the i64 on LP32 case). -+ if (Align > getMinStackArgumentAlignment()) { -+ VAList = DAG.getNode( -+ ISD::ADD, DL, VAList.getValueType(), VAList, -+ DAG.getConstant(Align.value() - 1, DL, VAList.getValueType())); -+ -+ VAList = DAG.getNode( -+ ISD::AND, DL, VAList.getValueType(), VAList, -+ DAG.getConstant(-(int64_t)Align.value(), DL, VAList.getValueType())); -+ } -+ -+ // Increment the pointer, VAList, to the next vaarg. -+ auto &TD = DAG.getDataLayout(); -+ unsigned ArgSizeInBytes = -+ TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); -+ SDValue Tmp3 = -+ DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, -+ DAG.getConstant(alignTo(ArgSizeInBytes, ArgSlotSizeInBytes), -+ DL, VAList.getValueType())); -+ // Store the incremented VAList to the legalized pointer -+ Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, -+ MachinePointerInfo(SV)); -+ -+ // Load the actual argument out of the pointer VAList -+ return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo()); -+} -+ -+SDValue LoongArchTargetLowering:: -+lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { -+ // check the depth -+ assert((cast(Op.getOperand(0))->getZExtValue() == 0) && -+ "Frame address can only be determined for current frame."); -+ -+ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); -+ MFI.setFrameAddressIsTaken(true); -+ EVT VT = Op.getValueType(); -+ SDLoc DL(Op); -+ SDValue FrameAddr = DAG.getCopyFromReg( -+ DAG.getEntryNode(), DL, ABI.IsLP64() ? LoongArch::FP_64 : LoongArch::FP, VT); -+ return FrameAddr; -+} -+ -+SDValue LoongArchTargetLowering::lowerRETURNADDR(SDValue Op, -+ SelectionDAG &DAG) const { -+ if (verifyReturnAddressArgumentIsConstant(Op, DAG)) -+ return SDValue(); -+ -+ // check the depth -+ assert((cast(Op.getOperand(0))->getZExtValue() == 0) && -+ "Return address can be determined only for current frame."); -+ -+ MachineFunction &MF = DAG.getMachineFunction(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ MVT VT = Op.getSimpleValueType(); -+ unsigned RA = ABI.IsLP64() ? LoongArch::RA_64 : LoongArch::RA; -+ MFI.setReturnAddressIsTaken(true); -+ -+ // Return RA, which contains the return address. Mark it an implicit live-in. -+ unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); -+ return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT); -+} -+ -+// An EH_RETURN is the result of lowering llvm.eh.return which in turn is -+// generated from __builtin_eh_return (offset, handler) -+// The effect of this is to adjust the stack pointer by "offset" -+// and then branch to "handler". -+SDValue LoongArchTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) -+ const { -+ MachineFunction &MF = DAG.getMachineFunction(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); -+ -+ LoongArchFI->setCallsEhReturn(); -+ SDValue Chain = Op.getOperand(0); -+ SDValue Offset = Op.getOperand(1); -+ SDValue Handler = Op.getOperand(2); -+ SDLoc DL(Op); -+ EVT Ty = ABI.IsLP64() ? MVT::i64 : MVT::i32; -+ -+ // Store stack offset in A1, store jump target in A0. Glue CopyToReg and -+ // EH_RETURN nodes, so that instructions are emitted back-to-back. -+ unsigned OffsetReg = ABI.IsLP64() ? LoongArch::A1_64 : LoongArch::A1; -+ unsigned AddrReg = ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; -+ Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); -+ Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); -+ return DAG.getNode(LoongArchISD::EH_RETURN, DL, MVT::Other, Chain, -+ DAG.getRegister(OffsetReg, Ty), -+ DAG.getRegister(AddrReg, getPointerTy(MF.getDataLayout())), -+ Chain.getValue(1)); -+} -+ -+SDValue LoongArchTargetLowering::lowerATOMIC_FENCE(SDValue Op, -+ SelectionDAG &DAG) const { -+ // FIXME: Need pseudo-fence for 'singlethread' fences -+ // FIXME: Set SType for weaker fences where supported/appropriate. -+ unsigned SType = 0; -+ SDLoc DL(Op); -+ return DAG.getNode(LoongArchISD::DBAR, DL, MVT::Other, Op.getOperand(0), -+ DAG.getConstant(SType, DL, MVT::i32)); -+} -+ -+SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ MVT VT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32; -+ -+ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); -+ SDValue Shamt = Op.getOperand(2); -+ // if shamt < (VT.bits): -+ // lo = (shl lo, shamt) -+ // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) -+ // else: -+ // lo = 0 -+ // hi = (shl lo, shamt[4:0]) -+ SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, -+ DAG.getConstant(-1, DL, MVT::i32)); -+ SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, -+ DAG.getConstant(1, DL, VT)); -+ SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); -+ SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); -+ SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); -+ SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); -+ SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, -+ DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); -+ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, -+ DAG.getConstant(0, DL, VT), ShiftLeftLo); -+ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); -+ -+ SDValue Ops[2] = {Lo, Hi}; -+ return DAG.getMergeValues(Ops, DL); -+} -+ -+SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, -+ bool IsSRA) const { -+ SDLoc DL(Op); -+ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); -+ SDValue Shamt = Op.getOperand(2); -+ MVT VT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32; -+ -+ // if shamt < (VT.bits): -+ // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) -+ // if isSRA: -+ // hi = (sra hi, shamt) -+ // else: -+ // hi = (srl hi, shamt) -+ // else: -+ // if isSRA: -+ // lo = (sra hi, shamt[4:0]) -+ // hi = (sra hi, 31) -+ // else: -+ // lo = (srl hi, shamt[4:0]) -+ // hi = 0 -+ SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, -+ DAG.getConstant(-1, DL, MVT::i32)); -+ SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, -+ DAG.getConstant(1, DL, VT)); -+ SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); -+ SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); -+ SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); -+ SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, -+ DL, VT, Hi, Shamt); -+ SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, -+ DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); -+ SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi, -+ DAG.getConstant(VT.getSizeInBits() - 1, DL, VT)); -+ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); -+ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, -+ IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi); -+ -+ SDValue Ops[2] = {Lo, Hi}; -+ return DAG.getMergeValues(Ops, DL); -+} -+ -+// Lower (store (fp_to_sint $fp) $ptr) to (store (TruncIntFP $fp), $ptr). -+static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG, -+ bool SingleFloat) { -+ SDValue Val = SD->getValue(); -+ -+ if (Val.getOpcode() != ISD::FP_TO_SINT || -+ (Val.getValueSizeInBits() > 32 && SingleFloat)) -+ return SDValue(); -+ -+ EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits()); -+ SDValue Tr = DAG.getNode(LoongArchISD::TruncIntFP, SDLoc(Val), FPTy, -+ Val.getOperand(0)); -+ return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(), -+ SD->getPointerInfo(), SD->getAlignment(), -+ SD->getMemOperand()->getFlags()); -+} -+ -+SDValue LoongArchTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { -+ StoreSDNode *SD = cast(Op); -+ return lowerFP_TO_SINT_STORE(SD, DAG, Subtarget.isSingleFloat()); -+} -+ -+SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ unsigned Intrinsic = cast(Op->getOperand(0))->getZExtValue(); -+ switch (Intrinsic) { -+ default: -+ return SDValue(); -+ case Intrinsic::loongarch_lsx_vaddi_bu: -+ case Intrinsic::loongarch_lsx_vaddi_hu: -+ case Intrinsic::loongarch_lsx_vaddi_wu: -+ case Intrinsic::loongarch_lsx_vaddi_du: -+ return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1), -+ lowerLSXSplatImm(Op, 2, DAG)); -+ case Intrinsic::loongarch_lsx_vand_v: -+ case Intrinsic::loongarch_lasx_xvand_v: -+ return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vbitclr_b: -+ case Intrinsic::loongarch_lsx_vbitclr_h: -+ case Intrinsic::loongarch_lsx_vbitclr_w: -+ case Intrinsic::loongarch_lsx_vbitclr_d: -+ return lowerLSXBitClear(Op, DAG); -+ case Intrinsic::loongarch_lsx_vdiv_b: -+ case Intrinsic::loongarch_lsx_vdiv_h: -+ case Intrinsic::loongarch_lsx_vdiv_w: -+ case Intrinsic::loongarch_lsx_vdiv_d: -+ return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vdiv_bu: -+ case Intrinsic::loongarch_lsx_vdiv_hu: -+ case Intrinsic::loongarch_lsx_vdiv_wu: -+ case Intrinsic::loongarch_lsx_vdiv_du: -+ return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vfdiv_s: -+ case Intrinsic::loongarch_lsx_vfdiv_d: -+ return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vffint_s_wu: -+ case Intrinsic::loongarch_lsx_vffint_d_lu: -+ return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0), -+ Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vffint_s_w: -+ case Intrinsic::loongarch_lsx_vffint_d_l: -+ return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0), -+ Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vfmul_s: -+ case Intrinsic::loongarch_lsx_vfmul_d: -+ return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vfrint_s: -+ case Intrinsic::loongarch_lsx_vfrint_d: -+ return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vfsqrt_s: -+ case Intrinsic::loongarch_lsx_vfsqrt_d: -+ return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vftintrz_wu_s: -+ case Intrinsic::loongarch_lsx_vftintrz_lu_d: -+ return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0), -+ Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vpackev_b: -+ case Intrinsic::loongarch_lsx_vpackev_h: -+ case Intrinsic::loongarch_lsx_vpackev_w: -+ case Intrinsic::loongarch_lsx_vpackev_d: -+ return DAG.getNode(LoongArchISD::VPACKEV, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vilvh_b: -+ case Intrinsic::loongarch_lsx_vilvh_h: -+ case Intrinsic::loongarch_lsx_vilvh_w: -+ case Intrinsic::loongarch_lsx_vilvh_d: -+ return DAG.getNode(LoongArchISD::VILVH, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vpackod_b: -+ case Intrinsic::loongarch_lsx_vpackod_h: -+ case Intrinsic::loongarch_lsx_vpackod_w: -+ case Intrinsic::loongarch_lsx_vpackod_d: -+ return DAG.getNode(LoongArchISD::VPACKOD, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vilvl_b: -+ case Intrinsic::loongarch_lsx_vilvl_h: -+ case Intrinsic::loongarch_lsx_vilvl_w: -+ case Intrinsic::loongarch_lsx_vilvl_d: -+ return DAG.getNode(LoongArchISD::VILVL, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmadd_b: -+ case Intrinsic::loongarch_lsx_vmadd_h: -+ case Intrinsic::loongarch_lsx_vmadd_w: -+ case Intrinsic::loongarch_lsx_vmadd_d: { -+ EVT ResTy = Op->getValueType(0); -+ return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1), -+ DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, -+ Op->getOperand(2), Op->getOperand(3))); -+ } -+ case Intrinsic::loongarch_lsx_vmax_b: -+ case Intrinsic::loongarch_lsx_vmax_h: -+ case Intrinsic::loongarch_lsx_vmax_w: -+ case Intrinsic::loongarch_lsx_vmax_d: -+ return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmax_bu: -+ case Intrinsic::loongarch_lsx_vmax_hu: -+ case Intrinsic::loongarch_lsx_vmax_wu: -+ case Intrinsic::loongarch_lsx_vmax_du: -+ return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmin_b: -+ case Intrinsic::loongarch_lsx_vmin_h: -+ case Intrinsic::loongarch_lsx_vmin_w: -+ case Intrinsic::loongarch_lsx_vmin_d: -+ return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmin_bu: -+ case Intrinsic::loongarch_lsx_vmin_hu: -+ case Intrinsic::loongarch_lsx_vmin_wu: -+ case Intrinsic::loongarch_lsx_vmin_du: -+ return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmini_bu: -+ case Intrinsic::loongarch_lsx_vmini_hu: -+ case Intrinsic::loongarch_lsx_vmini_wu: -+ case Intrinsic::loongarch_lsx_vmini_du: -+ return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), -+ lowerLSXSplatImm(Op, 2, DAG)); -+ case Intrinsic::loongarch_lsx_vmod_b: -+ case Intrinsic::loongarch_lsx_vmod_h: -+ case Intrinsic::loongarch_lsx_vmod_w: -+ case Intrinsic::loongarch_lsx_vmod_d: -+ return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmod_bu: -+ case Intrinsic::loongarch_lsx_vmod_hu: -+ case Intrinsic::loongarch_lsx_vmod_wu: -+ case Intrinsic::loongarch_lsx_vmod_du: -+ return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmul_b: -+ case Intrinsic::loongarch_lsx_vmul_h: -+ case Intrinsic::loongarch_lsx_vmul_w: -+ case Intrinsic::loongarch_lsx_vmul_d: -+ return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vmsub_b: -+ case Intrinsic::loongarch_lsx_vmsub_h: -+ case Intrinsic::loongarch_lsx_vmsub_w: -+ case Intrinsic::loongarch_lsx_vmsub_d: { -+ EVT ResTy = Op->getValueType(0); -+ return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1), -+ DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, -+ Op->getOperand(2), Op->getOperand(3))); -+ } -+ case Intrinsic::loongarch_lsx_vclz_b: -+ case Intrinsic::loongarch_lsx_vclz_h: -+ case Intrinsic::loongarch_lsx_vclz_w: -+ case Intrinsic::loongarch_lsx_vclz_d: -+ return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vnor_v: -+ case Intrinsic::loongarch_lasx_xvnor_v: { -+ SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ return DAG.getNOT(DL, Res, Res->getValueType(0)); -+ } -+ case Intrinsic::loongarch_lsx_vor_v: -+ case Intrinsic::loongarch_lasx_xvor_v: -+ return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vpickev_b: -+ case Intrinsic::loongarch_lsx_vpickev_h: -+ case Intrinsic::loongarch_lsx_vpickev_w: -+ case Intrinsic::loongarch_lsx_vpickev_d: -+ return DAG.getNode(LoongArchISD::VPICKEV, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vpickod_b: -+ case Intrinsic::loongarch_lsx_vpickod_h: -+ case Intrinsic::loongarch_lsx_vpickod_w: -+ case Intrinsic::loongarch_lsx_vpickod_d: -+ return DAG.getNode(LoongArchISD::VPICKOD, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vpcnt_b: -+ case Intrinsic::loongarch_lsx_vpcnt_h: -+ case Intrinsic::loongarch_lsx_vpcnt_w: -+ case Intrinsic::loongarch_lsx_vpcnt_d: -+ return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vsat_b: -+ case Intrinsic::loongarch_lsx_vsat_h: -+ case Intrinsic::loongarch_lsx_vsat_w: -+ case Intrinsic::loongarch_lsx_vsat_d: -+ case Intrinsic::loongarch_lsx_vsat_bu: -+ case Intrinsic::loongarch_lsx_vsat_hu: -+ case Intrinsic::loongarch_lsx_vsat_wu: -+ case Intrinsic::loongarch_lsx_vsat_du: { -+ // Report an error for out of range values. -+ int64_t Max; -+ switch (Intrinsic) { -+ case Intrinsic::loongarch_lsx_vsat_b: -+ case Intrinsic::loongarch_lsx_vsat_bu: -+ Max = 7; -+ break; -+ case Intrinsic::loongarch_lsx_vsat_h: -+ case Intrinsic::loongarch_lsx_vsat_hu: -+ Max = 15; -+ break; -+ case Intrinsic::loongarch_lsx_vsat_w: -+ case Intrinsic::loongarch_lsx_vsat_wu: -+ Max = 31; -+ break; -+ case Intrinsic::loongarch_lsx_vsat_d: -+ case Intrinsic::loongarch_lsx_vsat_du: -+ Max = 63; -+ break; -+ default: -+ llvm_unreachable("Unmatched intrinsic"); -+ } -+ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); -+ if (Value < 0 || Value > Max) -+ report_fatal_error("Immediate out of range"); -+ return SDValue(); -+ } -+ case Intrinsic::loongarch_lsx_vshuf4i_b: -+ case Intrinsic::loongarch_lsx_vshuf4i_h: -+ case Intrinsic::loongarch_lsx_vshuf4i_w: -+ // case Intrinsic::loongarch_lsx_vshuf4i_d: -+ { -+ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); -+ if (Value < 0 || Value > 255) -+ report_fatal_error("Immediate out of range"); -+ return DAG.getNode(LoongArchISD::SHF, DL, Op->getValueType(0), -+ Op->getOperand(2), Op->getOperand(1)); -+ } -+ case Intrinsic::loongarch_lsx_vsll_b: -+ case Intrinsic::loongarch_lsx_vsll_h: -+ case Intrinsic::loongarch_lsx_vsll_w: -+ case Intrinsic::loongarch_lsx_vsll_d: -+ return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), -+ truncateVecElts(Op, DAG)); -+ case Intrinsic::loongarch_lsx_vslli_b: -+ case Intrinsic::loongarch_lsx_vslli_h: -+ case Intrinsic::loongarch_lsx_vslli_w: -+ case Intrinsic::loongarch_lsx_vslli_d: -+ return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), -+ lowerLSXSplatImm(Op, 2, DAG)); -+ case Intrinsic::loongarch_lsx_vreplve_b: -+ case Intrinsic::loongarch_lsx_vreplve_h: -+ case Intrinsic::loongarch_lsx_vreplve_w: -+ case Intrinsic::loongarch_lsx_vreplve_d: -+ // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle -+ // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because -+ // EXTRACT_VECTOR_ELT can't extract i64's on LoongArch32. -+ // Instead we lower to LoongArchISD::VSHF and match from there. -+ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), -+ lowerLSXSplatZExt(Op, 2, DAG), Op->getOperand(1), -+ Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vreplvei_b: -+ case Intrinsic::loongarch_lsx_vreplvei_h: -+ case Intrinsic::loongarch_lsx_vreplvei_w: -+ case Intrinsic::loongarch_lsx_vreplvei_d: -+ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), -+ lowerLSXSplatImm(Op, 2, DAG), Op->getOperand(1), -+ Op->getOperand(1)); -+ case Intrinsic::loongarch_lsx_vsra_b: -+ case Intrinsic::loongarch_lsx_vsra_h: -+ case Intrinsic::loongarch_lsx_vsra_w: -+ case Intrinsic::loongarch_lsx_vsra_d: -+ return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1), -+ truncateVecElts(Op, DAG)); -+ case Intrinsic::loongarch_lsx_vsrari_b: -+ case Intrinsic::loongarch_lsx_vsrari_h: -+ case Intrinsic::loongarch_lsx_vsrari_w: -+ case Intrinsic::loongarch_lsx_vsrari_d: { -+ // Report an error for out of range values. -+ int64_t Max; -+ switch (Intrinsic) { -+ case Intrinsic::loongarch_lsx_vsrari_b: -+ Max = 7; -+ break; -+ case Intrinsic::loongarch_lsx_vsrari_h: -+ Max = 15; -+ break; -+ case Intrinsic::loongarch_lsx_vsrari_w: -+ Max = 31; -+ break; -+ case Intrinsic::loongarch_lsx_vsrari_d: -+ Max = 63; -+ break; -+ default: -+ llvm_unreachable("Unmatched intrinsic"); -+ } -+ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); -+ if (Value < 0 || Value > Max) -+ report_fatal_error("Immediate out of range"); -+ return SDValue(); -+ } -+ case Intrinsic::loongarch_lsx_vsrl_b: -+ case Intrinsic::loongarch_lsx_vsrl_h: -+ case Intrinsic::loongarch_lsx_vsrl_w: -+ case Intrinsic::loongarch_lsx_vsrl_d: -+ return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), -+ truncateVecElts(Op, DAG)); -+ case Intrinsic::loongarch_lsx_vsrli_b: -+ case Intrinsic::loongarch_lsx_vsrli_h: -+ case Intrinsic::loongarch_lsx_vsrli_w: -+ case Intrinsic::loongarch_lsx_vsrli_d: -+ return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), -+ lowerLSXSplatImm(Op, 2, DAG)); -+ case Intrinsic::loongarch_lsx_vsrlri_b: -+ case Intrinsic::loongarch_lsx_vsrlri_h: -+ case Intrinsic::loongarch_lsx_vsrlri_w: -+ case Intrinsic::loongarch_lsx_vsrlri_d: { -+ // Report an error for out of range values. -+ int64_t Max; -+ switch (Intrinsic) { -+ case Intrinsic::loongarch_lsx_vsrlri_b: -+ Max = 7; -+ break; -+ case Intrinsic::loongarch_lsx_vsrlri_h: -+ Max = 15; -+ break; -+ case Intrinsic::loongarch_lsx_vsrlri_w: -+ Max = 31; -+ break; -+ case Intrinsic::loongarch_lsx_vsrlri_d: -+ Max = 63; -+ break; -+ default: -+ llvm_unreachable("Unmatched intrinsic"); -+ } -+ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); -+ if (Value < 0 || Value > Max) -+ report_fatal_error("Immediate out of range"); -+ return SDValue(); -+ } -+ case Intrinsic::loongarch_lsx_vsubi_bu: -+ case Intrinsic::loongarch_lsx_vsubi_hu: -+ case Intrinsic::loongarch_lsx_vsubi_wu: -+ case Intrinsic::loongarch_lsx_vsubi_du: -+ return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1), -+ lowerLSXSplatImm(Op, 2, DAG)); -+ case Intrinsic::loongarch_lsx_vshuf_h: -+ case Intrinsic::loongarch_lsx_vshuf_w: -+ case Intrinsic::loongarch_lsx_vshuf_d: -+ case Intrinsic::loongarch_lasx_xvshuf_h: -+ case Intrinsic::loongarch_lasx_xvshuf_w: -+ case Intrinsic::loongarch_lasx_xvshuf_d: -+ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); -+ case Intrinsic::loongarch_lsx_vxor_v: -+ case Intrinsic::loongarch_lasx_xvxor_v: -+ return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1), -+ Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vrotr_b: -+ case Intrinsic::loongarch_lsx_vrotr_h: -+ case Intrinsic::loongarch_lsx_vrotr_w: -+ case Intrinsic::loongarch_lsx_vrotr_d: -+ return DAG.getNode(LoongArchISD::VROR, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::loongarch_lsx_vrotri_b: -+ case Intrinsic::loongarch_lsx_vrotri_h: -+ case Intrinsic::loongarch_lsx_vrotri_w: -+ case Intrinsic::loongarch_lsx_vrotri_d: -+ return DAG.getNode(LoongArchISD::VRORI, DL, Op->getValueType(0), -+ Op->getOperand(1), Op->getOperand(2)); -+ case Intrinsic::thread_pointer: { -+ EVT PtrVT = getPointerTy(DAG.getDataLayout()); -+ if (PtrVT == MVT::i64) -+ return DAG.getRegister(LoongArch::TP_64, MVT::i64); -+ return DAG.getRegister(LoongArch::TP, MVT::i32); -+ } -+ } -+} -+ -+SDValue -+LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, -+ SelectionDAG &DAG) const { -+ unsigned Intr = cast(Op->getOperand(1))->getZExtValue(); -+ switch (Intr) { -+ default: -+ return SDValue(); -+ case Intrinsic::loongarch_lsx_vld: -+ return lowerLSXLoadIntr(Op, DAG, Intr, Subtarget); -+ case Intrinsic::loongarch_lasx_xvld: -+ return lowerLASXLoadIntr(Op, DAG, Intr, Subtarget); -+ case Intrinsic::loongarch_lasx_xvldrepl_b: -+ case Intrinsic::loongarch_lasx_xvldrepl_h: -+ case Intrinsic::loongarch_lasx_xvldrepl_w: -+ case Intrinsic::loongarch_lasx_xvldrepl_d: -+ return lowerLASXVLDRIntr(Op, DAG, Intr, Subtarget); -+ case Intrinsic::loongarch_lsx_vldrepl_b: -+ case Intrinsic::loongarch_lsx_vldrepl_h: -+ case Intrinsic::loongarch_lsx_vldrepl_w: -+ case Intrinsic::loongarch_lsx_vldrepl_d: -+ return lowerLSXVLDRIntr(Op, DAG, Intr, Subtarget); -+ } -+} -+ -+SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op, -+ SelectionDAG &DAG) const { -+ unsigned Intr = cast(Op->getOperand(1))->getZExtValue(); -+ switch (Intr) { -+ default: -+ return SDValue(); -+ case Intrinsic::loongarch_lsx_vst: -+ return lowerLSXStoreIntr(Op, DAG, Intr, Subtarget); -+ case Intrinsic::loongarch_lasx_xvst: -+ return lowerLASXStoreIntr(Op, DAG, Intr, Subtarget); -+ } -+} -+ -+// Lower ISD::EXTRACT_VECTOR_ELT into LoongArchISD::VEXTRACT_SEXT_ELT. -+// -+// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We -+// choose to sign-extend but we could have equally chosen zero-extend. The -+// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT -+// result into this node later (possibly changing it to a zero-extend in the -+// process). -+SDValue -+LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ EVT ResTy = Op->getValueType(0); -+ SDValue Op0 = Op->getOperand(0); -+ EVT VecTy = Op0->getValueType(0); -+ -+ if (!VecTy.is128BitVector() && !VecTy.is256BitVector()) -+ return SDValue(); -+ -+ if (ResTy.isInteger()) { -+ SDValue Op1 = Op->getOperand(1); -+ EVT EltTy = VecTy.getVectorElementType(); -+ if (VecTy.is128BitVector()) -+ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1, -+ DAG.getValueType(EltTy)); -+ -+ ConstantSDNode *cn = dyn_cast(Op1); -+ if (!cn) -+ return SDValue(); -+ -+ if (EltTy == MVT::i32 || EltTy == MVT::i64) -+ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1, -+ DAG.getValueType(EltTy)); -+ } -+ -+ return SDValue(); -+} -+ -+SDValue -+LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op, -+ SelectionDAG &DAG) const { -+ -+ MVT VT = Op.getSimpleValueType(); -+ MVT EltVT = VT.getVectorElementType(); -+ -+ SDLoc DL(Op); -+ SDValue Op0 = Op.getOperand(0); -+ SDValue Op1 = Op.getOperand(1); -+ SDValue Op2 = Op.getOperand(2); -+ -+ if (!EltVT.isInteger()) -+ return Op; -+ -+ if (!isa(Op2)) { -+ if (EltVT == MVT::i8 || EltVT == MVT::i16) { -+ return Op; // ==> pseudo -+ // use stack -+ return SDValue(); -+ } else { -+ return Op; -+ } -+ } -+ -+ if (VT.is128BitVector()) -+ return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Op0, Op1, Op2); -+ -+ if (VT.is256BitVector()) { -+ -+ if (EltVT == MVT::i32 || EltVT == MVT::i64) -+ return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Op0, Op1, Op2); -+ -+ return Op; -+ } -+ -+ return SDValue(); -+} -+ -+// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the -+// backend. -+// -+// Lowers according to the following rules: -+// - Constant splats are legal as-is as long as the SplatBitSize is a power of -+// 2 less than or equal to 64 and the value fits into a signed 10-bit -+// immediate -+// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize -+// is a power of 2 less than or equal to 64 and the value does not fit into a -+// signed 10-bit immediate -+// - Non-constant splats are legal as-is. -+// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT. -+// - All others are illegal and must be expanded. -+SDValue LoongArchTargetLowering::lowerBUILD_VECTOR(SDValue Op, -+ SelectionDAG &DAG) const { -+ BuildVectorSDNode *Node = cast(Op); -+ EVT ResTy = Op->getValueType(0); -+ SDLoc DL(Op); -+ APInt SplatValue, SplatUndef; -+ unsigned SplatBitSize; -+ bool HasAnyUndefs; -+ -+ if ((!Subtarget.hasLSX() || !ResTy.is128BitVector()) && -+ (!Subtarget.hasLASX() || !ResTy.is256BitVector())) -+ return SDValue(); -+ -+ if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, -+ 8) && -+ SplatBitSize <= 64) { -+ // We can only cope with 8, 16, 32, or 64-bit elements -+ if ((ResTy.is128BitVector() && SplatBitSize != 8 && SplatBitSize != 16 && -+ SplatBitSize != 32 && SplatBitSize != 64) || -+ (ResTy.is256BitVector() && SplatBitSize != 8 && SplatBitSize != 16 && -+ SplatBitSize != 32 && SplatBitSize != 64)) -+ return SDValue(); -+ -+ // If the value isn't an integer type we will have to bitcast -+ // from an integer type first. Also, if there are any undefs, we must -+ // lower them to defined values first. -+ if (ResTy.isInteger() && !HasAnyUndefs) -+ return Op; -+ -+ EVT ViaVecTy; -+ -+ if ((ResTy.is128BitVector() && -+ !isLSXBySplatBitSize(SplatBitSize, ViaVecTy)) || -+ (ResTy.is256BitVector() && -+ !isLASXBySplatBitSize(SplatBitSize, ViaVecTy))) -+ return SDValue(); -+ -+ // SelectionDAG::getConstant will promote SplatValue appropriately. -+ SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy); -+ -+ // Bitcast to the type we originally wanted -+ if (ViaVecTy != ResTy) -+ Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result); -+ -+ return Result; -+ } else if (DAG.isSplatValue(Op, /* AllowUndefs */ false)) -+ return Op; -+ else if (!isConstantOrUndefBUILD_VECTOR(Node)) { -+ // Use INSERT_VECTOR_ELT operations rather than expand to stores. -+ // The resulting code is the same length as the expansion, but it doesn't -+ // use memory operations -+ EVT ResTy = Node->getValueType(0); -+ -+ assert(ResTy.isVector()); -+ -+ unsigned NumElts = ResTy.getVectorNumElements(); -+ SDValue Vector = DAG.getUNDEF(ResTy); -+ for (unsigned i = 0; i < NumElts; ++i) { -+ Vector = -+ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector, -+ Node->getOperand(i), DAG.getConstant(i, DL, MVT::i32)); -+ } -+ return Vector; -+ } -+ -+ return SDValue(); -+} -+ -+SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ EVT ResTy = Op->getValueType(0); -+ Op = LowerSUINT_TO_FP(ISD::ZERO_EXTEND_VECTOR_INREG, Op, DAG); -+ if (!ResTy.isVector()) -+ return Op; -+ return DAG.getNode(ISD::UINT_TO_FP, DL, ResTy, Op); -+} -+ -+SDValue LoongArchTargetLowering::lowerSINT_TO_FP(SDValue Op, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ EVT ResTy = Op->getValueType(0); -+ Op = LowerSUINT_TO_FP(ISD::SIGN_EXTEND_VECTOR_INREG, Op, DAG); -+ if (!ResTy.isVector()) -+ return Op; -+ return DAG.getNode(ISD::SINT_TO_FP, DL, ResTy, Op); -+} -+ -+SDValue LoongArchTargetLowering::lowerFP_TO_UINT(SDValue Op, -+ SelectionDAG &DAG) const { -+ if (!Op->getValueType(0).isVector()) -+ return SDValue(); -+ return LowerFP_TO_SUINT(ISD::FP_TO_UINT, ISD::ZERO_EXTEND_VECTOR_INREG, Op, -+ DAG); -+} -+ -+SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, -+ SelectionDAG &DAG) const { -+ if (Op->getValueType(0).isVector()) -+ return LowerFP_TO_SUINT(ISD::FP_TO_SINT, ISD::SIGN_EXTEND_VECTOR_INREG, Op, -+ DAG); -+ -+ if (Op.getValueSizeInBits() > 32 && Subtarget.isSingleFloat()) -+ return SDValue(); -+ -+ EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); -+ SDValue Trunc = -+ DAG.getNode(LoongArchISD::TruncIntFP, SDLoc(Op), FPTy, Op.getOperand(0)); -+ return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); -+} -+ -+static bool checkUndef(ArrayRef Mask, int Lo, int Hi) { -+ -+ for (int i = Lo, end = Hi; i != end; i++, Hi++) -+ if (!((Mask[i] == -1) || (Mask[i] == Hi))) -+ return false; -+ return true; -+} -+ -+static bool CheckRev(ArrayRef Mask) { -+ -+ int Num = Mask.size() - 1; -+ for (long unsigned int i = 0; i < Mask.size(); i++, Num--) -+ if (Mask[i] != Num) -+ return false; -+ return true; -+} -+ -+static bool checkHalf(ArrayRef Mask, int Lo, int Hi, int base) { -+ -+ for (int i = Lo; i < Hi; i++) -+ if (Mask[i] != (base + i)) -+ return false; -+ return true; -+} -+ -+static SDValue lowerHalfHalf(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, -+ ArrayRef Mask, SelectionDAG &DAG) { -+ -+ int Num = VT.getVectorNumElements(); -+ int HalfNum = Num / 2; -+ -+ if (Op1->isUndef() || Op2->isUndef() || Mask.size() > (long unsigned int)Num) -+ return SDValue(); -+ -+ if (checkHalf(Mask, HalfNum, Num, Num) && checkHalf(Mask, 0, HalfNum, 0)) { -+ return SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, -+ DAG.getTargetConstant(48, DL, MVT::i32)), -+ 0); -+ } -+ -+ return SDValue(); -+} -+ -+static bool checkHalfUndef(ArrayRef Mask, int Lo, int Hi) { -+ -+ for (int i = Lo; i < Hi; i++) -+ if (Mask[i] != -1) -+ return false; -+ return true; -+} -+ -+// Lowering vectors with half undef data, -+// use EXTRACT_SUBVECTOR and INSERT_SUBVECTOR instead of VECTOR_SHUFFLE -+static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, -+ ArrayRef Mask, SelectionDAG &DAG) { -+ -+ int Num = VT.getVectorNumElements(); -+ int HalfNum = Num / 2; -+ MVT HalfVT = MVT::getVectorVT(VT.getVectorElementType(), HalfNum); -+ MVT VT1 = Op1.getSimpleValueType(); -+ SDValue Op; -+ -+ bool check1 = Op1->isUndef() && (!Op2->isUndef()); -+ bool check2 = Op2->isUndef() && (!Op1->isUndef()); -+ -+ if ((check1 || check2) && (VT1 == VT)) { -+ if (check1) { -+ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op2); -+ } else if (check2) { -+ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op1); -+ } -+ -+ if (VT == MVT::v32i8 && CheckRev(Mask)) { -+ SDValue Vector; -+ SDValue Rev[4]; -+ SDValue Ext[4]; -+ for (int i = 0; i < 4; i++) { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op, -+ DAG.getConstant(i, DL, MVT::i32)); -+ Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]); -+ } -+ -+ Vector = -+ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, DAG.getUNDEF(VT), -+ Rev[3], DAG.getConstant(3, DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, -+ Rev[2], DAG.getConstant(2, DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, -+ Rev[1], DAG.getConstant(1, DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, -+ Rev[0], DAG.getConstant(0, DL, MVT::i32)); -+ -+ Vector = DAG.getNode(ISD::BITCAST, DL, MVT::v32i8, Vector); -+ -+ return Vector; -+ } -+ } -+ -+ if (checkHalfUndef(Mask, HalfNum, Num) && checkUndef(Mask, 0, HalfNum)) { -+ SDValue High = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Op1, -+ DAG.getConstant(HalfNum, DL, MVT::i64)); -+ return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), High, -+ DAG.getConstant(0, DL, MVT::i64)); -+ } -+ -+ if (checkHalfUndef(Mask, HalfNum, Num) && (VT == MVT::v8i32) && -+ (Mask[0] == 0) && (Mask[1] == 1) && (Mask[2] == (Num + 2)) && -+ (Mask[3] == (Num + 3))) { -+ -+ SDValue Val1 = -+ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, -+ DAG.getTargetConstant(32, DL, MVT::i32)), -+ 0); -+ -+ SDValue Val2 = -+ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_D, DL, VT, Val1, -+ DAG.getTargetConstant(12, DL, MVT::i32)), -+ 0); -+ -+ SDValue Val3 = SDValue( -+ DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Val2, DAG.getUNDEF(VT), -+ DAG.getTargetConstant(2, DL, MVT::i32)), -+ 0); -+ return Val3; -+ } -+ -+ if (checkHalfUndef(Mask, 0, HalfNum) && checkUndef(Mask, HalfNum, Num)) { -+ SDValue Low = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Op1, -+ DAG.getConstant(0, DL, MVT::i32)); -+ return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), Low, -+ DAG.getConstant(HalfNum, DL, MVT::i32)); -+ } -+ -+ if (checkHalfUndef(Mask, 0, HalfNum) && (VT == MVT::v8i32) && -+ (Mask[HalfNum] == HalfNum) && (Mask[HalfNum + 1] == (HalfNum + 1)) && -+ (Mask[HalfNum + 2] == (2 * Num - 2)) && -+ (Mask[HalfNum + 3] == (2 * Num - 1))) { -+ -+ SDValue Val1 = -+ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, -+ DAG.getTargetConstant(49, DL, MVT::i32)), -+ 0); -+ -+ SDValue Val2 = -+ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_D, DL, VT, Val1, -+ DAG.getTargetConstant(12, DL, MVT::i32)), -+ 0); -+ -+ SDValue Val3 = SDValue( -+ DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Val2, DAG.getUNDEF(VT), -+ DAG.getTargetConstant(32, DL, MVT::i32)), -+ 0); -+ return Val3; -+ } -+ -+ if ((VT == MVT::v8i32) || (VT == MVT::v4i64)) { -+ int def = 0; -+ int j = 0; -+ int ext[3]; -+ int ins[3]; -+ bool useOp1[3] = {true, true, true}; -+ bool checkdef = true; -+ -+ for (int i = 0; i < Num; i++) { -+ if (def > 2) { -+ checkdef = false; -+ break; -+ } -+ if (Mask[i] != -1) { -+ def++; -+ ins[j] = i; -+ if (Mask[i] >= Num) { -+ ext[j] = Mask[i] - Num; -+ useOp1[j] = false; -+ } else { -+ ext[j] = Mask[i]; -+ } -+ j++; -+ } -+ } -+ -+ if (checkdef) { -+ SDValue Vector = DAG.getUNDEF(VT); -+ EVT EltTy = VT.getVectorElementType(); -+ SDValue Ext[2]; -+ -+ if (check1 || check2) { -+ for (int i = 0; i < def; i++) { -+ if (check1) { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2, -+ DAG.getConstant(ext[i], DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], -+ DAG.getConstant(ins[i], DL, MVT::i32)); -+ } else if (check2) { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1, -+ DAG.getConstant(ext[i], DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], -+ DAG.getConstant(ins[i], DL, MVT::i32)); -+ } -+ } -+ return Vector; -+ } else { -+ for (int i = 0; i < def; i++) { -+ if (!useOp1[i]) { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2, -+ DAG.getConstant(ext[i], DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], -+ DAG.getConstant(ins[i], DL, MVT::i32)); -+ } else { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1, -+ DAG.getConstant(ext[i], DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], -+ DAG.getConstant(ins[i], DL, MVT::i32)); -+ } -+ } -+ return Vector; -+ } -+ } -+ } -+ -+ return SDValue(); -+} -+ -+static SDValue lowerHalfUndef_LSX(const SDLoc &DL, EVT ResTy, MVT VT, -+ SDValue Op1, SDValue Op2, ArrayRef Mask, -+ SelectionDAG &DAG) { -+ -+ MVT VT1 = Op1.getSimpleValueType(); -+ -+ bool check1 = Op1->isUndef() && (!Op2->isUndef()); -+ bool check2 = Op2->isUndef() && (!Op1->isUndef()); -+ -+ if ((check1 || check2) && (VT1 == VT)) { -+ SDValue Op; -+ -+ if (VT == MVT::v16i8 && CheckRev(Mask)) { -+ -+ if (check1) { -+ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op2); -+ } else if (check2) { -+ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op1); -+ } -+ -+ SDValue Vector; -+ SDValue Rev[2]; -+ SDValue Ext[2]; -+ for (int i = 0; i < 2; i++) { -+ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op, -+ DAG.getConstant(i, DL, MVT::i32)); -+ Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]); -+ } -+ -+ Vector = -+ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, DAG.getUNDEF(VT), -+ Rev[1], DAG.getConstant(1, DL, MVT::i32)); -+ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, Vector, -+ Rev[0], DAG.getConstant(0, DL, MVT::i32)); -+ -+ Vector = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, Vector); -+ -+ return Vector; -+ } -+ } -+ -+ return SDValue(); -+} -+ -+// Use SDNode of LoongArchINSVE instead of -+// a series of EXTRACT_VECTOR_ELT and INSERT_VECTOR_ELT -+static SDValue lowerVECTOR_SHUFFLE_INSVE(const SDLoc &DL, MVT VT, EVT ResTy, -+ SDValue Op1, SDValue Op2, -+ ArrayRef Mask, -+ SelectionDAG &DAG) { -+ -+ int Num = VT.getVectorNumElements(); -+ if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8) -+ return SDValue(); -+ -+ int CheckOne = 0; -+ int CheckOther = 0; -+ int Idx; -+ -+ for (int i = 0; i < Num; i++) { -+ if ((Mask[i] == i) || (Mask[i] == -1)) { -+ CheckOther++; -+ } else if (Mask[i] == Num) { -+ CheckOne++; -+ Idx = i; -+ } else -+ return SDValue(); -+ } -+ -+ if ((CheckOne != 1) || (CheckOther != (Num - 1))) -+ return SDValue(); -+ else { -+ return DAG.getNode(LoongArchISD::INSVE, DL, ResTy, Op1, Op2, -+ DAG.getConstant(Idx, DL, MVT::i32)); -+ } -+ -+ return SDValue(); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVPICKVE(const SDLoc &DL, MVT VT, EVT ResTy, -+ SDValue Op1, SDValue Op2, -+ ArrayRef Mask, -+ SelectionDAG &DAG) { -+ -+ int Num = VT.getVectorNumElements(); -+ if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8 || -+ (!ISD::isBuildVectorAllZeros(Op1.getNode()))) -+ return SDValue(); -+ -+ bool CheckV = true; -+ -+ if ((Mask[0] < Num) || (Mask[0] > (2 * Num - 1))) -+ CheckV = false; -+ -+ for (int i = 1; i < Num; i++) { -+ if (Mask[i] != 0) { -+ CheckV = false; -+ break; -+ } -+ } -+ -+ if (!CheckV) -+ return SDValue(); -+ else { -+ return DAG.getNode(LoongArchISD::XVPICKVE, DL, ResTy, Op1, Op2, -+ DAG.getConstant(Mask[0] - Num, DL, MVT::i32)); -+ } -+ -+ return SDValue(); -+} -+ -+static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, MVT VT, EVT ResTy, -+ SDValue Op1, SDValue Op2, -+ ArrayRef Mask, -+ SelectionDAG &DAG) { -+ -+ if (VT == MVT::v4i64) { -+ int Num = VT.getVectorNumElements(); -+ -+ bool CheckV = true; -+ for (int i = 0; i < Num; i++) { -+ if (Mask[i] != (i * 2)) { -+ CheckV = false; -+ break; -+ } -+ } -+ -+ if (!CheckV) -+ return SDValue(); -+ else { -+ SDValue Res = DAG.getNode(LoongArchISD::XVSHUF4I, DL, ResTy, Op1, Op2, -+ DAG.getConstant(8, DL, MVT::i32)); -+ return DAG.getNode(LoongArchISD::XVPERMI, DL, ResTy, Res, -+ DAG.getConstant(0xD8, DL, MVT::i32)); -+ } -+ } else -+ return SDValue(); -+} -+ -+// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the -+// indices in the shuffle. -+SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, -+ SelectionDAG &DAG) const { -+ ShuffleVectorSDNode *Node = cast(Op); -+ EVT ResTy = Op->getValueType(0); -+ ArrayRef Mask = Node->getMask(); -+ SDValue Op1 = Op.getOperand(0); -+ SDValue Op2 = Op.getOperand(1); -+ MVT VT = Op.getSimpleValueType(); -+ SDLoc DL(Op); -+ -+ if (ResTy.is128BitVector()) { -+ -+ int ResTyNumElts = ResTy.getVectorNumElements(); -+ SmallVector Indices; -+ -+ for (int i = 0; i < ResTyNumElts; ++i) -+ Indices.push_back(Node->getMaskElt(i)); -+ -+ SDValue Result; -+ if (isVECTOR_SHUFFLE_VREPLVEI(Op, ResTy, Indices, DAG)) -+ return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); -+ if ((Result = lowerVECTOR_SHUFFLE_VPACKEV(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_VPACKOD(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_VILVH(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_VILVL(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_VPICKEV(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_VPICKOD(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerHalfUndef_LSX(DL, ResTy, VT, Op1, Op2, Mask, DAG))) -+ return Result; -+ return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); -+ -+ } else if (ResTy.is256BitVector()) { -+ int ResTyNumElts = ResTy.getVectorNumElements(); -+ SmallVector Indices; -+ -+ for (int i = 0; i < ResTyNumElts; ++i) -+ Indices.push_back(Node->getMaskElt(i)); -+ -+ SDValue Result; -+ if ((Result = lowerHalfHalf(DL, VT, Op1, Op2, Mask, DAG))) -+ return Result; -+ if ((Result = lowerHalfUndef(DL, VT, Op1, Op2, Mask, DAG))) -+ return Result; -+ if (isVECTOR_SHUFFLE_XVREPLVEI(Op, ResTy, Indices, DAG)) -+ return SDValue(); -+ if ((Result = lowerVECTOR_SHUFFLE_XVPACKEV(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XVPACKOD(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XVILVH(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XVILVL(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XVPICKEV(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XVPICKOD(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = lowerVECTOR_SHUFFLE_XSHF(Op, ResTy, Indices, DAG))) -+ return Result; -+ if ((Result = -+ lowerVECTOR_SHUFFLE_INSVE(DL, VT, ResTy, Op1, Op2, Mask, DAG))) -+ return Result; -+ if ((Result = -+ lowerVECTOR_SHUFFLE_XVPICKVE(DL, VT, ResTy, Op1, Op2, Mask, DAG))) -+ return Result; -+ if ((Result = -+ lowerVECTOR_SHUFFLE_XVSHUF(DL, VT, ResTy, Op1, Op2, Mask, DAG))) -+ return Result; -+ } -+ -+ return SDValue(); -+} -+ -+SDValue LoongArchTargetLowering::lowerEH_DWARF_CFA(SDValue Op, -+ SelectionDAG &DAG) const { -+ -+ // Return a fixed StackObject with offset 0 which points to the old stack -+ // pointer. -+ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); -+ EVT ValTy = Op->getValueType(0); -+ int FI = MFI.CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); -+ return DAG.getFrameIndex(FI, ValTy); -+} -+ -+// Check whether the tail call optimization conditions are met -+bool LoongArchTargetLowering::isEligibleForTailCallOptimization( -+ const CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, -+ unsigned NextStackOffset, const LoongArchFunctionInfo &FI) const { -+ -+ auto CalleeCC = CLI.CallConv; -+ auto IsVarArg = CLI.IsVarArg; -+ auto &Outs = CLI.Outs; -+ auto &Caller = MF.getFunction(); -+ auto CallerCC = Caller.getCallingConv(); -+ -+ if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true") -+ return false; -+ -+ if (Caller.hasFnAttribute("interrupt")) -+ return false; -+ -+ if (IsVarArg) -+ return false; -+ -+ if (getTargetMachine().getCodeModel() == CodeModel::Large) -+ return false; -+ -+ if (getTargetMachine().getRelocationModel() == Reloc::Static) -+ return false; -+ -+ // Do not tail call optimize if the stack is used to pass parameters. -+ if (CCInfo.getNextStackOffset() != 0) -+ return false; -+ -+ // Do not tail call optimize functions with byval parameters. -+ for (auto &Arg : Outs) -+ if (Arg.Flags.isByVal()) -+ return false; -+ -+ // Do not tail call optimize if either caller or callee uses structret -+ // semantics. -+ auto IsCallerStructRet = Caller.hasStructRetAttr(); -+ auto IsCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet(); -+ if (IsCallerStructRet || IsCalleeStructRet) -+ return false; -+ -+ // The callee has to preserve all registers the caller needs to preserve. -+ const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo(); -+ const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC); -+ if (CalleeCC != CallerCC) { -+ const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC); -+ if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) -+ return false; -+ } -+ -+ // Return false if either the callee or caller has a byval argument. -+ if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg()) -+ return false; -+ -+ // Return true if the callee's argument area is no larger than the -+ // caller's. -+ return NextStackOffset <= FI.getIncomingArgSize(); -+} -+ -+//===----------------------------------------------------------------------===// -+// Calling Convention Implementation -+//===----------------------------------------------------------------------===// -+ -+//===----------------------------------------------------------------------===// -+// TODO: Implement a generic logic using tblgen that can support this. -+// LoongArch LP32 ABI rules: -+// --- -+// i32 - Passed in A0, A1, A2, A3 and stack -+// f32 - Only passed in f32 registers if no int reg has been used yet to hold -+// an argument. Otherwise, passed in A1, A2, A3 and stack. -+// f64 - Only passed in two aliased f32 registers if no int reg has been used -+// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is -+// not used, it must be shadowed. If only A3 is available, shadow it and -+// go to stack. -+// vXiX - Received as scalarized i32s, passed in A0 - A3 and the stack. -+// vXf32 - Passed in either a pair of registers {A0, A1}, {A2, A3} or {A0 - A3} -+// with the remainder spilled to the stack. -+// vXf64 - Passed in either {A0, A1, A2, A3} or {A2, A3} and in both cases -+// spilling the remainder to the stack. -+// -+// For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. -+//===----------------------------------------------------------------------===// -+ -+static bool CC_LoongArchLP32(unsigned ValNo, MVT ValVT, MVT LocVT, -+ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, -+ CCState &State, ArrayRef F64Regs) { -+ static const MCPhysReg IntRegs[] = { LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3 }; -+ -+ const LoongArchCCState * LoongArchState = static_cast(&State); -+ -+ static const MCPhysReg F32Regs[] = { LoongArch::F12, LoongArch::F14 }; -+ -+ static const MCPhysReg FloatVectorIntRegs[] = { LoongArch::A0, LoongArch::A2 }; -+ -+ // Do not process byval args here. -+ if (ArgFlags.isByVal()) -+ return true; -+ -+ -+ // Promote i8 and i16 -+ if (LocVT == MVT::i8 || LocVT == MVT::i16) { -+ LocVT = MVT::i32; -+ if (ArgFlags.isSExt()) -+ LocInfo = CCValAssign::SExt; -+ else if (ArgFlags.isZExt()) -+ LocInfo = CCValAssign::ZExt; -+ else -+ LocInfo = CCValAssign::AExt; -+ } -+ -+ unsigned Reg; -+ -+ // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following -+ // is true: function is vararg, argument is 3rd or higher, there is previous -+ // argument which is not f32 or f64. -+ bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || -+ State.getFirstUnallocated(F32Regs) != ValNo; -+ Align OrigAlign = ArgFlags.getNonZeroOrigAlign(); -+ bool isI64 = (ValVT == MVT::i32 && OrigAlign == Align(8)); -+ bool isVectorFloat = LoongArchState->WasOriginalArgVectorFloat(ValNo); -+ -+ // The LoongArch vector ABI for floats passes them in a pair of registers -+ if (ValVT == MVT::i32 && isVectorFloat) { -+ // This is the start of an vector that was scalarized into an unknown number -+ // of components. It doesn't matter how many there are. Allocate one of the -+ // notional 8 byte aligned registers which map onto the argument stack, and -+ // shadow the register lost to alignment requirements. -+ if (ArgFlags.isSplit()) { -+ Reg = State.AllocateReg(FloatVectorIntRegs); -+ if (Reg == LoongArch::A2) -+ State.AllocateReg(LoongArch::A1); -+ else if (Reg == 0) -+ State.AllocateReg(LoongArch::A3); -+ } else { -+ // If we're an intermediate component of the split, we can just attempt to -+ // allocate a register directly. -+ Reg = State.AllocateReg(IntRegs); -+ } -+ } else if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { -+ Reg = State.AllocateReg(IntRegs); -+ // If this is the first part of an i64 arg, -+ // the allocated register must be either A0 or A2. -+ if (isI64 && (Reg == LoongArch::A1 || Reg == LoongArch::A3)) -+ Reg = State.AllocateReg(IntRegs); -+ LocVT = MVT::i32; -+ } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { -+ // Allocate int register and shadow next int register. If first -+ // available register is LoongArch::A1 or LoongArch::A3, shadow it too. -+ Reg = State.AllocateReg(IntRegs); -+ if (Reg == LoongArch::A1 || Reg == LoongArch::A3) -+ Reg = State.AllocateReg(IntRegs); -+ State.AllocateReg(IntRegs); -+ LocVT = MVT::i32; -+ } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { -+ // we are guaranteed to find an available float register -+ if (ValVT == MVT::f32) { -+ Reg = State.AllocateReg(F32Regs); -+ // Shadow int register -+ State.AllocateReg(IntRegs); -+ } else { -+ Reg = State.AllocateReg(F64Regs); -+ // Shadow int registers -+ unsigned Reg2 = State.AllocateReg(IntRegs); -+ if (Reg2 == LoongArch::A1 || Reg2 == LoongArch::A3) -+ State.AllocateReg(IntRegs); -+ State.AllocateReg(IntRegs); -+ } -+ } else -+ llvm_unreachable("Cannot handle this ValVT."); -+ -+ if (!Reg) { -+ unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign); -+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); -+ } else -+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); -+ -+ return false; -+} -+ -+static bool CC_LoongArchLP32_FP32(unsigned ValNo, MVT ValVT, -+ MVT LocVT, CCValAssign::LocInfo LocInfo, -+ ISD::ArgFlagsTy ArgFlags, CCState &State) { -+ static const MCPhysReg F64Regs[] = {LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, \ -+ LoongArch::F3_64, LoongArch::F4_64, LoongArch::F5_64, \ -+ LoongArch::F6_64, LoongArch::F7_64 }; -+ -+ return CC_LoongArchLP32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); -+} -+ -+static bool CC_LoongArchLP32_FP64(unsigned ValNo, MVT ValVT, -+ MVT LocVT, CCValAssign::LocInfo LocInfo, -+ ISD::ArgFlagsTy ArgFlags, CCState &State) { -+ static const MCPhysReg F64Regs[] = {LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, \ -+ LoongArch::F3_64, LoongArch::F4_64, LoongArch::F5_64, \ -+ LoongArch::F6_64, LoongArch::F7_64 }; -+ -+ return CC_LoongArchLP32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); -+} -+ -+static bool CC_LoongArch_F128(unsigned ValNo, MVT ValVT, -+ MVT LocVT, CCValAssign::LocInfo LocInfo, -+ ISD::ArgFlagsTy ArgFlags, CCState &State) LLVM_ATTRIBUTE_UNUSED; -+ -+static bool CC_LoongArch_F128(unsigned ValNo, MVT ValVT, -+ MVT LocVT, CCValAssign::LocInfo LocInfo, -+ ISD::ArgFlagsTy ArgFlags, CCState &State) { -+ -+ static const MCPhysReg ArgRegs[8] = { -+ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64, -+ LoongArch::A4_64, LoongArch::A5_64, LoongArch::A6_64, LoongArch::A7_64}; -+ -+ unsigned Idx = State.getFirstUnallocated(ArgRegs); -+ // Skip 'odd' register if necessary. -+ if (!ArgFlags.isSplitEnd() && Idx != array_lengthof(ArgRegs) && Idx % 2 == 1) -+ State.AllocateReg(ArgRegs); -+ return true; -+} -+ -+static bool CC_LoongArchLP32(unsigned ValNo, MVT ValVT, MVT LocVT, -+ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, -+ CCState &State) LLVM_ATTRIBUTE_UNUSED; -+ -+#include "LoongArchGenCallingConv.inc" -+ -+ CCAssignFn *LoongArchTargetLowering::CCAssignFnForCall() const{ -+ return CC_LoongArch; -+ } -+ -+ CCAssignFn *LoongArchTargetLowering::CCAssignFnForReturn() const{ -+ return RetCC_LoongArch; -+ } -+ -+//===----------------------------------------------------------------------===// -+// Call Calling Convention Implementation -+//===----------------------------------------------------------------------===// -+SDValue LoongArchTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, -+ SDValue Chain, SDValue Arg, -+ const SDLoc &DL, bool IsTailCall, -+ SelectionDAG &DAG) const { -+ if (!IsTailCall) { -+ SDValue PtrOff = -+ DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr, -+ DAG.getIntPtrConstant(Offset, DL)); -+ return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()); -+ } -+ -+ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); -+ int FI = MFI.CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); -+ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); -+ return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), -+ /* Alignment = */ 0, MachineMemOperand::MOVolatile); -+} -+ -+void LoongArchTargetLowering::getOpndList( -+ SmallVectorImpl &Ops, -+ std::deque> &RegsToPass, bool IsPICCall, -+ bool GlobalOrExternal, bool IsCallReloc, CallLoweringInfo &CLI, -+ SDValue Callee, SDValue Chain, bool IsTailCall) const { -+ // Build a sequence of copy-to-reg nodes chained together with token -+ // chain and flag operands which copy the outgoing args into registers. -+ // The InFlag in necessary since all emitted instructions must be -+ // stuck together. -+ SDValue InFlag; -+ -+ Ops.push_back(Callee); -+ -+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { -+ Chain = CLI.DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first, -+ RegsToPass[i].second, InFlag); -+ InFlag = Chain.getValue(1); -+ } -+ -+ // Add argument registers to the end of the list so that they are -+ // known live into the call. -+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) -+ Ops.push_back(CLI.DAG.getRegister(RegsToPass[i].first, -+ RegsToPass[i].second.getValueType())); -+ -+ if (!IsTailCall) { -+ // Add a register mask operand representing the call-preserved registers. -+ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); -+ const uint32_t *Mask = -+ TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv); -+ assert(Mask && "Missing call preserved mask for calling convention"); -+ Ops.push_back(CLI.DAG.getRegisterMask(Mask)); -+ } -+ -+ if (InFlag.getNode()) -+ Ops.push_back(InFlag); -+} -+ -+void LoongArchTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, -+ SDNode *Node) const { -+ switch (MI.getOpcode()) { -+ default: -+ return; -+ } -+} -+ -+/// LowerCall - functions arguments are copied from virtual regs to -+/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. -+SDValue -+LoongArchTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, -+ SmallVectorImpl &InVals) const { -+ SelectionDAG &DAG = CLI.DAG; -+ SDLoc DL = CLI.DL; -+ SmallVectorImpl &Outs = CLI.Outs; -+ SmallVectorImpl &OutVals = CLI.OutVals; -+ SmallVectorImpl &Ins = CLI.Ins; -+ SDValue Chain = CLI.Chain; -+ SDValue Callee = CLI.Callee; -+ bool &IsTailCall = CLI.IsTailCall; -+ CallingConv::ID CallConv = CLI.CallConv; -+ bool IsVarArg = CLI.IsVarArg; -+ -+ MachineFunction &MF = DAG.getMachineFunction(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); -+ bool IsPIC = isPositionIndependent(); -+ -+ // Analyze operands of the call, assigning locations to each operand. -+ SmallVector ArgLocs; -+ LoongArchCCState CCInfo( -+ CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), -+ LoongArchCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); -+ -+ const ExternalSymbolSDNode *ES = -+ dyn_cast_or_null(Callee.getNode()); -+ -+ // There is one case where CALLSEQ_START..CALLSEQ_END can be nested, which -+ // is during the lowering of a call with a byval argument which produces -+ // a call to memcpy. For the LP32 case, this causes the caller to allocate -+ // stack space for the reserved argument area for the callee, then recursively -+ // again for the memcpy call. In the NEWABI case, this doesn't occur as those -+ // ABIs mandate that the callee allocates the reserved argument area. We do -+ // still produce nested CALLSEQ_START..CALLSEQ_END with zero space though. -+ // -+ // If the callee has a byval argument and memcpy is used, we are mandated -+ // to already have produced a reserved argument area for the callee for LP32. -+ // Therefore, the reserved argument area can be reused for both calls. -+ // -+ // Other cases of calling memcpy cannot have a chain with a CALLSEQ_START -+ // present, as we have yet to hook that node onto the chain. -+ // -+ // Hence, the CALLSEQ_START and CALLSEQ_END nodes can be eliminated in this -+ // case. GCC does a similar trick, in that wherever possible, it calculates -+ // the maximum out going argument area (including the reserved area), and -+ // preallocates the stack space on entrance to the caller. -+ // -+ // FIXME: We should do the same for efficiency and space. -+ -+ bool MemcpyInByVal = ES && -+ StringRef(ES->getSymbol()) == StringRef("memcpy") && -+ Chain.getOpcode() == ISD::CALLSEQ_START; -+ -+ CCInfo.AnalyzeCallOperands(Outs, CC_LoongArch, CLI.getArgs(), -+ ES ? ES->getSymbol() : nullptr); -+ -+ // Get a count of how many bytes are to be pushed on the stack. -+ unsigned NextStackOffset = CCInfo.getNextStackOffset(); -+ -+ // Check if it's really possible to do a tail call. Restrict it to functions -+ // that are part of this compilation unit. -+ if (IsTailCall) { -+ IsTailCall = isEligibleForTailCallOptimization( -+ CCInfo, CLI, MF, NextStackOffset, *MF.getInfo()); -+ if (GlobalAddressSDNode *G = dyn_cast(Callee)) { -+ if (G->getGlobal()->hasExternalWeakLinkage()) -+ IsTailCall = false; -+ } -+ } -+ if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall()) -+ report_fatal_error("failed to perform tail call elimination on a call " -+ "site marked musttail"); -+ -+ if (IsTailCall) -+ ++NumTailCalls; -+ -+ // Chain is the output chain of the last Load/Store or CopyToReg node. -+ // ByValChain is the output chain of the last Memcpy node created for copying -+ // byval arguments to the stack. -+ unsigned StackAlignment = TFL->getStackAlignment(); -+ NextStackOffset = alignTo(NextStackOffset, StackAlignment); -+ SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); -+ -+ if (!(IsTailCall || MemcpyInByVal)) -+ Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); -+ -+ SDValue StackPtr = -+ DAG.getCopyFromReg(Chain, DL, ABI.IsLP64() ? LoongArch::SP_64 : LoongArch::SP, -+ getPointerTy(DAG.getDataLayout())); -+ -+ std::deque> RegsToPass; -+ SmallVector MemOpChains; -+ -+ CCInfo.rewindByValRegsInfo(); -+ -+ // Walk the register/memloc assignments, inserting copies/loads. -+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { -+ SDValue Arg = OutVals[i]; -+ CCValAssign &VA = ArgLocs[i]; -+ MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); -+ ISD::ArgFlagsTy Flags = Outs[i].Flags; -+ bool UseUpperBits = false; -+ -+ // ByVal Arg. -+ if (Flags.isByVal()) { -+ unsigned FirstByValReg, LastByValReg; -+ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); -+ CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); -+ -+ assert(Flags.getByValSize() && -+ "ByVal args of size 0 should have been ignored by front-end."); -+ assert(ByValIdx < CCInfo.getInRegsParamsCount()); -+ assert(!IsTailCall && -+ "Do not tail-call optimize if there is a byval argument."); -+ passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, -+ FirstByValReg, LastByValReg, Flags, -+ VA); -+ CCInfo.nextInRegsParam(); -+ continue; -+ } -+ -+ // Promote the value if needed. -+ switch (VA.getLocInfo()) { -+ default: -+ llvm_unreachable("Unknown loc info!"); -+ case CCValAssign::Full: -+ if (VA.isRegLoc()) { -+ if ((ValVT == MVT::f32 && LocVT == MVT::i32) || -+ (ValVT == MVT::f64 && LocVT == MVT::i64) || -+ (ValVT == MVT::i64 && LocVT == MVT::f64)) -+ Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); -+ } -+ break; -+ case CCValAssign::BCvt: -+ Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); -+ break; -+ case CCValAssign::SExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::SExt: -+ Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); -+ break; -+ case CCValAssign::ZExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::ZExt: -+ Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); -+ break; -+ case CCValAssign::AExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::AExt: -+ Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); -+ break; -+ } -+ -+ if (UseUpperBits) { -+ unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); -+ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); -+ Arg = DAG.getNode( -+ ISD::SHL, DL, VA.getLocVT(), Arg, -+ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); -+ } -+ -+ // Arguments that can be passed on register must be kept at -+ // RegsToPass vector -+ if (VA.isRegLoc()) { -+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); -+ continue; -+ } -+ -+ // Register can't get to this point... -+ assert(VA.isMemLoc()); -+ -+ // emit ISD::STORE whichs stores the -+ // parameter value to a stack Location -+ MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), -+ Chain, Arg, DL, IsTailCall, DAG)); -+ } -+ -+ // Transform all store nodes into one single node because all store -+ // nodes are independent of each other. -+ if (!MemOpChains.empty()) -+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); -+ -+ // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every -+ // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol -+ // node so that legalize doesn't hack it. -+ -+ bool GlobalOrExternal = false, IsCallReloc = false; -+ -+ if (GlobalAddressSDNode *G = dyn_cast(Callee)) { -+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, -+ getPointerTy(DAG.getDataLayout()), 0, -+ LoongArchII::MO_NO_FLAG); -+ GlobalOrExternal = true; -+ } -+ else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { -+ const char *Sym = S->getSymbol(); -+ Callee = DAG.getTargetExternalSymbol( -+ Sym, getPointerTy(DAG.getDataLayout()), LoongArchII::MO_NO_FLAG); -+ -+ GlobalOrExternal = true; -+ } -+ -+ SmallVector Ops(1, Chain); -+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); -+ -+ getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, IsCallReloc, CLI, -+ Callee, Chain, IsTailCall); -+ -+ if (IsTailCall) { -+ MF.getFrameInfo().setHasTailCall(); -+ return DAG.getNode(LoongArchISD::TailCall, DL, MVT::Other, Ops); -+ } -+ -+ Chain = DAG.getNode(LoongArchISD::JmpLink, DL, NodeTys, Ops); -+ DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); -+ SDValue InFlag = Chain.getValue(1); -+ -+ // Create the CALLSEQ_END node in the case of where it is not a call to -+ // memcpy. -+ if (!(MemcpyInByVal)) { -+ Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, -+ DAG.getIntPtrConstant(0, DL, true), InFlag, DL); -+ InFlag = Chain.getValue(1); -+ } -+ -+ // Handle result values, copying them out of physregs into vregs that we -+ // return. -+ return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, -+ InVals, CLI); -+} -+ -+/// LowerCallResult - Lower the result values of a call into the -+/// appropriate copies out of appropriate physical registers. -+SDValue LoongArchTargetLowering::LowerCallResult( -+ SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, -+ const SmallVectorImpl &Ins, const SDLoc &DL, -+ SelectionDAG &DAG, SmallVectorImpl &InVals, -+ TargetLowering::CallLoweringInfo &CLI) const { -+ // Assign locations to each value returned by this call. -+ SmallVector RVLocs; -+ LoongArchCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, -+ *DAG.getContext()); -+ -+ const ExternalSymbolSDNode *ES = -+ dyn_cast_or_null(CLI.Callee.getNode()); -+ CCInfo.AnalyzeCallResult(Ins, RetCC_LoongArch, CLI.RetTy, -+ ES ? ES->getSymbol() : nullptr); -+ -+ // Copy all of the result registers out of their specified physreg. -+ for (unsigned i = 0; i != RVLocs.size(); ++i) { -+ CCValAssign &VA = RVLocs[i]; -+ assert(VA.isRegLoc() && "Can only return in registers!"); -+ -+ SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(), -+ RVLocs[i].getLocVT(), InFlag); -+ Chain = Val.getValue(1); -+ InFlag = Val.getValue(2); -+ -+ if (VA.isUpperBitsInLoc()) { -+ unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits(); -+ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); -+ unsigned Shift = -+ VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; -+ Val = DAG.getNode( -+ Shift, DL, VA.getLocVT(), Val, -+ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); -+ } -+ -+ switch (VA.getLocInfo()) { -+ default: -+ llvm_unreachable("Unknown loc info!"); -+ case CCValAssign::Full: -+ break; -+ case CCValAssign::BCvt: -+ Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); -+ break; -+ case CCValAssign::AExt: -+ case CCValAssign::AExtUpper: -+ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); -+ break; -+ case CCValAssign::ZExt: -+ case CCValAssign::ZExtUpper: -+ Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val, -+ DAG.getValueType(VA.getValVT())); -+ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); -+ break; -+ case CCValAssign::SExt: -+ case CCValAssign::SExtUpper: -+ Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val, -+ DAG.getValueType(VA.getValVT())); -+ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); -+ break; -+ } -+ -+ InVals.push_back(Val); -+ } -+ -+ return Chain; -+} -+ -+static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, -+ EVT ArgVT, const SDLoc &DL, -+ SelectionDAG &DAG) { -+ MVT LocVT = VA.getLocVT(); -+ EVT ValVT = VA.getValVT(); -+ -+ // Shift into the upper bits if necessary. -+ switch (VA.getLocInfo()) { -+ default: -+ break; -+ case CCValAssign::AExtUpper: -+ case CCValAssign::SExtUpper: -+ case CCValAssign::ZExtUpper: { -+ unsigned ValSizeInBits = ArgVT.getSizeInBits(); -+ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); -+ unsigned Opcode = -+ VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; -+ Val = DAG.getNode( -+ Opcode, DL, VA.getLocVT(), Val, -+ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); -+ break; -+ } -+ } -+ -+ // If this is an value smaller than the argument slot size (32-bit for LP32, -+ // 64-bit for LPX32/LP64), it has been promoted in some way to the argument slot -+ // size. Extract the value and insert any appropriate assertions regarding -+ // sign/zero extension. -+ switch (VA.getLocInfo()) { -+ default: -+ llvm_unreachable("Unknown loc info!"); -+ case CCValAssign::Full: -+ break; -+ case CCValAssign::AExtUpper: -+ case CCValAssign::AExt: -+ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); -+ break; -+ case CCValAssign::SExtUpper: -+ case CCValAssign::SExt: { -+ if ((ArgVT == MVT::i1) || (ArgVT == MVT::i8) || (ArgVT == MVT::i16)) { -+ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); -+ Val = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, ValVT, -+ Val, SubReg), -+ 0); -+ } else { -+ Val = -+ DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); -+ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); -+ } -+ break; -+ } -+ case CCValAssign::ZExtUpper: -+ case CCValAssign::ZExt: -+ Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); -+ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); -+ break; -+ case CCValAssign::BCvt: -+ Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); -+ break; -+ } -+ -+ return Val; -+} -+ -+//===----------------------------------------------------------------------===// -+// Formal Arguments Calling Convention Implementation -+//===----------------------------------------------------------------------===// -+/// LowerFormalArguments - transform physical registers into virtual registers -+/// and generate load operations for arguments places on the stack. -+SDValue LoongArchTargetLowering::LowerFormalArguments( -+ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, -+ const SmallVectorImpl &Ins, const SDLoc &DL, -+ SelectionDAG &DAG, SmallVectorImpl &InVals) const { -+ MachineFunction &MF = DAG.getMachineFunction(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); -+ -+ LoongArchFI->setVarArgsFrameIndex(0); -+ -+ // Used with vargs to acumulate store chains. -+ std::vector OutChains; -+ -+ // Assign locations to all of the incoming arguments. -+ SmallVector ArgLocs; -+ LoongArchCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, -+ *DAG.getContext()); -+ const Function &Func = DAG.getMachineFunction().getFunction(); -+ Function::const_arg_iterator FuncArg = Func.arg_begin(); -+ -+ CCInfo.AnalyzeFormalArguments(Ins, CC_LoongArch_FixedArg); -+ LoongArchFI->setFormalArgInfo(CCInfo.getNextStackOffset(), -+ CCInfo.getInRegsParamsCount() > 0); -+ -+ unsigned CurArgIdx = 0; -+ CCInfo.rewindByValRegsInfo(); -+ -+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { -+ CCValAssign &VA = ArgLocs[i]; -+ if (Ins[i].isOrigArg()) { -+ std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); -+ CurArgIdx = Ins[i].getOrigArgIndex(); -+ } -+ EVT ValVT = VA.getValVT(); -+ ISD::ArgFlagsTy Flags = Ins[i].Flags; -+ bool IsRegLoc = VA.isRegLoc(); -+ -+ if (Flags.isByVal()) { -+ assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); -+ unsigned FirstByValReg, LastByValReg; -+ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); -+ CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); -+ -+ assert(Flags.getByValSize() && -+ "ByVal args of size 0 should have been ignored by front-end."); -+ assert(ByValIdx < CCInfo.getInRegsParamsCount()); -+ copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, -+ FirstByValReg, LastByValReg, VA, CCInfo); -+ CCInfo.nextInRegsParam(); -+ continue; -+ } -+ -+ // Arguments stored on registers -+ if (IsRegLoc) { -+ MVT RegVT = VA.getLocVT(); -+ unsigned ArgReg = VA.getLocReg(); -+ const TargetRegisterClass *RC = getRegClassFor(RegVT); -+ -+ // Transform the arguments stored on -+ // physical registers into virtual ones -+ unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); -+ SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); -+ -+ ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); -+ -+ // Handle floating point arguments passed in integer registers and -+ // long double arguments passed in floating point registers. -+ if ((RegVT == MVT::i32 && ValVT == MVT::f32) || -+ (RegVT == MVT::i64 && ValVT == MVT::f64) || -+ (RegVT == MVT::f64 && ValVT == MVT::i64)) -+ ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); -+ else if (ABI.IsLP32() && RegVT == MVT::i32 && -+ ValVT == MVT::f64) { -+ // TODO: lp32 -+ } -+ -+ InVals.push_back(ArgValue); -+ } else { // VA.isRegLoc() -+ MVT LocVT = VA.getLocVT(); -+ -+ if (ABI.IsLP32()) { -+ // We ought to be able to use LocVT directly but LP32 sets it to i32 -+ // when allocating floating point values to integer registers. -+ // This shouldn't influence how we load the value into registers unless -+ // we are targeting softfloat. -+ if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat()) -+ LocVT = VA.getValVT(); -+ } -+ -+ // sanity check -+ assert(VA.isMemLoc()); -+ -+ // The stack pointer offset is relative to the caller stack frame. -+ int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8, -+ VA.getLocMemOffset(), true); -+ -+ // Create load nodes to retrieve arguments from the stack -+ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); -+ SDValue ArgValue = DAG.getLoad( -+ LocVT, DL, Chain, FIN, -+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); -+ OutChains.push_back(ArgValue.getValue(1)); -+ -+ ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); -+ -+ InVals.push_back(ArgValue); -+ } -+ } -+ -+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { -+ // The loongarch ABIs for returning structs by value requires that we copy -+ // the sret argument into $v0 for the return. Save the argument into -+ // a virtual register so that we can access it from the return points. -+ if (Ins[i].Flags.isSRet()) { -+ unsigned Reg = LoongArchFI->getSRetReturnReg(); -+ if (!Reg) { -+ Reg = MF.getRegInfo().createVirtualRegister( -+ getRegClassFor(ABI.IsLP64() ? MVT::i64 : MVT::i32)); -+ LoongArchFI->setSRetReturnReg(Reg); -+ } -+ SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); -+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); -+ break; -+ } - } -- return SDValue(); -+ -+ if (IsVarArg) -+ writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo); -+ -+ // All stores are grouped in one node to allow the matching between -+ // the size of Ins and InVals. This only happens when on varg functions -+ if (!OutChains.empty()) { -+ OutChains.push_back(Chain); -+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); -+ } -+ -+ return Chain; - } - --static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, -- MachineBasicBlock &MBB, -- const TargetInstrInfo &TII) { -- if (!ZeroDivCheck) -- return &MBB; -+//===----------------------------------------------------------------------===// -+// Return Value Calling Convention Implementation -+//===----------------------------------------------------------------------===// - -- // Build instructions: -- // div(or mod) $dst, $dividend, $divisor -- // bnez $divisor, 8 -- // break 7 -- // fallthrough -- MachineOperand &Divisor = MI.getOperand(2); -- auto FallThrough = std::next(MI.getIterator()); -+bool -+LoongArchTargetLowering::CanLowerReturn(CallingConv::ID CallConv, -+ MachineFunction &MF, bool IsVarArg, -+ const SmallVectorImpl &Outs, -+ LLVMContext &Context) const { -+ SmallVector RVLocs; -+ LoongArchCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); -+ return CCInfo.CheckReturn(Outs, RetCC_LoongArch); -+} - -- BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BNEZ)) -- .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) -- .addImm(8); -+bool -+LoongArchTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { -+ if ((ABI.IsLPX32() || ABI.IsLP64()) && Type == MVT::i32) -+ return true; - -- // See linux header file arch/loongarch/include/uapi/asm/break.h for the -- // definition of BRK_DIVZERO. -- BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BREAK)) -- .addImm(7/*BRK_DIVZERO*/); -+ return IsSigned; -+} - -- // Clear Divisor's kill flag. -- Divisor.setIsKill(false); -+SDValue -+LoongArchTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, -+ bool IsVarArg, -+ const SmallVectorImpl &Outs, -+ const SmallVectorImpl &OutVals, -+ const SDLoc &DL, SelectionDAG &DAG) const { -+ // CCValAssign - represent the assignment of -+ // the return value to a location -+ SmallVector RVLocs; -+ MachineFunction &MF = DAG.getMachineFunction(); - -- return &MBB; -+ // CCState - Info about the registers and stack slot. -+ LoongArchCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); -+ -+ // Analyze return values. -+ CCInfo.AnalyzeReturn(Outs, RetCC_LoongArch); -+ -+ SDValue Flag; -+ SmallVector RetOps(1, Chain); -+ -+ // Copy the result values into the output registers. -+ for (unsigned i = 0; i != RVLocs.size(); ++i) { -+ SDValue Val = OutVals[i]; -+ CCValAssign &VA = RVLocs[i]; -+ assert(VA.isRegLoc() && "Can only return in registers!"); -+ bool UseUpperBits = false; -+ -+ switch (VA.getLocInfo()) { -+ default: -+ llvm_unreachable("Unknown loc info!"); -+ case CCValAssign::Full: -+ break; -+ case CCValAssign::BCvt: -+ Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val); -+ break; -+ case CCValAssign::AExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::AExt: -+ Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val); -+ break; -+ case CCValAssign::ZExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::ZExt: -+ Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val); -+ break; -+ case CCValAssign::SExtUpper: -+ UseUpperBits = true; -+ LLVM_FALLTHROUGH; -+ case CCValAssign::SExt: -+ Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val); -+ break; -+ } -+ -+ if (UseUpperBits) { -+ unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); -+ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); -+ Val = DAG.getNode( -+ ISD::SHL, DL, VA.getLocVT(), Val, -+ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); -+ } -+ -+ Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); -+ -+ // Guarantee that all emitted copies are stuck together with flags. -+ Flag = Chain.getValue(1); -+ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); -+ } -+ -+ // The loongarch ABIs for returning structs by value requires that we copy -+ // the sret argument into $v0 for the return. We saved the argument into -+ // a virtual register in the entry block, so now we copy the value out -+ // and into $v0. -+ if (MF.getFunction().hasStructRetAttr()) { -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); -+ unsigned Reg = LoongArchFI->getSRetReturnReg(); -+ -+ if (!Reg) -+ llvm_unreachable("sret virtual register not created in the entry block"); -+ SDValue Val = -+ DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout())); -+ unsigned A0 = ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; -+ -+ Chain = DAG.getCopyToReg(Chain, DL, A0, Val, Flag); -+ Flag = Chain.getValue(1); -+ RetOps.push_back(DAG.getRegister(A0, getPointerTy(DAG.getDataLayout()))); -+ } -+ -+ RetOps[0] = Chain; // Update chain. -+ -+ // Add the flag if we have it. -+ if (Flag.getNode()) -+ RetOps.push_back(Flag); -+ -+ // Standard return on LoongArch is a "jr $ra" -+ return DAG.getNode(LoongArchISD::Ret, DL, MVT::Other, RetOps); - } - --MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter( -- MachineInstr &MI, MachineBasicBlock *BB) const { -+//===----------------------------------------------------------------------===// -+// LoongArch Inline Assembly Support -+//===----------------------------------------------------------------------===// - -- switch (MI.getOpcode()) { -+/// getConstraintType - Given a constraint letter, return the type of -+/// constraint it is for this target. -+LoongArchTargetLowering::ConstraintType -+LoongArchTargetLowering::getConstraintType(StringRef Constraint) const { -+ // LoongArch specific constraints -+ // GCC config/loongarch/constraints.md -+ // -+ // 'f': Floating Point register -+ // 'G': Floating-point 0 -+ // 'l': Signed 16-bit constant -+ // 'R': Memory address that can be used in a non-macro load or store -+ // "ZC" Memory address with 16-bit and 4 bytes aligned offset -+ // "ZB" Memory address with 0 offset -+ -+ if (Constraint.size() == 1) { -+ switch (Constraint[0]) { -+ default : break; -+ case 'f': -+ return C_RegisterClass; -+ case 'l': -+ case 'G': -+ return C_Other; -+ case 'R': -+ return C_Memory; -+ } -+ } -+ -+ if (Constraint == "ZC" || Constraint == "ZB") -+ return C_Memory; -+ -+ return TargetLowering::getConstraintType(Constraint); -+} -+ -+/// Examine constraint type and operand type and determine a weight value. -+/// This object must already have been set up with the operand type -+/// and the current alternative constraint selected. -+TargetLowering::ConstraintWeight -+LoongArchTargetLowering::getSingleConstraintMatchWeight( -+ AsmOperandInfo &info, const char *constraint) const { -+ ConstraintWeight weight = CW_Invalid; -+ Value *CallOperandVal = info.CallOperandVal; -+ // If we don't have a value, we can't do a match, -+ // but allow it at the lowest weight. -+ if (!CallOperandVal) -+ return CW_Default; -+ Type *type = CallOperandVal->getType(); -+ // Look at the constraint type. -+ switch (*constraint) { - default: -- llvm_unreachable("Unexpected instr type to insert"); -- case LoongArch::DIV_W: -- case LoongArch::DIV_WU: -- case LoongArch::MOD_W: -- case LoongArch::MOD_WU: -- case LoongArch::DIV_D: -- case LoongArch::DIV_DU: -- case LoongArch::MOD_D: -- case LoongArch::MOD_DU: -- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo()); -+ weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); -+ break; -+ case 'f': // FPU -+ if (Subtarget.hasLSX() && type->isVectorTy() && -+ type->getPrimitiveSizeInBits() == 128) -+ weight = CW_Register; -+ else if (Subtarget.hasLASX() && type->isVectorTy() && -+ type->getPrimitiveSizeInBits() == 256) -+ weight = CW_Register; -+ else if (type->isFloatTy()) -+ weight = CW_Register; -+ break; -+ case 'l': // signed 16 bit immediate -+ case 'I': // signed 12 bit immediate -+ case 'J': // integer zero -+ case 'G': // floating-point zero -+ case 'K': // unsigned 12 bit immediate -+ if (isa(CallOperandVal)) -+ weight = CW_Constant; -+ break; -+ case 'm': -+ case 'R': -+ weight = CW_Memory; - break; - } -+ return weight; - } - --const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { -- switch ((LoongArchISD::NodeType)Opcode) { -- case LoongArchISD::FIRST_NUMBER: -- break; -- --#define NODE_NAME_CASE(node) \ -- case LoongArchISD::node: \ -- return "LoongArchISD::" #node; -- -- // TODO: Add more target-dependent nodes later. -- NODE_NAME_CASE(CALL) -- NODE_NAME_CASE(RET) -- NODE_NAME_CASE(SLL_W) -- NODE_NAME_CASE(SRA_W) -- NODE_NAME_CASE(SRL_W) -- NODE_NAME_CASE(BSTRINS) -- NODE_NAME_CASE(BSTRPICK) -- NODE_NAME_CASE(MOVGR2FR_W_LA64) -- NODE_NAME_CASE(MOVFR2GR_S_LA64) -- NODE_NAME_CASE(FTINT) -- } --#undef NODE_NAME_CASE -+/// This is a helper function to parse a physical register string and split it -+/// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag -+/// that is returned indicates whether parsing was successful. The second flag -+/// is true if the numeric part exists. -+static std::pair parsePhysicalReg(StringRef C, StringRef &Prefix, -+ unsigned long long &Reg) { -+ if (C.empty() || C.front() != '{' || C.back() != '}') -+ return std::make_pair(false, false); -+ -+ // Search for the first numeric character. -+ StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; -+ I = std::find_if(B, E, isdigit); -+ -+ Prefix = StringRef(B, I - B); -+ -+ // The second flag is set to false if no numeric characters were found. -+ if (I == E) -+ return std::make_pair(true, false); -+ -+ // Parse the numeric characters. -+ return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg), -+ true); -+} -+ -+EVT LoongArchTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, -+ ISD::NodeType) const { -+ bool Cond = !Subtarget.isABI_LP32() && VT.getSizeInBits() == 32; -+ EVT MinVT = getRegisterType(Context, Cond ? MVT::i64 : MVT::i32); -+ return VT.bitsLT(MinVT) ? MinVT : VT; -+} -+ -+static const TargetRegisterClass *getRegisterClassForVT(MVT VT, bool Is64Bit) { -+ // Newer llvm versions (>= 12) do not require simple VTs for constraints and -+ // they use MVT::Other for constraints with complex VTs. For more details, -+ // please see https://reviews.llvm.org/D91710. -+ if (VT == MVT::Other || VT.getSizeInBits() <= 32) -+ return &LoongArch::GPR32RegClass; -+ if (VT.getSizeInBits() <= 64) -+ return Is64Bit ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; - return nullptr; - } - --//===----------------------------------------------------------------------===// --// Calling Convention Implementation --//===----------------------------------------------------------------------===// --// FIXME: Now, we only support CallingConv::C with fixed arguments which are --// passed with integer or floating-point registers. --const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, -- LoongArch::R7, LoongArch::R8, LoongArch::R9, -- LoongArch::R10, LoongArch::R11}; --const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2, -- LoongArch::F3, LoongArch::F4, LoongArch::F5, -- LoongArch::F6, LoongArch::F7}; --const MCPhysReg ArgFPR64s[] = { -- LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, -- LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64}; -- --// Implements the LoongArch calling convention. Returns true upon failure. --static bool CC_LoongArch(unsigned ValNo, MVT ValVT, -- CCValAssign::LocInfo LocInfo, CCState &State) { -- // Allocate to a register if possible. -- Register Reg; -- -- if (ValVT == MVT::f32) -- Reg = State.AllocateReg(ArgFPR32s); -- else if (ValVT == MVT::f64) -- Reg = State.AllocateReg(ArgFPR64s); -- else -- Reg = State.AllocateReg(ArgGPRs); -- if (Reg) { -- State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); -- return false; -+std::pair LoongArchTargetLowering:: -+parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { -+ const TargetRegisterInfo *TRI = -+ Subtarget.getRegisterInfo(); -+ const TargetRegisterClass *RC; -+ StringRef Prefix; -+ unsigned long long Reg; -+ -+ std::pair R = parsePhysicalReg(C, Prefix, Reg); -+ -+ if (!R.first) -+ return std::make_pair(0U, nullptr); -+ -+ if (!R.second) -+ return std::make_pair(0U, nullptr); -+ -+ if (Prefix == "$f") { // Parse $f0-$f31. -+ // If the size of FP registers is 64-bit or Reg is an even number, select -+ // the 64-bit register class. Otherwise, select the 32-bit register class. -+ if (VT == MVT::Other) -+ VT = (Subtarget.isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32; -+ -+ RC = getRegClassFor(VT); -+ } -+ else if (Prefix == "$vr") { // Parse $vr0-$vr31. -+ RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); -+ } -+ else if (Prefix == "$xr") { // Parse $xr0-$xr31. -+ RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); -+ } -+ else if (Prefix == "$fcc") // Parse $fcc0-$fcc7. -+ RC = TRI->getRegClass(LoongArch::FCFRRegClassID); -+ else { // Parse $r0-$r31. -+ assert(Prefix == "$r"); -+ if ((RC = getRegisterClassForVT(VT, Subtarget.is64Bit())) == nullptr) { -+ // This will generate an error message. -+ return std::make_pair(0U, nullptr); -+ } - } - -- // TODO: Handle arguments passed without register. -- return true; -+ assert(Reg < RC->getNumRegs()); -+ -+ if (RC == &LoongArch::GPR64RegClass || RC == &LoongArch::GPR32RegClass) { -+ // Sync with the GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td -+ // that just like LoongArchAsmParser.cpp -+ switch (Reg) { -+ case 0: return std::make_pair(*(RC->begin() + 0), RC); // r0 -+ case 1: return std::make_pair(*(RC->begin() + 27), RC); // r1 -+ case 2: return std::make_pair(*(RC->begin() + 28), RC); // r2 -+ case 3: return std::make_pair(*(RC->begin() + 29), RC); // r3 -+ case 4: return std::make_pair(*(RC->begin() + 1), RC); // r4 -+ case 5: return std::make_pair(*(RC->begin() + 2), RC); // r5 -+ case 6: return std::make_pair(*(RC->begin() + 3), RC); // r6 -+ case 7: return std::make_pair(*(RC->begin() + 4), RC); // r7 -+ case 8: return std::make_pair(*(RC->begin() + 5), RC); // r8 -+ case 9: return std::make_pair(*(RC->begin() + 6), RC); // r9 -+ case 10: return std::make_pair(*(RC->begin() + 7), RC); // r10 -+ case 11: return std::make_pair(*(RC->begin() + 8), RC); // r11 -+ case 12: return std::make_pair(*(RC->begin() + 9), RC); // r12 -+ case 13: return std::make_pair(*(RC->begin() + 10), RC); // r13 -+ case 14: return std::make_pair(*(RC->begin() + 11), RC); // r14 -+ case 15: return std::make_pair(*(RC->begin() + 12), RC); // r15 -+ case 16: return std::make_pair(*(RC->begin() + 13), RC); // r16 -+ case 17: return std::make_pair(*(RC->begin() + 14), RC); // r17 -+ case 18: return std::make_pair(*(RC->begin() + 15), RC); // r18 -+ case 19: return std::make_pair(*(RC->begin() + 16), RC); // r19 -+ case 20: return std::make_pair(*(RC->begin() + 17), RC); // r20 -+ case 21: return std::make_pair(*(RC->begin() + 30), RC); // r21 -+ case 22: return std::make_pair(*(RC->begin() + 31), RC); // r22 -+ case 23: return std::make_pair(*(RC->begin() + 18), RC); // r23 -+ case 24: return std::make_pair(*(RC->begin() + 19), RC); // r24 -+ case 25: return std::make_pair(*(RC->begin() + 20), RC); // r25 -+ case 26: return std::make_pair(*(RC->begin() + 21), RC); // r26 -+ case 27: return std::make_pair(*(RC->begin() + 22), RC); // r27 -+ case 28: return std::make_pair(*(RC->begin() + 23), RC); // r28 -+ case 29: return std::make_pair(*(RC->begin() + 24), RC); // r29 -+ case 30: return std::make_pair(*(RC->begin() + 25), RC); // r30 -+ case 31: return std::make_pair(*(RC->begin() + 26), RC); // r31 -+ } -+ } -+ return std::make_pair(*(RC->begin() + Reg), RC); - } - --void LoongArchTargetLowering::analyzeInputArgs( -- CCState &CCInfo, const SmallVectorImpl &Ins, -- LoongArchCCAssignFn Fn) const { -- for (unsigned i = 0, e = Ins.size(); i != e; ++i) { -- MVT ArgVT = Ins[i].VT; -+/// Given a register class constraint, like 'r', if this corresponds directly -+/// to an LLVM register class, return a register of 0 and the register class -+/// pointer. -+std::pair -+LoongArchTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, -+ StringRef Constraint, -+ MVT VT) const { -+ if (Constraint.size() == 1) { -+ switch (Constraint[0]) { -+ case 'r': -+ return std::make_pair(0U, getRegisterClassForVT(VT, Subtarget.is64Bit())); -+ case 'f': // FPU or LSX register -+ if (VT == MVT::v16i8) -+ return std::make_pair(0U, &LoongArch::LSX128BRegClass); -+ else if (VT == MVT::v8i16) -+ return std::make_pair(0U, &LoongArch::LSX128HRegClass); -+ else if (VT == MVT::v4i32 || VT == MVT::v4f32) -+ return std::make_pair(0U, &LoongArch::LSX128WRegClass); -+ else if (VT == MVT::v2i64 || VT == MVT::v2f64) -+ return std::make_pair(0U, &LoongArch::LSX128DRegClass); -+ else if (VT == MVT::v32i8) -+ return std::make_pair(0U, &LoongArch::LASX256BRegClass); -+ else if (VT == MVT::v16i16) -+ return std::make_pair(0U, &LoongArch::LASX256HRegClass); -+ else if (VT == MVT::v8i32 || VT == MVT::v8f32) -+ return std::make_pair(0U, &LoongArch::LASX256WRegClass); -+ else if (VT == MVT::v4i64 || VT == MVT::v4f64) -+ return std::make_pair(0U, &LoongArch::LASX256DRegClass); -+ else if (VT == MVT::f32) -+ return std::make_pair(0U, &LoongArch::FGR32RegClass); -+ else if (VT == MVT::f64) -+ return std::make_pair(0U, &LoongArch::FGR64RegClass); -+ break; -+ } -+ } -+ -+ std::pair R; -+ R = parseRegForInlineAsmConstraint(Constraint, VT); -+ -+ if (R.second) -+ return R; -+ -+ return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); -+} - -- if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { -- LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " -- << EVT(ArgVT).getEVTString() << '\n'); -- llvm_unreachable(""); -+/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops -+/// vector. If it is invalid, don't add anything to Ops. -+void LoongArchTargetLowering::LowerAsmOperandForConstraint(SDValue Op, -+ std::string &Constraint, -+ std::vector&Ops, -+ SelectionDAG &DAG) const { -+ SDLoc DL(Op); -+ SDValue Result; -+ -+ // Only support length 1 constraints for now. -+ if (Constraint.length() > 1) return; -+ -+ char ConstraintLetter = Constraint[0]; -+ switch (ConstraintLetter) { -+ default: break; // This will fall through to the generic implementation -+ case 'l': // Signed 16 bit constant -+ // If this fails, the parent routine will give an error -+ if (ConstantSDNode *C = dyn_cast(Op)) { -+ EVT Type = Op.getValueType(); -+ int64_t Val = C->getSExtValue(); -+ if (isInt<16>(Val)) { -+ Result = DAG.getTargetConstant(Val, DL, Type); -+ break; -+ } -+ } -+ return; -+ case 'I': // Signed 12 bit constant -+ // If this fails, the parent routine will give an error -+ if (ConstantSDNode *C = dyn_cast(Op)) { -+ EVT Type = Op.getValueType(); -+ int64_t Val = C->getSExtValue(); -+ if (isInt<12>(Val)) { -+ Result = DAG.getTargetConstant(Val, DL, Type); -+ break; -+ } -+ } -+ return; -+ case 'J': // integer zero -+ if (ConstantSDNode *C = dyn_cast(Op)) { -+ EVT Type = Op.getValueType(); -+ int64_t Val = C->getZExtValue(); -+ if (Val == 0) { -+ Result = DAG.getTargetConstant(0, DL, Type); -+ break; -+ } - } -+ return; -+ case 'G': // floating-point zero -+ if (ConstantFPSDNode *C = dyn_cast(Op)) { -+ if (C->isZero()) { -+ EVT Type = Op.getValueType(); -+ Result = DAG.getTargetConstantFP(0, DL, Type); -+ break; -+ } -+ } -+ return; -+ case 'K': // unsigned 12 bit immediate -+ if (ConstantSDNode *C = dyn_cast(Op)) { -+ EVT Type = Op.getValueType(); -+ uint64_t Val = (uint64_t)C->getZExtValue(); -+ if (isUInt<12>(Val)) { -+ Result = DAG.getTargetConstant(Val, DL, Type); -+ break; -+ } -+ } -+ return; -+ } -+ -+ if (Result.getNode()) { -+ Ops.push_back(Result); -+ return; -+ } -+ -+ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); -+} -+ -+bool LoongArchTargetLowering::isLegalAddressingMode(const DataLayout &DL, -+ const AddrMode &AM, Type *Ty, -+ unsigned AS, Instruction *I) const { -+ // No global is ever allowed as a base. -+ if (AM.BaseGV) -+ return false; -+ -+ switch (AM.Scale) { -+ case 0: // "r+i" or just "i", depending on HasBaseReg. -+ break; -+ case 1: -+ if (!AM.HasBaseReg) // allow "r+i". -+ break; -+ return false; // disallow "r+r" or "r+r+i". -+ default: -+ return false; - } -+ -+ return true; - } - --void LoongArchTargetLowering::analyzeOutputArgs( -- CCState &CCInfo, const SmallVectorImpl &Outs, -- LoongArchCCAssignFn Fn) const { -- for (unsigned i = 0, e = Outs.size(); i != e; ++i) { -- MVT ArgVT = Outs[i].VT; -+bool -+LoongArchTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { -+ // The LoongArch target isn't yet aware of offsets. -+ return false; -+} - -- if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { -- LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " -- << EVT(ArgVT).getEVTString() << "\n"); -- llvm_unreachable(""); -+EVT LoongArchTargetLowering::getOptimalMemOpType( -+ const MemOp &Op, const AttributeList &FuncAttributes) const { -+ if (!FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) { -+ if (Op.size() >= 16) { -+ if (Op.size() >= 32 && Subtarget.hasLASX()) { -+ return MVT::v32i8; -+ } -+ if (Subtarget.hasLSX()) -+ return MVT::v16i8; - } - } -+ -+ if (Subtarget.is64Bit()) -+ return MVT::i64; -+ -+ return MVT::i32; - } - --static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, -- const CCValAssign &VA, const SDLoc &DL, -- const LoongArchTargetLowering &TLI) { -- MachineFunction &MF = DAG.getMachineFunction(); -- MachineRegisterInfo &RegInfo = MF.getRegInfo(); -- EVT LocVT = VA.getLocVT(); -- const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); -- Register VReg = RegInfo.createVirtualRegister(RC); -- RegInfo.addLiveIn(VA.getLocReg(), VReg); -+/// isFPImmLegal - Returns true if the target can instruction select the -+/// specified FP immediate natively. If false, the legalizer will -+/// materialize the FP immediate as a load from a constant pool. -+bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, -+ bool ForCodeSize) const { -+ if (VT != MVT::f32 && VT != MVT::f64) -+ return false; -+ if (Imm.isNegZero()) -+ return false; -+ return (Imm.isZero() || Imm.isExactlyValue(+1.0)); -+} - -- return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); -+bool LoongArchTargetLowering::useSoftFloat() const { -+ return Subtarget.useSoftFloat(); - } - --// Transform physical registers into virtual registers. --SDValue LoongArchTargetLowering::LowerFormalArguments( -- SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, -- const SmallVectorImpl &Ins, const SDLoc &DL, -- SelectionDAG &DAG, SmallVectorImpl &InVals) const { -+// Return whether the an instruction can potentially be optimized to a tail -+// call. This will cause the optimizers to attempt to move, or duplicate, -+// return instructions to help enable tail call optimizations for this -+// instruction. -+bool LoongArchTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { -+ return CI->isTailCall(); -+} - -+void LoongArchTargetLowering::copyByValRegs( -+ SDValue Chain, const SDLoc &DL, std::vector &OutChains, -+ SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, -+ SmallVectorImpl &InVals, const Argument *FuncArg, -+ unsigned FirstReg, unsigned LastReg, const CCValAssign &VA, -+ LoongArchCCState &State) const { - MachineFunction &MF = DAG.getMachineFunction(); -- -- switch (CallConv) { -- default: -- llvm_unreachable("Unsupported calling convention"); -- case CallingConv::C: -- break; -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); -+ unsigned NumRegs = LastReg - FirstReg; -+ unsigned RegAreaSize = NumRegs * GPRSizeInBytes; -+ unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); -+ int FrameObjOffset; -+ ArrayRef ByValArgRegs = ABI.GetByValArgRegs(); -+ -+ if (RegAreaSize) -+ FrameObjOffset = -(int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes); -+ else -+ FrameObjOffset = VA.getLocMemOffset(); -+ -+ // Create frame object. -+ EVT PtrTy = getPointerTy(DAG.getDataLayout()); -+ // Make the fixed object stored to mutable so that the load instructions -+ // referencing it have their memory dependencies added. -+ // Set the frame object as isAliased which clears the underlying objects -+ // vector in ScheduleDAGInstrs::buildSchedGraph() resulting in addition of all -+ // stores as dependencies for loads referencing this fixed object. -+ int FI = MFI.CreateFixedObject(FrameObjSize, FrameObjOffset, false, true); -+ SDValue FIN = DAG.getFrameIndex(FI, PtrTy); -+ InVals.push_back(FIN); -+ -+ if (!NumRegs) -+ return; -+ -+ // Copy arg registers. -+ MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); -+ const TargetRegisterClass *RC = getRegClassFor(RegTy); -+ -+ for (unsigned I = 0; I < NumRegs; ++I) { -+ unsigned ArgReg = ByValArgRegs[FirstReg + I]; -+ unsigned VReg = addLiveIn(MF, ArgReg, RC); -+ unsigned Offset = I * GPRSizeInBytes; -+ SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, -+ DAG.getConstant(Offset, DL, PtrTy)); -+ SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), -+ StorePtr, MachinePointerInfo(FuncArg, Offset)); -+ OutChains.push_back(Store); - } -+} - -- // Assign locations to all of the incoming arguments. -- SmallVector ArgLocs; -- CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); -+// Copy byVal arg to registers and stack. -+void LoongArchTargetLowering::passByValArg( -+ SDValue Chain, const SDLoc &DL, -+ std::deque> &RegsToPass, -+ SmallVectorImpl &MemOpChains, SDValue StackPtr, -+ MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, -+ unsigned LastReg, const ISD::ArgFlagsTy &Flags, -+ const CCValAssign &VA) const { -+ unsigned ByValSizeInBytes = Flags.getByValSize(); -+ unsigned OffsetInBytes = 0; // From beginning of struct -+ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); -+ Align Alignment = -+ std::min(Flags.getNonZeroByValAlign(), Align(RegSizeInBytes)); -+ EVT PtrTy = getPointerTy(DAG.getDataLayout()), -+ RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); -+ unsigned NumRegs = LastReg - FirstReg; -+ -+ if (NumRegs) { -+ ArrayRef ArgRegs = ABI.GetByValArgRegs(); -+ bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); -+ unsigned I = 0; -+ -+ // Copy words to registers. -+ for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { -+ SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, -+ DAG.getConstant(OffsetInBytes, DL, PtrTy)); -+ SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, -+ MachinePointerInfo(), Alignment); -+ MemOpChains.push_back(LoadVal.getValue(1)); -+ unsigned ArgReg = ArgRegs[FirstReg + I]; -+ RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); -+ } - -- analyzeInputArgs(CCInfo, Ins, CC_LoongArch); -+ // Return if the struct has been fully copied. -+ if (ByValSizeInBytes == OffsetInBytes) -+ return; - -- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) -- InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); -+ // Copy the remainder of the byval argument with sub-word loads and shifts. -+ if (LeftoverBytes) { -+ SDValue Val; - -- return Chain; --} -+ for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0; -+ OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) { -+ unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes; - --// Lower a call to a callseq_start + CALL + callseq_end chain, and add input --// and output parameter nodes. --SDValue --LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI, -- SmallVectorImpl &InVals) const { -- SelectionDAG &DAG = CLI.DAG; -- SDLoc &DL = CLI.DL; -- SmallVectorImpl &Outs = CLI.Outs; -- SmallVectorImpl &OutVals = CLI.OutVals; -- SmallVectorImpl &Ins = CLI.Ins; -- SDValue Chain = CLI.Chain; -- SDValue Callee = CLI.Callee; -- CallingConv::ID CallConv = CLI.CallConv; -- bool IsVarArg = CLI.IsVarArg; -- EVT PtrVT = getPointerTy(DAG.getDataLayout()); -- CLI.IsTailCall = false; -+ if (RemainingSizeInBytes < LoadSizeInBytes) -+ continue; - -- if (IsVarArg) -- report_fatal_error("LowerCall with varargs not implemented"); -+ // Load subword. -+ SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, -+ DAG.getConstant(OffsetInBytes, DL, -+ PtrTy)); -+ SDValue LoadVal = DAG.getExtLoad( -+ ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), -+ MVT::getIntegerVT(LoadSizeInBytes * 8), Alignment); -+ MemOpChains.push_back(LoadVal.getValue(1)); - -- MachineFunction &MF = DAG.getMachineFunction(); -+ // Shift the loaded value. -+ unsigned Shamt; - -- // Analyze the operands of the call, assigning locations to each operand. -- SmallVector ArgLocs; -- CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); -+ Shamt = TotalBytesLoaded * 8; - -- analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch); -+ SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, -+ DAG.getConstant(Shamt, DL, MVT::i32)); - -- // Get a count of how many bytes are to be pushed on the stack. -- unsigned NumBytes = ArgCCInfo.getNextStackOffset(); -+ if (Val.getNode()) -+ Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); -+ else -+ Val = Shift; - -- for (auto &Arg : Outs) { -- if (!Arg.Flags.isByVal()) -- continue; -- report_fatal_error("Passing arguments byval not implemented"); -+ OffsetInBytes += LoadSizeInBytes; -+ TotalBytesLoaded += LoadSizeInBytes; -+ Alignment = std::min(Alignment, Align(LoadSizeInBytes)); -+ } -+ -+ unsigned ArgReg = ArgRegs[FirstReg + I]; -+ RegsToPass.push_back(std::make_pair(ArgReg, Val)); -+ return; -+ } - } - -- Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); -+ // Copy remainder of byval arg to it with memcpy. -+ unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; -+ SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, -+ DAG.getConstant(OffsetInBytes, DL, PtrTy)); -+ SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, -+ DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); -+ Chain = DAG.getMemcpy( -+ Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, DL, PtrTy), -+ Align(Alignment), /*isVolatile=*/false, /*AlwaysInline=*/false, -+ /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); -+ MemOpChains.push_back(Chain); -+} - -- // Copy argument values to their designated locations. -- SmallVector> RegsToPass; -- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { -- CCValAssign &VA = ArgLocs[i]; -- SDValue ArgValue = OutVals[i]; -+void LoongArchTargetLowering::writeVarArgRegs(std::vector &OutChains, -+ SDValue Chain, const SDLoc &DL, -+ SelectionDAG &DAG, -+ CCState &State) const { -+ ArrayRef ArgRegs = ABI.GetVarArgRegs(); -+ unsigned Idx = State.getFirstUnallocated(ArgRegs); -+ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); -+ MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); -+ const TargetRegisterClass *RC = getRegClassFor(RegTy); -+ MachineFunction &MF = DAG.getMachineFunction(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); - -- // Promote the value if needed. -- // For now, only handle fully promoted arguments. -- if (VA.getLocInfo() != CCValAssign::Full) -- report_fatal_error("Unknown loc info"); -+ // Offset of the first variable argument from stack pointer. -+ int VaArgOffset, VarArgsSaveSize; - -- if (VA.isRegLoc()) { -- // Queue up the argument copies and emit them at the end. -- RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); -- } else { -- report_fatal_error("Passing arguments via the stack not implemented"); -- } -+ if (ArgRegs.size() == Idx) { -+ VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes); -+ VarArgsSaveSize = 0; -+ } else { -+ VarArgsSaveSize = (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); -+ VaArgOffset = -VarArgsSaveSize; - } - -- SDValue Glue; -+ // Record the frame index of the first variable argument -+ // which is a value necessary to VASTART. -+ int FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); -+ LoongArchFI->setVarArgsFrameIndex(FI); -+ -+ // If saving an odd number of registers then create an extra stack slot to -+ // ensure that the frame pointer is 2*GRLEN-aligned, which in turn ensures -+ // offsets to even-numbered registered remain 2*GRLEN-aligned. -+ if (Idx % 2) { -+ MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset - (int)RegSizeInBytes, -+ true); -+ VarArgsSaveSize += RegSizeInBytes; -+ } - -- // Build a sequence of copy-to-reg nodes, chained and glued together. -- for (auto &Reg : RegsToPass) { -- Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); -- Glue = Chain.getValue(1); -+ // Copy the integer registers that have not been used for argument passing -+ // to the argument register save area. For LP32, the save area is allocated -+ // in the caller's stack frame, while for LPX32/LP64, it is allocated in the -+ // callee's stack frame. -+ for (unsigned I = Idx; I < ArgRegs.size(); -+ ++I, VaArgOffset += RegSizeInBytes) { -+ unsigned Reg = addLiveIn(MF, ArgRegs[I], RC); -+ SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); -+ FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); -+ SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); -+ SDValue Store = -+ DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo()); -+ cast(Store.getNode())->getMemOperand()->setValue( -+ (Value *)nullptr); -+ OutChains.push_back(Store); - } -+ LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize); -+} - -- // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a -- // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't -- // split it and then direct call can be matched by PseudoCALL. -- // FIXME: Add target flags for relocation. -- if (GlobalAddressSDNode *S = dyn_cast(Callee)) -- Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT); -- else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) -- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT); -+void LoongArchTargetLowering::HandleByVal(CCState *State, unsigned &Size, -+ Align Alignment) const { -+ const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); -+ -+ assert(Size && "Byval argument's size shouldn't be 0."); -+ -+ Alignment = std::min(Alignment, TFL->getStackAlign()); -+ -+ unsigned FirstReg = 0; -+ unsigned NumRegs = 0; -+ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); -+ ArrayRef IntArgRegs = ABI.GetByValArgRegs(); -+ // FIXME: The LP32 case actually describes no shadow registers. -+ const MCPhysReg *ShadowRegs = -+ ABI.IsLP32() ? IntArgRegs.data() : LoongArch64DPRegs; -+ -+ // We used to check the size as well but we can't do that anymore since -+ // CCState::HandleByVal() rounds up the size after calling this function. -+ assert(Alignment >= Align(RegSizeInBytes) && -+ "Byval argument's alignment should be a multiple of RegSizeInBytes."); -+ -+ FirstReg = State->getFirstUnallocated(IntArgRegs); -+ -+ // If Alignment > RegSizeInBytes, the first arg register must be even. -+ // FIXME: This condition happens to do the right thing but it's not the -+ // right way to test it. We want to check that the stack frame offset -+ // of the register is aligned. -+ if ((Alignment > RegSizeInBytes) && (FirstReg % 2)) { -+ State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]); -+ ++FirstReg; -+ // assert(true && "debug#######################################"); -+ } - -- // The first call operand is the chain and the second is the target address. -- SmallVector Ops; -- Ops.push_back(Chain); -- Ops.push_back(Callee); -+ // Mark the registers allocated. -+ // Size = alignTo(Size, RegSizeInBytes); -+ // for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); -+ // Size -= RegSizeInBytes, ++I, ++NumRegs) -+ // State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); - -- // Add argument registers to the end of the list so that they are -- // known live into the call. -- for (auto &Reg : RegsToPass) -- Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); -+ State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); -+} - -- // Add a register mask operand representing the call-preserved registers. -- const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); -- const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); -- assert(Mask && "Missing call preserved mask for calling convention"); -- Ops.push_back(DAG.getRegisterMask(Mask)); -+MachineBasicBlock *LoongArchTargetLowering::emitPseudoSELECT(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ bool isFPCmp, -+ unsigned Opc) const { -+ const TargetInstrInfo *TII = -+ Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ // To "insert" a SELECT instruction, we actually have to insert the -+ // diamond control-flow pattern. The incoming instruction knows the -+ // destination vreg to set, the condition code register to branch on, the -+ // true/false values to select between, and a branch opcode to use. -+ const BasicBlock *LLVM_BB = BB->getBasicBlock(); -+ MachineFunction::iterator It = ++BB->getIterator(); -+ -+ // thisMBB: -+ // ... -+ // TrueVal = ... -+ // setcc r1, r2, r3 -+ // bNE r1, r0, copy1MBB -+ // fallthrough --> copy0MBB -+ MachineBasicBlock *thisMBB = BB; -+ MachineFunction *F = BB->getParent(); -+ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); -+ F->insert(It, copy0MBB); -+ F->insert(It, sinkMBB); -+ -+ // Transfer the remainder of BB and its successor edges to sinkMBB. -+ sinkMBB->splice(sinkMBB->begin(), BB, -+ std::next(MachineBasicBlock::iterator(MI)), BB->end()); -+ sinkMBB->transferSuccessorsAndUpdatePHIs(BB); -+ -+ // Next, add the true and fallthrough blocks as its successors. -+ BB->addSuccessor(copy0MBB); -+ BB->addSuccessor(sinkMBB); -+ -+ if (isFPCmp) { -+ // bc1[tf] cc, sinkMBB -+ BuildMI(BB, DL, TII->get(Opc)) -+ .addReg(MI.getOperand(1).getReg()) -+ .addMBB(sinkMBB); -+ } else { -+ BuildMI(BB, DL, TII->get(Opc)) -+ .addReg(MI.getOperand(1).getReg()) -+ .addReg(LoongArch::ZERO) -+ .addMBB(sinkMBB); -+ } - -- // Glue the call to the argument copies, if any. -- if (Glue.getNode()) -- Ops.push_back(Glue); -+ // copy0MBB: -+ // %FalseValue = ... -+ // # fallthrough to sinkMBB -+ BB = copy0MBB; - -- // Emit the call. -- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); -+ // Update machine-CFG edges -+ BB->addSuccessor(sinkMBB); - -- Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops); -- DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); -- Glue = Chain.getValue(1); -+ // sinkMBB: -+ // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] -+ // ... -+ BB = sinkMBB; - -- // Mark the end of the call, which is glued to the call itself. -- Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), -- DAG.getConstant(0, DL, PtrVT, true), Glue, DL); -- Glue = Chain.getValue(1); -+ BuildMI(*BB, BB->begin(), DL, TII->get(LoongArch::PHI), MI.getOperand(0).getReg()) -+ .addReg(MI.getOperand(2).getReg()) -+ .addMBB(thisMBB) -+ .addReg(MI.getOperand(3).getReg()) -+ .addMBB(copy0MBB); - -- // Assign locations to each value returned by this call. -- SmallVector RVLocs; -- CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); -- analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch); -+ MI.eraseFromParent(); // The pseudo instruction is gone now. - -- // Copy all of the result registers out of their specified physreg. -- for (auto &VA : RVLocs) { -- // Copy the value out. -- SDValue RetValue = -- DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); -- Chain = RetValue.getValue(1); -- Glue = RetValue.getValue(2); -+ return BB; -+} - -- InVals.push_back(Chain.getValue(0)); -+MachineBasicBlock *LoongArchTargetLowering::emitLSXCBranchPseudo( -+ MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const { -+ -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ const TargetRegisterClass *RC = &LoongArch::GPR32RegClass; -+ DebugLoc DL = MI.getDebugLoc(); -+ const BasicBlock *LLVM_BB = BB->getBasicBlock(); -+ MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); -+ MachineFunction *F = BB->getParent(); -+ MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); -+ F->insert(It, FBB); -+ F->insert(It, TBB); -+ F->insert(It, Sink); -+ -+ // Transfer the remainder of BB and its successor edges to Sink. -+ Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), -+ BB->end()); -+ Sink->transferSuccessorsAndUpdatePHIs(BB); -+ -+ // Add successors. -+ BB->addSuccessor(FBB); -+ BB->addSuccessor(TBB); -+ FBB->addSuccessor(Sink); -+ TBB->addSuccessor(Sink); -+ // Insert the real bnz.b instruction to $BB. -+ BuildMI(BB, DL, TII->get(BranchOp)) -+ .addReg(LoongArch::FCC0) -+ .addReg(MI.getOperand(1).getReg()); -+ -+ BuildMI(BB, DL, TII->get(LoongArch::BCNEZ)) -+ .addReg(LoongArch::FCC0) -+ .addMBB(TBB); -+ -+ // Fill $FBB. -+ unsigned RD1 = RegInfo.createVirtualRegister(RC); -+ BuildMI(*FBB, FBB->end(), DL, TII->get(LoongArch::ADDI_W), RD1) -+ .addReg(LoongArch::ZERO) -+ .addImm(0); -+ BuildMI(*FBB, FBB->end(), DL, TII->get(LoongArch::B32)).addMBB(Sink); -+ -+ // Fill $TBB. -+ unsigned RD2 = RegInfo.createVirtualRegister(RC); -+ BuildMI(*TBB, TBB->end(), DL, TII->get(LoongArch::ADDI_W), RD2) -+ .addReg(LoongArch::ZERO) -+ .addImm(1); -+ -+ // Insert phi function to $Sink. -+ BuildMI(*Sink, Sink->begin(), DL, TII->get(LoongArch::PHI), -+ MI.getOperand(0).getReg()) -+ .addReg(RD1) -+ .addMBB(FBB) -+ .addReg(RD2) -+ .addMBB(TBB); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return Sink; -+} -+ -+// Emit the COPY_FW pseudo instruction. -+// -+// copy_fw_pseudo $fd, $vk, n -+// => -+// vreplvei.w $rt, $vk, $n -+// copy $rt, $fd -+// -+// When n is zero, the equivalent operation can be performed with (potentially) -+// zero instructions due to register overlaps. -+MachineBasicBlock * -+LoongArchTargetLowering::emitCOPY_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Fd = MI.getOperand(0).getReg(); -+ unsigned Vk = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ -+ if (Lane == 0) { -+ unsigned Vj = Vk; -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Vj, 0, LoongArch::sub_lo); -+ } else { -+ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_W), Vj) -+ .addReg(Vk) -+ .addImm(Lane); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Vj, 0, LoongArch::sub_lo); - } - -- return Chain; -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the COPY_FD pseudo instruction. -+// -+// copy_fd_pseudo $fd, $vj, n -+// => -+// vreplvei.d $vd, $vj, $n -+// copy $fd, $vd:sub_64 -+// -+// When n is zero, the equivalent operation can be performed with (potentially) -+// zero instructions due to register overlaps. -+MachineBasicBlock * -+LoongArchTargetLowering::emitCOPY_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ unsigned Fd = MI.getOperand(0).getReg(); -+ unsigned Vk = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ if (Lane == 0) -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Vk, 0, LoongArch::sub_64); -+ else { -+ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); -+ assert(Lane == 1); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_D), Vj) -+ .addReg(Vk) -+ .addImm(Lane); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Vj, 0, LoongArch::sub_64); -+ } -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; - } - --bool LoongArchTargetLowering::CanLowerReturn( -- CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, -- const SmallVectorImpl &Outs, LLVMContext &Context) const { -- // Any return value split in to more than two values can't be returned -- // directly. -- return Outs.size() <= 2; -+MachineBasicBlock * -+LoongArchTargetLowering::emitXCOPY_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Fd = MI.getOperand(0).getReg(); -+ unsigned Xk = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned Xj = Xk; -+ -+ if (Lane == 0) { -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Xj, 0, LoongArch::sub_lo); -+ } else { -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Rj) -+ .addReg(Xk) -+ .addImm(Lane); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd).addReg(Rj); -+ } -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; - } - --SDValue LoongArchTargetLowering::LowerReturn( -- SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, -- const SmallVectorImpl &Outs, -- const SmallVectorImpl &OutVals, const SDLoc &DL, -- SelectionDAG &DAG) const { -- // Stores the assignment of the return value to a location. -- SmallVector RVLocs; -+MachineBasicBlock * -+LoongArchTargetLowering::emitXCOPY_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ unsigned Fd = MI.getOperand(0).getReg(); -+ unsigned Xk = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ DebugLoc DL = MI.getDebugLoc(); -+ -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR64RegClass); -+ if (Lane == 0) { -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) -+ .addReg(Xk, 0, LoongArch::sub_64); -+ } else { -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_DU), Rj) -+ .addReg(Xk) -+ .addImm(Lane); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd).addReg(Rj); -+ } - -- // Info about the registers and stack slot. -- CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, -- *DAG.getContext()); -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} - -- analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); -+MachineBasicBlock *LoongArchTargetLowering::emitCONCAT_VECTORS( -+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Bytes) const { - -- SDValue Glue; -- SmallVector RetOps(1, Chain); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned SubReg1 = MI.getOperand(1).getReg(); -+ unsigned SubReg2 = MI.getOperand(2).getReg(); -+ const TargetRegisterClass *RC = nullptr; - -- // Copy the result values into the output registers. -- for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { -- CCValAssign &VA = RVLocs[i]; -- assert(VA.isRegLoc() && "Can only return in registers!"); -+ switch (Bytes) { -+ default: -+ llvm_unreachable("Unexpected size"); -+ case 1: -+ RC = &LoongArch::LASX256BRegClass; -+ break; -+ case 2: -+ RC = &LoongArch::LASX256HRegClass; -+ break; -+ case 4: -+ RC = &LoongArch::LASX256WRegClass; -+ break; -+ case 8: -+ RC = &LoongArch::LASX256DRegClass; -+ break; -+ } - -- // Handle a 'normal' return. -- Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); -+ unsigned X0 = RegInfo.createVirtualRegister(RC); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), X0) -+ .addImm(0) -+ .addReg(SubReg1) -+ .addImm(LoongArch::sub_128); -+ unsigned X1 = RegInfo.createVirtualRegister(RC); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), X1) -+ .addImm(0) -+ .addReg(SubReg2) -+ .addImm(LoongArch::sub_128); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xd) -+ .addReg(X0) -+ .addReg(X1) -+ .addImm(2); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} - -- // Guarantee that all emitted copies are stuck together. -- Glue = Chain.getValue(1); -- RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); -+// xcopy_fw_gpr_pseudo $fd, $xs, $rk -+// => -+// bb: addi.d $rt1, zero, 4 -+// bge $lane, $rt1 hbb -+// lbb:xvreplve.w $xt1, $xs, $lane -+// copy $rf0, $xt1 -+// b sink -+// hbb: addi.d $rt2, $lane, -4 -+// xvpermi.q $xt2 $xs, 1 -+// xvreplve.w $xt3, $xt2, $rt2 -+// copy $rf1, $xt3 -+// sink:phi -+MachineBasicBlock * -+LoongArchTargetLowering::emitXCOPY_FW_GPR(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xs = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getReg(); -+ -+ const TargetRegisterClass *RC = &LoongArch::GPR64RegClass; -+ const BasicBlock *LLVM_BB = BB->getBasicBlock(); -+ MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); -+ MachineFunction *F = BB->getParent(); -+ MachineBasicBlock *HBB = F->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *LBB = F->CreateMachineBasicBlock(LLVM_BB); -+ MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); -+ F->insert(It, LBB); -+ F->insert(It, HBB); -+ F->insert(It, Sink); -+ -+ Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), -+ BB->end()); -+ Sink->transferSuccessorsAndUpdatePHIs(BB); -+ -+ BB->addSuccessor(LBB); -+ BB->addSuccessor(HBB); -+ HBB->addSuccessor(Sink); -+ LBB->addSuccessor(Sink); -+ -+ unsigned Rt1 = RegInfo.createVirtualRegister(RC); -+ BuildMI(BB, DL, TII->get(LoongArch::ADDI_D), Rt1) -+ .addReg(LoongArch::ZERO_64) -+ .addImm(4); -+ BuildMI(BB, DL, TII->get(LoongArch::BGE)) -+ .addReg(Lane) -+ .addReg(Rt1) -+ .addMBB(HBB); -+ -+ unsigned Xt1 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ unsigned Rf0 = RegInfo.createVirtualRegister(&LoongArch::FGR32RegClass); -+ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::XVREPLVE_W_N), Xt1) -+ .addReg(Xs) -+ .addReg(Lane); -+ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::COPY), Rf0) -+ .addReg(Xt1, 0, LoongArch::sub_lo); -+ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::B)).addMBB(Sink); -+ -+ unsigned Xt2 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ unsigned Xt3 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ unsigned Rt2 = RegInfo.createVirtualRegister(RC); -+ unsigned Rf1 = RegInfo.createVirtualRegister(&LoongArch::FGR32RegClass); -+ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::ADDI_D), Rt2) -+ .addReg(Lane) -+ .addImm(-4); -+ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::XVPERMI_Q), Xt2) -+ .addReg(Xs) -+ .addReg(Xs) -+ .addImm(1); -+ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::XVREPLVE_W_N), Xt3) -+ .addReg(Xt2) -+ .addReg(Rt2); -+ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::COPY), Rf1) -+ .addReg(Xt3, 0, LoongArch::sub_lo); -+ -+ BuildMI(*Sink, Sink->begin(), DL, TII->get(LoongArch::PHI), -+ MI.getOperand(0).getReg()) -+ .addReg(Rf0) -+ .addMBB(LBB) -+ .addReg(Rf1) -+ .addMBB(HBB); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return Sink; -+} -+ -+MachineBasicBlock * -+LoongArchTargetLowering::emitXINSERT_BH(MachineInstr &MI, MachineBasicBlock *BB, -+ unsigned Size) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned Xd_in = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Fs = MI.getOperand(3).getReg(); -+ const TargetRegisterClass *VecRC = nullptr; -+ const TargetRegisterClass *SubVecRC = nullptr; -+ unsigned HalfSize = 0; -+ unsigned InsertOp = 0; -+ -+ if (Size == 1) { -+ VecRC = &LoongArch::LASX256BRegClass; -+ SubVecRC = &LoongArch::LSX128BRegClass; -+ HalfSize = 16; -+ InsertOp = LoongArch::VINSGR2VR_B; -+ } else if (Size == 2) { -+ VecRC = &LoongArch::LASX256HRegClass; -+ SubVecRC = &LoongArch::LSX128HRegClass; -+ HalfSize = 8; -+ InsertOp = LoongArch::VINSGR2VR_H; -+ } else { -+ llvm_unreachable("Unexpected type"); -+ } -+ -+ unsigned Xk = Xd_in; -+ unsigned Imm = Lane; -+ if (Lane >= HalfSize) { -+ Xk = RegInfo.createVirtualRegister(VecRC); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xk) -+ .addReg(Xd_in) -+ .addReg(Xd_in) -+ .addImm(1); -+ Imm = Lane - HalfSize; - } - -- RetOps[0] = Chain; // Update chain. -+ unsigned Xk128 = RegInfo.createVirtualRegister(SubVecRC); -+ unsigned Xd128 = RegInfo.createVirtualRegister(SubVecRC); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Xk128) -+ .addReg(Xk, 0, LoongArch::sub_128); -+ BuildMI(*BB, MI, DL, TII->get(InsertOp), Xd128) -+ .addReg(Xk128) -+ .addReg(Fs) -+ .addImm(Imm); -+ -+ unsigned Xd256 = Xd; -+ if (Lane >= HalfSize) { -+ Xd256 = RegInfo.createVirtualRegister(VecRC); -+ } -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xd256) -+ .addImm(0) -+ .addReg(Xd128) -+ .addImm(LoongArch::sub_128); - -- // Add the glue node if we have it. -- if (Glue.getNode()) -- RetOps.push_back(Glue); -+ if (Lane >= HalfSize) { -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xd) -+ .addReg(Xd_in) -+ .addReg(Xd256) -+ .addImm(2); -+ } - -- return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; - } - --bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, -- bool ForCodeSize) const { -- assert((VT == MVT::f32 || VT == MVT::f64) && "Unexpected VT"); -+MachineBasicBlock * -+LoongArchTargetLowering::emitXINSERT_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned Xd_in = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Fs = MI.getOperand(3).getReg(); -+ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) -+ .addImm(0) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_lo); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Rj) -+ .addReg(Xj) -+ .addImm(0); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVINSGR2VR_W), Xd) -+ .addReg(Xd_in) -+ .addReg(Rj) -+ .addImm(Lane); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the INSERT_FW pseudo instruction. -+// -+// insert_fw_pseudo $vd, $vd_in, $n, $fs -+// => -+// subreg_to_reg $vj:sub_lo, $fs -+// vpickve2gr.w rj, vj, 0 -+// vinsgr2vr.w, vd, rj, lane -+MachineBasicBlock * -+LoongArchTargetLowering::emitINSERT_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Vd = MI.getOperand(0).getReg(); -+ unsigned Vd_in = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Fs = MI.getOperand(3).getReg(); -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); -+ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Vj) -+ .addImm(0) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_lo); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VPICKVE2GR_W), Rj) -+ .addReg(Vj) -+ .addImm(0); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VINSGR2VR_W), Vd) -+ .addReg(Vd_in) -+ .addReg(Rj) -+ .addImm(Lane); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the INSERT_FD pseudo instruction. -+// insert_fd_pseudo $vd, $fs, n -+// => -+// subreg_to_reg $vk:sub_64, $fs -+// vpickve2gr.d rj, vk, 0 -+// vinsgr2vr.d vd, rj, lane -+MachineBasicBlock * -+LoongArchTargetLowering::emitINSERT_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Vd = MI.getOperand(0).getReg(); -+ unsigned Vd_in = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Fs = MI.getOperand(3).getReg(); -+ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); -+ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR64RegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Vj) -+ .addImm(0) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_64); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VPICKVE2GR_D), Rj) -+ .addReg(Vj) -+ .addImm(0); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VINSGR2VR_D), Vd) -+ .addReg(Vd_in) -+ .addReg(Rj) -+ .addImm(Lane); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+MachineBasicBlock * -+LoongArchTargetLowering::emitXINSERT_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned Xd_in = MI.getOperand(1).getReg(); -+ unsigned Lane = MI.getOperand(2).getImm(); -+ unsigned Fs = MI.getOperand(3).getReg(); -+ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) -+ .addImm(0) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_64); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVINSVE0_D), Xd) -+ .addReg(Xd_in) -+ .addReg(Xj) -+ .addImm(Lane); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the FILL_FW pseudo instruction. -+// -+// fill_fw_pseudo $vd, $fs -+// => -+// implicit_def $vt1 -+// insert_subreg $vt2:subreg_lo, $vt1, $fs -+// vreplvei.w vd, vt2, 0 -+MachineBasicBlock * -+LoongArchTargetLowering::emitFILL_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Vd = MI.getOperand(0).getReg(); -+ unsigned Fs = MI.getOperand(1).getReg(); -+ unsigned Vj1 = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); -+ unsigned Vj2 = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Vj1); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Vj2) -+ .addReg(Vj1) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_lo); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_W), Vd) -+ .addReg(Vj2) -+ .addImm(0); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the FILL_FD pseudo instruction. -+// -+// fill_fd_pseudo $vd, $fs -+// => -+// implicit_def $vt1 -+// insert_subreg $vt2:subreg_64, $vt1, $fs -+// vreplvei.d vd, vt2, 0 -+MachineBasicBlock * -+LoongArchTargetLowering::emitFILL_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Vd = MI.getOperand(0).getReg(); -+ unsigned Fs = MI.getOperand(1).getReg(); -+ unsigned Vj1 = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); -+ unsigned Vj2 = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Vj1); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Vj2) -+ .addReg(Vj1) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_64); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_D), Vd) -+ .addReg(Vj2) -+ .addImm(0); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the XFILL_FW pseudo instruction. -+// -+// xfill_fw_pseudo $xd, $fs -+// => -+// implicit_def $xt1 -+// insert_subreg $xt2:subreg_lo, $xt1, $fs -+// xvreplve0.w xd, xt2, 0 -+MachineBasicBlock * -+LoongArchTargetLowering::emitXFILL_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned Fs = MI.getOperand(1).getReg(); -+ unsigned Xj1 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ unsigned Xj2 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Xj1); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Xj2) -+ .addReg(Xj1) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_lo); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVREPLVE0_W), Xd).addReg(Xj2); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+// Emit the XFILL_FD pseudo instruction. -+// -+// xfill_fd_pseudo $xd, $fs -+// => -+// implicit_def $xt1 -+// insert_subreg $xt2:subreg_64, $xt1, $fs -+// xvreplve0.d xd, xt2, 0 -+MachineBasicBlock * -+LoongArchTargetLowering::emitXFILL_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const { -+ assert(Subtarget.isFP64bit()); -+ -+ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); -+ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); -+ DebugLoc DL = MI.getDebugLoc(); -+ unsigned Xd = MI.getOperand(0).getReg(); -+ unsigned Fs = MI.getOperand(1).getReg(); -+ unsigned Xj1 = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); -+ unsigned Xj2 = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); -+ -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Xj1); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Xj2) -+ .addReg(Xj1) -+ .addReg(Fs) -+ .addImm(LoongArch::sub_64); -+ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVREPLVE0_D), Xd).addReg(Xj2); -+ -+ MI.eraseFromParent(); // The pseudo instruction is gone now. -+ return BB; -+} -+ -+bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm) const { -+ bool IsLegal = false; -+ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { -+ return isUInt<5>(Imm); -+ } -+ return IsLegal; -+} - -- if (VT == MVT::f32 && !Subtarget.hasBasicF()) -+bool LoongArchTargetLowering::isFMAFasterThanFMulAndFAdd( -+ const MachineFunction &MF, EVT VT) const { -+ -+ VT = VT.getScalarType(); -+ -+ if (!VT.isSimple()) - return false; -- if (VT == MVT::f64 && !Subtarget.hasBasicD()) -+ -+ switch (VT.getSimpleVT().SimpleTy) { -+ case MVT::f32: -+ case MVT::f64: -+ return true; -+ default: -+ break; -+ } -+ -+ return false; -+} -+ -+bool LoongArchTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, -+ unsigned Index) const { -+ if (!isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, ResVT)) - return false; -- return (Imm.isZero() || Imm.isExactlyValue(+1.0)); -+ -+ return ( -+ (ResVT != MVT::v16i8) && (ResVT != MVT::v8i16) && -+ (Index == 0 || (Index == ResVT.getVectorNumElements() && -+ (ResVT.getSizeInBits() == SrcVT.getSizeInBits() / 2)))); -+} -+ -+Register -+LoongArchTargetLowering::getRegisterByName(const char *RegName, LLT VT, -+ const MachineFunction &MF) const { -+ // Named registers is expected to be fairly rare. For now, just support $r2 -+ // and $r21 since the linux kernel uses them. -+ if (Subtarget.is64Bit()) { -+ Register Reg = StringSwitch(RegName) -+ .Case("$r2", LoongArch::TP_64) -+ .Case("$r21", LoongArch::T9_64) -+ .Default(Register()); -+ if (Reg) -+ return Reg; -+ } else { -+ Register Reg = StringSwitch(RegName) -+ .Case("$r2", LoongArch::TP) -+ .Case("$r21", LoongArch::T9) -+ .Default(Register()); -+ if (Reg) -+ return Reg; -+ } -+ report_fatal_error("Invalid register name global variable"); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h -index 141f1fd3a..64e06b53f 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h -@@ -1,4 +1,4 @@ --//=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===// -+//===- LoongArchISelLowering.h - LoongArch DAG Lowering Interface ---------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,115 +6,553 @@ - // - //===----------------------------------------------------------------------===// - // --// This file defines the interfaces that LoongArch uses to lower LLVM code into --// a selection DAG. -+// This file defines the interfaces that LoongArch uses to lower LLVM code into a -+// selection DAG. - // - //===----------------------------------------------------------------------===// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H - -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" - #include "LoongArch.h" - #include "llvm/CodeGen/CallingConvLower.h" -+#include "llvm/CodeGen/ISDOpcodes.h" -+#include "llvm/CodeGen/MachineMemOperand.h" - #include "llvm/CodeGen/SelectionDAG.h" -+#include "llvm/CodeGen/SelectionDAGNodes.h" - #include "llvm/CodeGen/TargetLowering.h" -+#include "llvm/CodeGen/ValueTypes.h" -+#include "llvm/IR/CallingConv.h" -+#include "llvm/IR/InlineAsm.h" -+#include "llvm/IR/Type.h" -+#include "llvm/Support/MachineValueType.h" -+#include "llvm/Target/TargetMachine.h" -+#include -+#include -+#include -+#include -+#include -+#include - - namespace llvm { -+ -+class Argument; -+class CCState; -+class CCValAssign; -+class FastISel; -+class FunctionLoweringInfo; -+class MachineBasicBlock; -+class MachineFrameInfo; -+class MachineInstr; -+class LoongArchCCState; -+class LoongArchFunctionInfo; - class LoongArchSubtarget; --struct LoongArchRegisterInfo; --namespace LoongArchISD { --enum NodeType : unsigned { -- FIRST_NUMBER = ISD::BUILTIN_OP_END, -- -- // TODO: add more LoongArchISDs -- CALL, -- RET, -- // 32-bit shifts, directly matching the semantics of the named LoongArch -- // instructions. -- SLL_W, -- SRA_W, -- SRL_W, -- -- // FPR<->GPR transfer operations -- MOVGR2FR_W_LA64, -- MOVFR2GR_S_LA64, -- -- FTINT, -- -- BSTRINS, -- BSTRPICK, -- --}; --} // end namespace LoongArchISD -- --class LoongArchTargetLowering : public TargetLowering { -- const LoongArchSubtarget &Subtarget; -- --public: -- explicit LoongArchTargetLowering(const TargetMachine &TM, -- const LoongArchSubtarget &STI); -- -- const LoongArchSubtarget &getSubtarget() const { return Subtarget; } -- -- // Provide custom lowering hooks for some operations. -- SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; -- void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, -- SelectionDAG &DAG) const override; -- -- SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; -- -- // This method returns the name of a target specific DAG node. -- const char *getTargetNodeName(unsigned Opcode) const override; -- -- // Lower incoming arguments, copy physregs into vregs. -- SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, -- bool IsVarArg, -- const SmallVectorImpl &Ins, -- const SDLoc &DL, SelectionDAG &DAG, -- SmallVectorImpl &InVals) const override; -- bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, -- bool IsVarArg, -- const SmallVectorImpl &Outs, -- LLVMContext &Context) const override; -- SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, -- const SmallVectorImpl &Outs, -- const SmallVectorImpl &OutVals, const SDLoc &DL, -- SelectionDAG &DAG) const override; -- SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, -- SmallVectorImpl &InVals) const override; -- --private: -- /// Target-specific function used to lower LoongArch calling conventions. -- typedef bool LoongArchCCAssignFn(unsigned ValNo, MVT ValVT, -- CCValAssign::LocInfo LocInfo, -- CCState &State); -- -- void analyzeInputArgs(CCState &CCInfo, -- const SmallVectorImpl &Ins, -- LoongArchCCAssignFn Fn) const; -- void analyzeOutputArgs(CCState &CCInfo, -- const SmallVectorImpl &Outs, -- LoongArchCCAssignFn Fn) const; -- -- SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; -- SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; -- SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; -- -- MachineBasicBlock * -- EmitInstrWithCustomInserter(MachineInstr &MI, -- MachineBasicBlock *BB) const override; -- SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; -- SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; -- SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; -- SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; -- -- bool isFPImmLegal(const APFloat &Imm, EVT VT, -- bool ForCodeSize) const override; -- -- bool shouldInsertFencesForAtomic(const Instruction *I) const override { -- return isa(I) || isa(I); -- } --}; -+class LoongArchTargetMachine; -+class SelectionDAG; -+class TargetLibraryInfo; -+class TargetRegisterClass; -+ -+ namespace LoongArchISD { -+ -+ enum NodeType : unsigned { -+ // Start the numbering from where ISD NodeType finishes. -+ FIRST_NUMBER = ISD::BUILTIN_OP_END, -+ -+ // Jump and link (call) -+ JmpLink, -+ -+ // Tail call -+ TailCall, -+ -+ // global address -+ GlobalAddress, -+ -+ // Floating Point Branch Conditional -+ FPBrcond, -+ -+ // Floating Point Compare -+ FPCmp, -+ -+ // Floating Point Conditional Moves -+ CMovFP_T, -+ CMovFP_F, -+ FSEL, -+ -+ // FP-to-int truncation node. -+ TruncIntFP, -+ -+ // Return -+ Ret, -+ -+ // error trap Return -+ ERet, -+ -+ // Software Exception Return. -+ EH_RETURN, -+ -+ DBAR, -+ -+ BSTRPICK, -+ BSTRINS, -+ -+ // Vector comparisons. -+ // These take a vector and return a boolean. -+ VALL_ZERO, -+ VANY_ZERO, -+ VALL_NONZERO, -+ VANY_NONZERO, -+ -+ // Vector Shuffle with mask as an operand -+ VSHF, // Generic shuffle -+ SHF, // 4-element set shuffle. -+ VPACKEV, // Interleave even elements -+ VPACKOD, // Interleave odd elements -+ VILVH, // Interleave left elements -+ VILVL, // Interleave right elements -+ VPICKEV, // Pack even elements -+ VPICKOD, // Pack odd elements -+ -+ // Vector Lane Copy -+ INSVE, // Copy element from one vector to another -+ -+ // Combined (XOR (OR $a, $b), -1) -+ VNOR, -+ -+ VROR, -+ VRORI, -+ XVPICKVE, -+ XVPERMI, -+ XVSHUF4I, -+ REVBD, -+ -+ // Extended vector element extraction -+ VEXTRACT_SEXT_ELT, -+ VEXTRACT_ZEXT_ELT, -+ -+ XVBROADCAST, -+ VBROADCAST, -+ VABSD, -+ UVABSD, -+ }; -+ -+ } // ene namespace LoongArchISD -+ -+ //===--------------------------------------------------------------------===// -+ // TargetLowering Implementation -+ //===--------------------------------------------------------------------===// -+ -+ class LoongArchTargetLowering : public TargetLowering { -+ public: -+ explicit LoongArchTargetLowering(const LoongArchTargetMachine &TM, -+ const LoongArchSubtarget &STI); -+ -+ bool allowsMisalignedMemoryAccesses( -+ EVT VT, unsigned AS = 0, Align Alignment = Align(1), -+ MachineMemOperand::Flags Flags = MachineMemOperand::MONone, -+ bool *Fast = nullptr) const override; -+ -+ /// Enable LSX support for the given integer type and Register -+ /// class. -+ void addLSXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); -+ -+ /// Enable LSX support for the given floating-point type and -+ /// Register class. -+ void addLSXFloatType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC); -+ -+ /// Enable LASX support for the given integer type and Register -+ /// class. -+ void addLASXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); -+ -+ /// Enable LASX support for the given floating-point type and -+ /// Register class. -+ void addLASXFloatType(MVT::SimpleValueType Ty, -+ const TargetRegisterClass *RC); -+ -+ MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { -+ return MVT::i32; -+ } -+ -+ EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, -+ ISD::NodeType) const override; -+ -+ bool isCheapToSpeculateCttz() const override; -+ bool isCheapToSpeculateCtlz() const override; -+ -+ bool isLegalAddImmediate(int64_t) const override; -+ -+ /// Return the correct alignment for the current calling convention. -+ Align getABIAlignmentForCallingConv(Type *ArgTy, -+ const DataLayout &DL) const override { -+ const Align ABIAlign = DL.getABITypeAlign(ArgTy); -+ if (ArgTy->isVectorTy()) -+ return std::min(ABIAlign, Align(8)); -+ return ABIAlign; -+ } -+ -+ ISD::NodeType getExtendForAtomicOps() const override { -+ return ISD::SIGN_EXTEND; -+ } -+ -+ bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, -+ unsigned Index) const override; -+ -+ void LowerOperationWrapper(SDNode *N, -+ SmallVectorImpl &Results, -+ SelectionDAG &DAG) const override; -+ -+ /// LowerOperation - Provide custom lowering hooks for some operations. -+ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; -+ -+ bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, -+ EVT VT) const override; -+ -+ /// ReplaceNodeResults - Replace the results of node with an illegal result -+ /// type with new values built out of custom code. -+ /// -+ void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, -+ SelectionDAG &DAG) const override; -+ -+ /// getTargetNodeName - This method returns the name of a target specific -+ // DAG node. -+ const char *getTargetNodeName(unsigned Opcode) const override; -+ -+ /// getSetCCResultType - get the ISD::SETCC result ValueType -+ EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, -+ EVT VT) const override; -+ -+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; -+ -+ MachineBasicBlock * -+ EmitInstrWithCustomInserter(MachineInstr &MI, -+ MachineBasicBlock *MBB) const override; -+ -+ bool isShuffleMaskLegal(ArrayRef Mask, EVT VT) const override { -+ return false; -+ } -+ -+ const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; -+ -+ void AdjustInstrPostInstrSelection(MachineInstr &MI, -+ SDNode *Node) const override; -+ -+ void HandleByVal(CCState *, unsigned &, Align) const override; -+ -+ Register getRegisterByName(const char* RegName, LLT VT, -+ const MachineFunction &MF) const override; -+ -+ /// If a physical register, this returns the register that receives the -+ /// exception address on entry to an EH pad. -+ Register -+ getExceptionPointerRegister(const Constant *PersonalityFn) const override { -+ return ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; -+ } -+ -+ /// If a physical register, this returns the register that receives the -+ /// exception typeid on entry to a landing pad. -+ Register -+ getExceptionSelectorRegister(const Constant *PersonalityFn) const override { -+ return ABI.IsLP64() ? LoongArch::A1_64 : LoongArch::A1; -+ } -+ -+ bool isJumpTableRelative() const override { -+ return getTargetMachine().isPositionIndependent(); -+ } -+ -+ CCAssignFn *CCAssignFnForCall() const; -+ -+ CCAssignFn *CCAssignFnForReturn() const; -+ -+ private: -+ template -+ SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; -+ -+ /// This function fills Ops, which is the list of operands that will later -+ /// be used when a function call node is created. It also generates -+ /// copyToReg nodes to set up argument registers. -+ void getOpndList(SmallVectorImpl &Ops, -+ std::deque> &RegsToPass, -+ bool IsPICCall, bool GlobalOrExternal, bool IsCallReloc, -+ CallLoweringInfo &CLI, SDValue Callee, SDValue Chain, -+ bool IsTailCall) const; -+ -+ SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; -+ -+ // Subtarget Info -+ const LoongArchSubtarget &Subtarget; -+ // Cache the ABI from the TargetMachine, we use it everywhere. -+ const LoongArchABIInfo &ABI; -+ -+ // Create a TargetGlobalAddress node. -+ SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, -+ unsigned Flag) const; -+ -+ // Create a TargetExternalSymbol node. -+ SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, -+ unsigned Flag) const; -+ -+ // Create a TargetBlockAddress node. -+ SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, -+ unsigned Flag) const; -+ -+ // Create a TargetJumpTable node. -+ SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, -+ unsigned Flag) const; -+ -+ // Create a TargetConstantPool node. -+ SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, -+ unsigned Flag) const; -+ -+ // Lower Operand helpers -+ SDValue LowerCallResult(SDValue Chain, SDValue InFlag, -+ CallingConv::ID CallConv, bool isVarArg, -+ const SmallVectorImpl &Ins, -+ const SDLoc &dl, SelectionDAG &DAG, -+ SmallVectorImpl &InVals, -+ TargetLowering::CallLoweringInfo &CLI) const; -+ -+ // Lower Operand specifics -+ SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; -+ /// Lower VECTOR_SHUFFLE into one of a number of instructions -+ /// depending on the indices in the shuffle. -+ SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; -+ SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; -+ SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; -+ SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, -+ bool IsSRA) const; -+ SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; -+ -+ /// isEligibleForTailCallOptimization - Check whether the call is eligible -+ /// for tail call optimization. -+ bool -+ isEligibleForTailCallOptimization(const CCState &CCInfo, -+ CallLoweringInfo &CLI, MachineFunction &MF, -+ unsigned NextStackOffset, -+ const LoongArchFunctionInfo &FI) const; -+ -+ /// copyByValArg - Copy argument registers which were used to pass a byval -+ /// argument to the stack. Create a stack frame object for the byval -+ /// argument. -+ void copyByValRegs(SDValue Chain, const SDLoc &DL, -+ std::vector &OutChains, SelectionDAG &DAG, -+ const ISD::ArgFlagsTy &Flags, -+ SmallVectorImpl &InVals, -+ const Argument *FuncArg, unsigned FirstReg, -+ unsigned LastReg, const CCValAssign &VA, -+ LoongArchCCState &State) const; -+ -+ /// passByValArg - Pass a byval argument in registers or on stack. -+ void passByValArg(SDValue Chain, const SDLoc &DL, -+ std::deque> &RegsToPass, -+ SmallVectorImpl &MemOpChains, SDValue StackPtr, -+ MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, -+ unsigned FirstReg, unsigned LastReg, -+ const ISD::ArgFlagsTy &Flags, -+ const CCValAssign &VA) const; -+ -+ /// writeVarArgRegs - Write variable function arguments passed in registers -+ /// to the stack. Also create a stack frame object for the first variable -+ /// argument. -+ void writeVarArgRegs(std::vector &OutChains, SDValue Chain, -+ const SDLoc &DL, SelectionDAG &DAG, -+ CCState &State) const; -+ -+ SDValue -+ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, -+ const SmallVectorImpl &Ins, -+ const SDLoc &dl, SelectionDAG &DAG, -+ SmallVectorImpl &InVals) const override; -+ -+ SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, -+ SDValue Arg, const SDLoc &DL, bool IsTailCall, -+ SelectionDAG &DAG) const; -+ -+ SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, -+ SmallVectorImpl &InVals) const override; -+ -+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, -+ bool isVarArg, -+ const SmallVectorImpl &Outs, -+ LLVMContext &Context) const override; -+ -+ SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, -+ const SmallVectorImpl &Outs, -+ const SmallVectorImpl &OutVals, -+ const SDLoc &dl, SelectionDAG &DAG) const override; -+ -+ bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override; -+ -+ // Inline asm support -+ ConstraintType getConstraintType(StringRef Constraint) const override; -+ -+ /// Examine constraint string and operand type and determine a weight value. -+ /// The operand object must already have been set up with the operand type. -+ ConstraintWeight getSingleConstraintMatchWeight( -+ AsmOperandInfo &info, const char *constraint) const override; -+ -+ /// This function parses registers that appear in inline-asm constraints. -+ /// It returns pair (0, 0) on failure. -+ std::pair -+ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; -+ -+ std::pair -+ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, -+ StringRef Constraint, MVT VT) const override; -+ -+ /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops -+ /// vector. If it is invalid, don't add anything to Ops. If hasMemory is -+ /// true it means one of the asm constraint of the inline asm instruction -+ /// being processed is 'm'. -+ void LowerAsmOperandForConstraint(SDValue Op, -+ std::string &Constraint, -+ std::vector &Ops, -+ SelectionDAG &DAG) const override; -+ -+ unsigned -+ getInlineAsmMemConstraint(StringRef ConstraintCode) const override { -+ if (ConstraintCode == "R") -+ return InlineAsm::Constraint_R; -+ else if (ConstraintCode == "ZC") -+ return InlineAsm::Constraint_ZC; -+ else if (ConstraintCode == "ZB") -+ return InlineAsm::Constraint_ZB; -+ return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); -+ } -+ -+ bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, -+ Type *Ty, unsigned AS, -+ Instruction *I = nullptr) const override; -+ -+ bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; -+ -+ EVT getOptimalMemOpType(const MemOp &Op, -+ const AttributeList &FuncAttributes) const override; -+ -+ /// isFPImmLegal - Returns true if the target can instruction select the -+ /// specified FP immediate natively. If false, the legalizer will -+ /// materialize the FP immediate as a load from a constant pool. -+ bool isFPImmLegal(const APFloat &Imm, EVT VT, -+ bool ForCodeSize) const override; -+ -+ bool useSoftFloat() const override; -+ -+ bool shouldInsertFencesForAtomic(const Instruction *I) const override { -+ return isa(I) || isa(I); -+ } -+ -+ bool mayBeEmittedAsTailCall(const CallInst *CI) const override; -+ -+ /// Emit a sign-extension using sll/sra, seb, or seh appropriately. -+ MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ unsigned Size, unsigned DstReg, -+ unsigned SrcRec) const; -+ -+ MachineBasicBlock *emitLoadAddress(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ unsigned Size) const; -+ -+ MachineBasicBlock *emitXINSERT_B(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ MachineBasicBlock *emitINSERT_H_VIDX(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ unsigned Size) const; -+ MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, -+ bool isFPCmp, unsigned Opc) const; -+ -+ /// SE -+ MachineBasicBlock *emitLSXCBranchPseudo(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ unsigned BranchOp) const; -+ /// Emit the COPY_FW pseudo instruction -+ MachineBasicBlock *emitCOPY_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ /// Emit the COPY_FD pseudo instruction -+ MachineBasicBlock *emitCOPY_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXCOPY_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXCOPY_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitCONCAT_VECTORS(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ unsigned Bytes) const; -+ -+ MachineBasicBlock *emitXCOPY_FW_GPR(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXINSERT_BH(MachineInstr &MI, MachineBasicBlock *BB, -+ unsigned EltSizeInBytes) const; -+ -+ MachineBasicBlock *emitXINSERT_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ /// Emit the INSERT_FW pseudo instruction -+ MachineBasicBlock *emitINSERT_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ /// Emit the INSERT_FD pseudo instruction -+ MachineBasicBlock *emitINSERT_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXINSERT_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXINSERT_DF_VIDX(MachineInstr &MI, -+ MachineBasicBlock *BB, -+ bool IsGPR64) const; -+ /// Emit the FILL_FW pseudo instruction -+ MachineBasicBlock *emitFILL_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ /// Emit the FILL_FD pseudo instruction -+ MachineBasicBlock *emitFILL_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ -+ MachineBasicBlock *emitXFILL_FW(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ MachineBasicBlock *emitXFILL_FD(MachineInstr &MI, -+ MachineBasicBlock *BB) const; -+ }; - - } // end namespace llvm - -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td -index bebc83a86..d75d5198b 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td -@@ -1,4 +1,4 @@ --//===- LoongArchInstrFormats.td - LoongArch Instr. Formats -*- tablegen -*-===// -+//===-- LoongArchInstrFormats.td - LoongArch Instruction Formats -----*- tablegen -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -9,396 +9,782 @@ - //===----------------------------------------------------------------------===// - // Describe LoongArch instructions format - // --// opcode - operation code. --// rd - destination register operand. --// r{j/k} - source register operand. --// immN - immediate data operand. -+// CPU INSTRUCTION FORMATS -+// -+// opcode - operation code. -+// rs - src reg. -+// rt - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr). -+// rd - dst reg, only used on 3 regs instr. -+// shamt - only used on shift instructions, contains the shift amount. -+// funct - combined with opcode field give us an operation code. - // - //===----------------------------------------------------------------------===// - --class LAInst pattern = []> -- : Instruction { -+class StdArch { -+ -+ bits<32> Inst; -+} -+ -+// Format specifies the encoding used by the instruction. This is part of the -+// ad-hoc solution used to emit machine instruction encodings by our machine -+// code emitter. -+class Format val> { -+ bits<4> Value = val; -+} -+ -+def Pseudo : Format<0>; -+def FrmR : Format<1>; -+def FrmI : Format<2>; -+def FrmJ : Format<3>; -+def FrmFR : Format<4>; -+def FrmFI : Format<5>; -+def FrmOther : Format<6>; -+ -+// Generic LoongArch Format -+class InstLA pattern, Format f> -+ : Instruction -+{ - field bits<32> Inst; -- // SoftFail is a field the disassembler can use to provide a way for -- // instructions to not match without killing the whole decode process. It is -- // mainly used for ARM, but Tablegen expects this field to exist or it fails -- // to build the decode table. -- field bits<32> SoftFail = 0; -+ Format Form = f; - - let Namespace = "LoongArch"; -+ - let Size = 4; -+ - let OutOperandList = outs; -- let InOperandList = ins; -- let AsmString = opcstr # "\t" # opnstr; -- let Pattern = pattern; -+ let InOperandList = ins; -+ let AsmString = asmstr; -+ let Pattern = pattern; -+ -+ // -+ // Attributes specific to LoongArch instructions... -+ // -+ bits<4> FormBits = Form.Value; -+ bit isCTI = 0; // Any form of Control Transfer Instruction. -+ // Required for LoongArch -+ bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. -+ bit IsPCRelativeLoad = 0; // Load instruction with implicit source register -+ // ($pc) and with explicit offset and destination -+ // register -+ bit hasFCCRegOperand = 0; // Instruction uses $fcc register -+ -+ // TSFlags layout should be kept in sync with MCTargetDesc/LoongArchBaseInfo.h. -+ let TSFlags{3-0} = FormBits; -+ let TSFlags{4} = isCTI; -+ let TSFlags{5} = hasForbiddenSlot; -+ let TSFlags{6} = IsPCRelativeLoad; -+ let TSFlags{7} = hasFCCRegOperand; -+ -+ let DecoderNamespace = "LoongArch"; -+ -+ field bits<32> SoftFail = 0; - } - --// Pseudo instructions --class Pseudo pattern = [], string opcstr = "", -- string opnstr = ""> -- : LAInst { -- let isPseudo = 1; -- let isCodeGenOnly = 1; -+class InstForm pattern, -+ Format f, string opstr = ""> : -+ InstLA { -+ string BaseOpcode = opstr; -+ string Arch; -+} -+ -+class LoongArch_str { -+ string Arch; -+ string BaseOpcode = opstr; -+} -+ -+//===-----------------------------------------------------------===// -+// Format instruction classes in the LoongArch -+//===-----------------------------------------------------------===// -+ -+// R2 classes: 2 registers -+// -+class R2 : StdArch { -+ bits<5> rj; -+ bits<5> rd; -+ -+ let Inst{9-5} = rj; -+ let Inst{4-0} = rd; -+} -+ -+class R2I op> -+ : R2 { -+ let Inst{31-15} = 0x0; -+ let Inst{14-10} = op; -+} -+ -+class R2F op> -+ : R2 { -+ bits<5> fj; -+ bits<5> fd; -+ -+ let Inst{31-20} = 0x11; -+ let Inst{19-10} = op; -+ let Inst{9-5} = fj; -+ let Inst{4-0} = fd; -+} -+ -+class MOVFI op> -+ : R2 { -+ bits<5> rj; -+ bits<5> fd; -+ -+ let Inst{31-20} = 0x11; -+ let Inst{19-10} = op; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = fd; -+} -+ -+class MOVIF op> -+ : R2 { -+ bits<5> fj; -+ bits<5> rd; -+ -+ let Inst{31-20} = 0x11; -+ let Inst{19-10} = op; -+ let Inst{9-5} = fj; -+ let Inst{4-0} = rd; -+} -+ -+class R2P op> -+ : R2 { -+ let Inst{31-13} = 0x3240; -+ let Inst{12-10} = op; -+} -+ -+class R2_CSR op> -+ : StdArch { -+ bits<5> rj; -+ bits<5> rd; -+ bits<14> csr; -+ -+ let Inst{31-24} = op; -+ let Inst{23-10} = csr; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = rd; - } - --// 2R-type --// --class Fmt2R op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -+class R2_SI16 op> -+ : StdArch { -+ bits<5> rd; -+ bits<5> rj; -+ bits<16> si16; -+ -+ let Inst{31-26} = op; -+ let Inst{25-10} = si16; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = rd; -+} -+ -+class R2_COND op, bits<5> cond> -+ : StdArch { -+ bits<5> fj; -+ bits<5> fk; -+ bits<3> cd; -+ -+ let Inst{31-22} = 0x30; -+ let Inst{21-20} = op; -+ let Inst{19-15} = cond; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-3} = 0b00; -+ let Inst{2-0} = cd; -+} -+ -+class R2_LEVEL op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<8> level; - -- let Inst{31-10} = op; -+ let Inst{31-18} = op; -+ let Inst{17-10} = level; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 3R-type --// --class Fmt3R op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -+class IMM32 op> -+ : StdArch { -+ let Inst{31-16} = 0x0648; -+ let Inst{15-10} = op; -+ let Inst{9-0} = 0; -+} -+ -+class WAIT_FM : StdArch { -+ bits<15> hint; -+ -+ let Inst{31-15} = 0xc91; -+ let Inst{14-0} = hint; -+} -+ -+class R2_INVTLB : StdArch { -+ bits<5> rj; -+ bits<5> op; -+ bits<5> rk; -+ -+ let Inst{31-15} = 0xc93; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = op; -+} -+ -+class BAR_FM op> -+ : StdArch { -+ bits<15> hint; -+ -+ let Inst{31-16} = 0x3872; -+ let Inst{15} = op; -+ let Inst{14-0} = hint; -+} -+ -+class PRELD_FM : StdArch { -+ bits<5> rj; -+ bits<5> hint; -+ bits<12> imm12; -+ -+ let Inst{31-22} = 0xab; -+ let Inst{21-10} = imm12; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = hint; -+} -+ -+// R3 classes: 3 registers -+// -+class R3 : StdArch { - bits<5> rk; - bits<5> rj; - bits<5> rd; - -- let Inst{31-15} = op; - let Inst{14-10} = rk; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 3RI2-type --// --class Fmt3RI2 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<2> imm2; -+class R3I op> -+ : R3 { -+ let Inst{31-22} = 0x0; -+ let Inst{21-15} = op; -+} -+ -+class R3F op> -+ : R3 { -+ bits<5> fk; -+ bits<5> fj; -+ bits<5> fd; -+ -+ let Inst{31-21} = 0x8; -+ let Inst{20-15} = op; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-0} = fd; -+} -+ -+class R3MI op> -+ : R3 { -+ let Inst{31-23} = 0x70; -+ let Inst{22-15} = op; -+} -+ -+class AM op> : StdArch { -+ bits<5> rk; -+ bits<17> addr; // rj + 12 bits offset 0 -+ bits<5> rd; -+ -+ let Inst{31-21} = 0x1c3; -+ let Inst{20-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = rd; -+} -+ -+class R3MF op> -+ : R3 { -+ bits<5> fd; -+ -+ let Inst{31-23} = 0x70; -+ let Inst{22-15} = op; -+ let Inst{4-0} = fd; -+} -+ -+class R3_SA2 op> -+ : StdArch { - bits<5> rk; - bits<5> rj; - bits<5> rd; -+ bits<2> sa; - -- let Inst{31-17} = op; -- let Inst{16-15} = imm2; -+ let Inst{31-22} = 0x0; -+ let Inst{21-17} = op; -+ let Inst{16-15} = sa; - let Inst{14-10} = rk; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 3RI3-type --// --class Fmt3RI3 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<3> imm3; -+class R3_SA3 : StdArch { - bits<5> rk; - bits<5> rj; - bits<5> rd; -+ bits<3> sa; - -- let Inst{31-18} = op; -- let Inst{17-15} = imm3; -+ let Inst{31-18} = 3; -+ let Inst{17-15} = sa; - let Inst{14-10} = rk; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI5-type --// --class Fmt2RI5 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> imm5; -+// R4 classes: 4 registers -+// -+class R4MUL op> -+ : StdArch { -+ bits<5> fa; -+ bits<5> fk; -+ bits<5> fj; -+ bits<5> fd; -+ -+ let Inst{31-24} = 0x8; -+ let Inst{23-20} = op; -+ let Inst{19-15} = fa; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-0} = fd; -+} -+ -+class R4CMP op> -+ : StdArch { -+ bits<5> cond; -+ bits<5> fk; -+ bits<5> fj; -+ bits<3> cd; -+ -+ let Inst{31-22} = 0x30; -+ let Inst{21-20} = op; -+ let Inst{19-15} = cond; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-3} = 0; -+ let Inst{2-0} = cd; -+} -+ -+class R4SEL : StdArch { -+ bits<3> ca; -+ bits<5> fk; -+ bits<5> fj; -+ bits<5> fd; -+ -+ let Inst{31-18} = 0x340; -+ let Inst{17-15} = ca; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-0} = fd; -+} -+ -+// R2_IMM5 classes: 2registers and 1 5bit-immediate -+// -+class R2_IMM5 op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<5> imm5; - -- let Inst{31-15} = op; -+ let Inst{31-20} = 0x4; -+ let Inst{19-18} = op; -+ let Inst{17-15} = 0x1; - let Inst{14-10} = imm5; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI6-type --// --class Fmt2RI6 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<6> imm6; -+// R2_IMM6 classes: 2registers and 1 6bit-immediate -+// -+class R2_IMM6 op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<6> imm6; - -- let Inst{31-16} = op; -+ let Inst{31-20} = 0x4; -+ let Inst{19-18} = op; -+ let Inst{17-16} = 0x1; - let Inst{15-10} = imm6; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI8-type --// --class Fmt2RI8 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<8> imm8; -+// R2_IMM12 classes: 2 registers and 1 12bit-immediate -+// -+class LOAD_STORE op> -+ : StdArch { -+ bits<5> rd; -+ bits<17> addr; -+ -+ let Inst{31-26} = 0xa; -+ let Inst{25-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = rd; -+} -+// for reloc -+class LOAD_STORE_RRI op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<12> imm12; - -- let Inst{31-18} = op; -- let Inst{17-10} = imm8; -+ let Inst{31-26} = 0xa; -+ let Inst{25-22} = op; -+ let Inst{21-10} = imm12; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI12-type --// --class Fmt2RI12 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<12> imm12; -+ -+class R2_IMM12 op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<12> imm12; - -- let Inst{31-22} = op; -+ let Inst{31-25} = 0x1; -+ let Inst{24-22} = op; - let Inst{21-10} = imm12; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI14-type --// --class Fmt2RI14 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<14> imm14; -+class LEA_ADDI_FM op> -+ : StdArch { -+ bits<5> rd; -+ bits<17> addr; -+ -+ let Inst{31-25} = 0x1; -+ let Inst{24-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = rd; -+} -+ -+// R2_IMM14 classes: 2 registers and 1 14bit-immediate -+// -+class LL_SC op> -+ : StdArch { -+ bits<5> rd; -+ bits<19> addr; -+ -+ let Inst{31-27} = 4; -+ let Inst{26-24} = op; -+ let Inst{23-10} = addr{13-0}; -+ let Inst{9-5} = addr{18-14}; -+ let Inst{4-0} = rd; -+} -+ -+// R2_IMM16 classes: 2 registers and 1 16bit-immediate -+// -+class R2_IMM16BEQ op> -+ : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<16> offs16; - -- let Inst{31-24} = op; -- let Inst{23-10} = imm14; -+ let Inst{31-26} = op; -+ let Inst{25-10} = offs16; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// 2RI16-type --// --class Fmt2RI16 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<16> imm16; -+class R2_IMM16JIRL : StdArch { - bits<5> rj; - bits<5> rd; -+ bits<16> offs16; -+ -+ let Inst{31-26} = 0x13; -+ let Inst{25-10} = offs16; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = rd; -+} -+ -+// R1_IMM21 classes: 1 registers and 1 21bit-immediate -+// -+class R1_IMM21BEQZ op> -+ : StdArch { -+ bits<5> rj; -+ bits<21> offs21; - - let Inst{31-26} = op; -- let Inst{25-10} = imm16; -+ let Inst{25-10} = offs21{15-0}; - let Inst{9-5} = rj; -+ let Inst{4-0} = offs21{20-16}; -+} -+ -+class R1_CSR op> -+ : StdArch { -+ bits<5> rd; -+ bits<14> csr; -+ -+ let Inst{31-24} = op{7-0}; -+ let Inst{23-10} = csr; -+ let Inst{9-5} = op{12-8}; - let Inst{4-0} = rd; - } - --// 1RI20-type --// --class Fmt1RI20 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<20> imm20; -+class R1_SI20 op> -+ : StdArch { - bits<5> rd; -+ bits<20> si20; - - let Inst{31-25} = op; -- let Inst{24-5} = imm20; -+ let Inst{24-5} = si20; - let Inst{4-0} = rd; - } - --// 1RI21-type --// --class Fmt1RI21 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<21> imm21; -+class R1_CACHE : StdArch { - bits<5> rj; -+ bits<5> op; -+ bits<12> si12; - -- let Inst{31-26} = op; -- let Inst{25-10} = imm21{15-0}; -+ let Inst{31-22} = 0x18; -+ let Inst{21-10} = si12; - let Inst{9-5} = rj; -- let Inst{4-0} = imm21{20-16}; -+ let Inst{4-0} = op; -+} -+ -+class R1_SEQ op> -+ : StdArch { -+ bits<5> rj; -+ bits<5> offset; -+ bits<8> seq; -+ -+ let Inst{31-18} = op; -+ let Inst{17-10} = seq; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = 0b00000; - } - --// I15-type --// --class FmtI15 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<15> imm15; -+class R1_BCEQZ op> -+ : StdArch { -+ bits<21> offset; -+ bits<3> cj; - -- let Inst{31-15} = op; -- let Inst{14-0} = imm15; -+ let Inst{31-26} = 0x12; -+ let Inst{25-10} = offset{15-0}; -+ let Inst{9-8} = op; -+ let Inst{7-5} = cj; -+ let Inst{4-0} = offset{20-16}; - } - --// I26-type --// --class FmtI26 op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<26> imm26; -+// IMM26 classes: 1 26bit-immediate -+// -+class IMM26B op> -+ : StdArch { -+ bits<26> offs26; - - let Inst{31-26} = op; -- let Inst{25-10} = imm26{15-0}; -- let Inst{9-0} = imm26{25-16}; -+ let Inst{25-10} = offs26{15-0}; -+ let Inst{9-0} = offs26{25-16}; -+} -+ -+// LoongArch Pseudo Instructions Format -+class LoongArchPseudo pattern> : -+ InstLA { -+ let isCodeGenOnly = 1; -+ let isPseudo = 1; -+} -+ -+// Pseudo-instructions for alternate assembly syntax (never used by codegen). -+// These are aliases that require C++ handling to convert to the target -+// instruction, while InstAliases can be handled directly by tblgen. -+class LoongArchAsmPseudoInst: -+ InstLA { -+ let isPseudo = 1; -+ let Pattern = []; - } - --// FmtBSTR_W --// --class FmtBSTR_W op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -+// -+// Misc instruction classes -+class ASSERT op> -+ : StdArch { -+ bits<5> rk; -+ bits<5> rj; -+ -+ let Inst{31-17} = 0x0; -+ let Inst{16-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = 0x0; -+} -+ -+class CODE15 op> -+ : StdArch { -+ bits<15> Code; -+ -+ let Inst{31-22} = 0x0; -+ let Inst{21-15} = op; -+ let Inst{14-0} = Code; -+} -+ -+class INSERT_BIT32 op> -+ : StdArch { - bits<5> msbw; - bits<5> lsbw; - bits<5> rj; - bits<5> rd; - -- let Inst{31-21} = op{11-1}; -+ let Inst{31-21} = 0x3; - let Inst{20-16} = msbw; -- let Inst{15} = op{0}; -+ let Inst{15} = op; - let Inst{14-10} = lsbw; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// FmtBSTR_D --// --class FmtBSTR_D op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -+class INSERT_BIT64 op> -+ : StdArch { - bits<6> msbd; - bits<6> lsbd; - bits<5> rj; - bits<5> rd; - -- let Inst{31-22} = op; -+ let Inst{31-23} = 0x1; -+ let Inst{22} = op; - let Inst{21-16} = msbd; - let Inst{15-10} = lsbd; - let Inst{9-5} = rj; - let Inst{4-0} = rd; - } - --// FmtASRT --// --class FmtASRT op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<5> rk; -+class MOVGPR2FCSR: StdArch { -+ bits<5> fcsr; - bits<5> rj; - -- let Inst{31-15} = op; -- let Inst{14-10} = rk; -+ let Inst{31-10} = 0x4530; - let Inst{9-5} = rj; -- let Inst{4-0} = 0x0; -+ let Inst{4-0} = fcsr; - } - --// FmtPRELD --// < 0b0010101011 | I12 | rj | I5> --class FmtPRELD pattern = []> -- : LAInst { -- bits<12> imm12; -- bits<5> rj; -- bits<5> imm5; -+class MOVFCSR2GPR: StdArch { -+ bits<5> fcsr; -+ bits<5> rd; - -- let Inst{31-22} = 0b0010101011; -- let Inst{21-10} = imm12; -- let Inst{9-5} = rj; -- let Inst{4-0} = imm5; -+ let Inst{31-10} = 0x4532; -+ let Inst{9-5} = fcsr; -+ let Inst{4-0} = rd; - } - --// FmtPRELDX --// < 0b00111000001011000 | rk | rj | I5> --class FmtPRELDX pattern = []> -- : LAInst { -- bits<5> rk; -+class MOVFGR2FCFR: StdArch { -+ bits<3> cd; -+ bits<5> fj; -+ -+ let Inst{31-10} = 0x4534; -+ let Inst{9-5} = fj; -+ let Inst{4-3} = 0; -+ let Inst{2-0} = cd; -+} -+ -+class MOVFCFR2FGR: StdArch { -+ bits<3> cj; -+ bits<5> fd; -+ -+ let Inst{31-10} = 0x4535; -+ let Inst{9-8} = 0; -+ let Inst{7-5} = cj; -+ let Inst{4-0} = fd; -+} -+ -+class MOVGPR2FCFR: StdArch { -+ bits<3> cd; - bits<5> rj; -- bits<5> imm5; - -- let Inst{31-15} = 0b00111000001011000; -- let Inst{14-10} = rk; -+ let Inst{31-10} = 0x4536; - let Inst{9-5} = rj; -- let Inst{4-0} = imm5; -+ let Inst{4-3} = 0; -+ let Inst{2-0} = cd; - } - --// FmtCSR --// --class FmtCSR op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<14> csr_num; -+class MOVFCFR2GPR: StdArch { -+ bits<3> cj; - bits<5> rd; - -- let Inst{31-24} = op{12-5}; -- let Inst{23-10} = csr_num; -- let Inst{9-5} = op{4-0}; -+ let Inst{31-10} = 0x4537; -+ let Inst{9-8} = 0; -+ let Inst{7-5} = cj; - let Inst{4-0} = rd; - } - --// FmtCSRXCHG --// --class FmtCSRXCHG op, dag outs, dag ins, string opcstr, string opnstr, -- list pattern = []> -- : LAInst { -- bits<14> csr_num; -- bits<5> rj; -- bits<5> rd; -+class LoongArchInst : InstLA<(outs), (ins), "", [], FrmOther> { -+} -+class JMP_OFFS_2R op> : LoongArchInst { -+ bits<5> rs; -+ bits<5> rd; -+ bits<16> offset; - -- let Inst{31-24} = op; -- let Inst{23-10} = csr_num; -- let Inst{9-5} = rj; -- let Inst{4-0} = rd; -+ bits<32> Inst; -+ -+ let Inst{31-26} = op; -+ let Inst{25-10} = offset; -+ let Inst{9-5} = rs; -+ let Inst{4-0} = rd; - } - --// FmtCACOP --// <0b0000011000 | I12 | rj | I5> --class FmtCACOP pattern = []> -- : LAInst { -- bits<12> imm12; -- bits<5> rj; -- bits<5> op; -+class FJ op> : StdArch -+{ -+ bits<26> target; - -- let Inst{31-22} = 0b0000011000; -- let Inst{21-10} = imm12; -- let Inst{9-5} = rj; -- let Inst{4-0} = op; -+ let Inst{31-26} = op; -+ let Inst{25-10} = target{15-0}; -+ let Inst{9-0} = target{25-16}; - } - --// FmtIMM32 --// --class FmtI32 op, string opstr, list pattern = []> -- : LAInst<(outs), (ins), opstr, "", pattern> { -- let Inst{31-0} = op; -+class LUI_FM : StdArch { -+ bits<5> rt; -+ bits<16> imm16; -+ -+ let Inst{31-26} = 0xf; -+ let Inst{25-21} = 0; -+ let Inst{20-16} = rt; -+ let Inst{15-0} = imm16; - } - --// FmtINVTLB --// <0b00000110010010011 | rk | rj | I5> --class FmtINVTLB pattern = []> -- : LAInst { -- bits<5> rk; -+class R2_IMM12M_STD op> : StdArch { - bits<5> rj; -- bits<5> op; -+ bits<5> rd; -+ bits<12> imm12; - -- let Inst{31-15} = 0b00000110010010011; -- let Inst{14-10} = rk; -+ let Inst{31-26} = 0xa; -+ let Inst{25-22} = op; -+ let Inst{21-10} = imm12; - let Inst{9-5} = rj; -- let Inst{4-0} = op; -+ let Inst{4-0} = rd; - } - --// FmtLDPTE --// <0b00000110010001 | seq | rj | 00000> --class FmtLDPTE pattern = []> -- : LAInst { -- bits<8> seq; -- bits<5> rj; -+class LLD_2R Code> : LoongArchInst { -+ bits<5> rd; -+ bits<19> addr; -+ bits<5> rj = addr{18-14}; -+ bits<14> offset = addr{13-0}; - -- let Inst{31-18} = 0b00000110010001; -- let Inst{17-10} = seq; -+ bits<32> Inst; -+ -+ let Inst{31-27} = 0x4; -+ let Inst{26-24} = Code; -+ let Inst{23-10} = offset; - let Inst{9-5} = rj; -- let Inst{4-0} = 0b00000; -+ let Inst{4-0} = rd; - } -+ -+class CEQS_FM op> { -+ bits<5> fj; -+ bits<5> fk; -+ bits<3> cd; -+ bits<5> cond; -+ -+ bits<32> Inst; -+ -+ let Inst{31-22} = 0x30; -+ let Inst{21-20} = op; -+ let Inst{19-15} = cond; -+ let Inst{14-10} = fk; -+ let Inst{9-5} = fj; -+ let Inst{4-3} = 0b00; -+ let Inst{2-0} = cd; -+} -+ -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp -index bcbd4b28f..00abd9167 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp -@@ -1,4 +1,4 @@ --//=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- C++ -*-===// -+//===- LoongArchInstrInfo.cpp - LoongArch Instruction Information -------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,105 +11,1030 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchInstrInfo.h" --#include "LoongArch.h" --#include "LoongArchMachineFunctionInfo.h" -+#include "LoongArchSubtarget.h" -+#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/ADT/SmallVector.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" -+#include "llvm/CodeGen/MachineFrameInfo.h" -+#include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineInstr.h" -+#include "llvm/CodeGen/MachineInstrBuilder.h" -+#include "llvm/CodeGen/MachineOperand.h" -+#include "llvm/CodeGen/RegisterScavenging.h" -+#include "llvm/CodeGen/TargetOpcodes.h" -+#include "llvm/CodeGen/TargetSubtargetInfo.h" -+#include "llvm/IR/DebugLoc.h" -+#include "llvm/MC/MCInstrDesc.h" -+#include "llvm/Target/TargetMachine.h" -+#include - - using namespace llvm; - - #define GET_INSTRINFO_CTOR_DTOR - #include "LoongArchGenInstrInfo.inc" - --LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI) -+// Pin the vtable to this file. -+void LoongArchInstrInfo::anchor() {} -+LoongArchInstrInfo::LoongArchInstrInfo(const LoongArchSubtarget &STI) - : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN, -- LoongArch::ADJCALLSTACKUP) {} -+ LoongArch::ADJCALLSTACKUP), -+ RI(), Subtarget(STI) {} -+ -+const LoongArchRegisterInfo &LoongArchInstrInfo::getRegisterInfo() const { -+ return RI; -+} -+ -+/// isLoadFromStackSlot - If the specified machine instruction is a direct -+/// load from a stack slot, return the virtual or physical register number of -+/// the destination along with the FrameIndex of the loaded stack slot. If -+/// not, return 0. This predicate must return 0 if the instruction has -+/// any side effects other than loading from the stack slot. -+unsigned LoongArchInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, -+ int &FrameIndex) const { -+ unsigned Opc = MI.getOpcode(); -+ if ((Opc == LoongArch::LD_W) || (Opc == LoongArch::LD_D) || -+ (Opc == LoongArch::FLD_S) || (Opc == LoongArch::FLD_D)) { -+ if ((MI.getOperand(1).isFI()) && // is a stack slot -+ (MI.getOperand(2).isImm()) && // the imm is zero -+ (isZeroImm(MI.getOperand(2)))) { -+ FrameIndex = MI.getOperand(1).getIndex(); -+ return MI.getOperand(0).getReg(); -+ } -+ } -+ return 0; -+} -+ -+/// isStoreToStackSlot - If the specified machine instruction is a direct -+/// store to a stack slot, return the virtual or physical register number of -+/// the source reg along with the FrameIndex of the loaded stack slot. If -+/// not, return 0. This predicate must return 0 if the instruction has -+/// any side effects other than storing to the stack slot. -+unsigned LoongArchInstrInfo::isStoreToStackSlot(const MachineInstr &MI, -+ int &FrameIndex) const { -+ unsigned Opc = MI.getOpcode(); -+ if ((Opc == LoongArch::ST_D) || (Opc == LoongArch::ST_W) || -+ (Opc == LoongArch::FST_S) ||(Opc == LoongArch::FST_D)) { -+ if ((MI.getOperand(1).isFI()) && // is a stack slot -+ (MI.getOperand(2).isImm()) && // the imm is zero -+ (isZeroImm(MI.getOperand(2)))) { -+ FrameIndex = MI.getOperand(1).getIndex(); -+ return MI.getOperand(0).getReg(); -+ } -+ } -+ return 0; -+} - - void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB, -- MachineBasicBlock::iterator MBBI, -- const DebugLoc &DL, MCRegister DstReg, -+ MachineBasicBlock::iterator I, -+ const DebugLoc &DL, MCRegister DestReg, - MCRegister SrcReg, bool KillSrc) const { -- if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) { -- BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg) -- .addReg(SrcReg, getKillRegState(KillSrc)) -- .addReg(LoongArch::R0); -- return; -+ unsigned Opc = 0, ZeroReg = 0; -+ unsigned ZeroImm = 1; -+ if (LoongArch::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg. -+ if (LoongArch::GPR32RegClass.contains(SrcReg)) { -+ Opc = LoongArch::OR32, ZeroReg = LoongArch::ZERO; -+ } -+ else if (LoongArch::FGR32RegClass.contains(SrcReg)) -+ Opc = LoongArch::MOVFR2GR_S; -+ else if (LoongArch::FCFRRegClass.contains(SrcReg)) -+ Opc = LoongArch::MOVCF2GR; - } -- -- // FPR->FPR copies. -- unsigned Opc; -- if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) { -+ else if (LoongArch::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg. -+ if (LoongArch::FGR32RegClass.contains(DestReg)) -+ Opc = LoongArch::MOVGR2FR_W; -+ else if (LoongArch::FCFRRegClass.contains(DestReg)) -+ Opc = LoongArch::MOVGR2CF; -+ } -+ else if (LoongArch::FGR32RegClass.contains(DestReg, SrcReg)) - Opc = LoongArch::FMOV_S; -- } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) { -+ else if (LoongArch::FGR64RegClass.contains(DestReg, SrcReg)) - Opc = LoongArch::FMOV_D; -- } else { -- // TODO: support other copies. -- llvm_unreachable("Impossible reg-to-reg copy"); -+ else if (LoongArch::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg. -+ if (LoongArch::GPR64RegClass.contains(SrcReg)) -+ Opc = LoongArch::OR, ZeroReg = LoongArch::ZERO_64; -+ else if (LoongArch::FGR64RegClass.contains(SrcReg)) -+ Opc = LoongArch::MOVFR2GR_D; -+ else if (LoongArch::FCFRRegClass.contains(SrcReg)) -+ Opc = LoongArch::MOVCF2GR; -+ } -+ else if (LoongArch::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg. -+ if (LoongArch::FGR64RegClass.contains(DestReg)) -+ Opc = LoongArch::MOVGR2FR_D; -+ else if (LoongArch::FCFRRegClass.contains(DestReg)) -+ Opc = LoongArch::MOVGR2CF; - } -+ else if (LoongArch::FGR32RegClass.contains(DestReg)) // Copy to FGR32 Reg -+ Opc = LoongArch::MOVCF2FR; -+ else if (LoongArch::FGR32RegClass.contains(SrcReg)) // Copy from FGR32 Reg -+ Opc = LoongArch::MOVFR2CF; -+ else if (LoongArch::FGR64RegClass.contains(DestReg)) // Copy to FGR64 Reg -+ Opc = LoongArch::MOVCF2FR; -+ else if (LoongArch::FGR64RegClass.contains(SrcReg)) // Copy from FGR64 Reg -+ Opc = LoongArch::MOVFR2CF; -+ else if (LoongArch::LSX128BRegClass.contains(DestReg)) { // Copy to LSX reg -+ if (LoongArch::LSX128BRegClass.contains(SrcReg)) -+ Opc = LoongArch::VORI_B, ZeroImm = 0; -+ } else if (LoongArch::LASX256BRegClass.contains( -+ DestReg)) { // Copy to LASX reg -+ if (LoongArch::LASX256BRegClass.contains(SrcReg)) -+ Opc = LoongArch::XVORI_B, ZeroImm = 0; -+ } -+ -+ assert(Opc && "Cannot copy registers"); -+ -+ MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); -+ -+ if (DestReg) -+ MIB.addReg(DestReg, RegState::Define); -+ -+ if (SrcReg) -+ MIB.addReg(SrcReg, getKillRegState(KillSrc)); -+ -+ if (ZeroReg) -+ MIB.addReg(ZeroReg); - -- BuildMI(MBB, MBBI, DL, get(Opc), DstReg) -- .addReg(SrcReg, getKillRegState(KillSrc)); -+ if (!ZeroImm) -+ MIB.addImm(0); -+} -+ -+static bool isORCopyInst(const MachineInstr &MI) { -+ switch (MI.getOpcode()) { -+ default: -+ break; -+ case LoongArch::OR: -+ if (MI.getOperand(2).getReg() == LoongArch::ZERO_64) -+ return true; -+ break; -+ case LoongArch::OR32: -+ if (MI.getOperand(2).getReg() == LoongArch::ZERO) -+ return true; -+ break; -+ } -+ return false; -+} -+ -+/// We check for the common case of 'or', as it's LoongArch' preferred instruction -+/// for GPRs but we have to check the operands to ensure that is the case. -+/// Other move instructions for LoongArch are directly identifiable. -+Optional -+LoongArchInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const { -+ if (MI.isMoveReg() || isORCopyInst(MI)) { -+ return DestSourcePair{MI.getOperand(0), MI.getOperand(1)}; -+ } -+ return None; - } - --void LoongArchInstrInfo::storeRegToStackSlot( -- MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg, -- bool IsKill, int FI, const TargetRegisterClass *RC, -- const TargetRegisterInfo *TRI) const { -+void LoongArchInstrInfo:: -+storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, -+ Register SrcReg, bool isKill, int FI, -+ const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, -+ int64_t Offset) const { - DebugLoc DL; -- if (I != MBB.end()) -- DL = I->getDebugLoc(); -- MachineFunction *MF = MBB.getParent(); -- MachineFrameInfo &MFI = MF->getFrameInfo(); -- -- unsigned Opcode; -- if (LoongArch::GPRRegClass.hasSubClassEq(RC)) -- Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 -- ? LoongArch::ST_W -- : LoongArch::ST_D; -- else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) -- Opcode = LoongArch::FST_S; -- else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) -- Opcode = LoongArch::FST_D; -- else -- llvm_unreachable("Can't store this register to stack slot"); -+ MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); - -- MachineMemOperand *MMO = MF->getMachineMemOperand( -- MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, -- MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); -+ unsigned Opc = 0; -+ if (LoongArch::GPR32RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::ST_W; -+ else if (LoongArch::GPR64RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::ST_D; -+ else if (LoongArch::FGR64RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::FST_D; -+ else if (LoongArch::FGR32RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::FST_S; - -- BuildMI(MBB, I, DL, get(Opcode)) -- .addReg(SrcReg, getKillRegState(IsKill)) -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) -+ Opc = LoongArch::VST; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16)) -+ Opc = LoongArch::VST_H; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || -+ TRI->isTypeLegalForClass(*RC, MVT::v4f32)) -+ Opc = LoongArch::VST_W; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || -+ TRI->isTypeLegalForClass(*RC, MVT::v2f64)) -+ Opc = LoongArch::VST_D; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v32i8)) -+ Opc = LoongArch::XVST; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i16)) -+ Opc = LoongArch::XVST_H; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i32) || -+ TRI->isTypeLegalForClass(*RC, MVT::v8f32)) -+ Opc = LoongArch::XVST_W; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i64) || -+ TRI->isTypeLegalForClass(*RC, MVT::v4f64)) -+ Opc = LoongArch::XVST_D; -+ -+ assert(Opc && "Register class not handled!"); -+ BuildMI(MBB, I, DL, get(Opc)) -+ .addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI) -- .addImm(0) -+ .addImm(Offset) - .addMemOperand(MMO); - } - --void LoongArchInstrInfo::loadRegFromStackSlot( -- MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DstReg, -- int FI, const TargetRegisterClass *RC, -- const TargetRegisterInfo *TRI) const { -+void LoongArchInstrInfo:: -+loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, -+ Register DestReg, int FI, const TargetRegisterClass *RC, -+ const TargetRegisterInfo *TRI, int64_t Offset) const { - DebugLoc DL; - if (I != MBB.end()) - DL = I->getDebugLoc(); -- MachineFunction *MF = MBB.getParent(); -- MachineFrameInfo &MFI = MF->getFrameInfo(); -- -- unsigned Opcode; -- if (LoongArch::GPRRegClass.hasSubClassEq(RC)) -- Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 -- ? LoongArch::LD_W -- : LoongArch::LD_D; -- else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) -- Opcode = LoongArch::FLD_S; -- else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) -- Opcode = LoongArch::FLD_D; -- else -- llvm_unreachable("Can't load this register from stack slot"); -+ MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); -+ unsigned Opc = 0; - -- MachineMemOperand *MMO = MF->getMachineMemOperand( -- MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, -- MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); -+ if (LoongArch::GPR32RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::LD_W; -+ else if (LoongArch::GPR64RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::LD_D; -+ else if (LoongArch::FGR32RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::FLD_S; -+ else if (LoongArch::FGR64RegClass.hasSubClassEq(RC)) -+ Opc = LoongArch::FLD_D; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) -+ Opc = LoongArch::VLD; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16)) -+ Opc = LoongArch::VLD_H; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || -+ TRI->isTypeLegalForClass(*RC, MVT::v4f32)) -+ Opc = LoongArch::VLD_W; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || -+ TRI->isTypeLegalForClass(*RC, MVT::v2f64)) -+ Opc = LoongArch::VLD_D; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v32i8)) -+ Opc = LoongArch::XVLD; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i16)) -+ Opc = LoongArch::XVLD_H; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i32) || -+ TRI->isTypeLegalForClass(*RC, MVT::v8f32)) -+ Opc = LoongArch::XVLD_W; -+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i64) || -+ TRI->isTypeLegalForClass(*RC, MVT::v4f64)) -+ Opc = LoongArch::XVLD_D; - -- BuildMI(MBB, I, DL, get(Opcode), DstReg) -+ assert(Opc && "Register class not handled!"); -+ -+ BuildMI(MBB, I, DL, get(Opc), DestReg) - .addFrameIndex(FI) -- .addImm(0) -+ .addImm(Offset) - .addMemOperand(MMO); - } -+ -+bool LoongArchInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { -+ MachineBasicBlock &MBB = *MI.getParent(); -+ switch (MI.getDesc().getOpcode()) { -+ default: -+ return false; -+ case LoongArch::RetRA: -+ expandRetRA(MBB, MI); -+ break; -+ case LoongArch::ERet: -+ expandERet(MBB, MI); -+ break; -+ case LoongArch::PseudoFFINT_S_W: -+ expandCvtFPInt(MBB, MI, LoongArch::FFINT_S_W, LoongArch::MOVGR2FR_W, false); -+ break; -+ case LoongArch::PseudoFFINT_S_L: -+ expandCvtFPInt(MBB, MI, LoongArch::FFINT_S_L, LoongArch::MOVGR2FR_D, true); -+ break; -+ case LoongArch::PseudoFFINT_D_W: -+ expandCvtFPInt(MBB, MI, LoongArch::FFINT_D_W, LoongArch::MOVGR2FR_W, true); -+ break; -+ case LoongArch::PseudoFFINT_D_L: -+ expandCvtFPInt(MBB, MI, LoongArch::FFINT_D_L, LoongArch::MOVGR2FR_D, true); -+ break; -+ case LoongArch::LoongArcheh_return32: -+ case LoongArch::LoongArcheh_return64: -+ expandEhReturn(MBB, MI); -+ break; -+ } -+ -+ MBB.erase(MI); -+ return true; -+} -+ -+/// getOppositeBranchOpc - Return the inverse of the specified -+/// opcode, e.g. turning BEQ to BNE. -+unsigned LoongArchInstrInfo::getOppositeBranchOpc(unsigned Opc) const { -+ switch (Opc) { -+ default: llvm_unreachable("Illegal opcode!"); -+ case LoongArch::BEQ32: return LoongArch::BNE32; -+ case LoongArch::BEQ: return LoongArch::BNE; -+ case LoongArch::BNE32: return LoongArch::BEQ32; -+ case LoongArch::BNE: return LoongArch::BEQ; -+ case LoongArch::BEQZ32: return LoongArch::BNEZ32; -+ case LoongArch::BEQZ: return LoongArch::BNEZ; -+ case LoongArch::BNEZ32: return LoongArch::BEQZ32; -+ case LoongArch::BNEZ: return LoongArch::BEQZ; -+ case LoongArch::BCEQZ: return LoongArch::BCNEZ; -+ case LoongArch::BCNEZ: return LoongArch::BCEQZ; -+ case LoongArch::BLT32: return LoongArch::BGE32; -+ case LoongArch::BLT: return LoongArch::BGE; -+ case LoongArch::BGE32: return LoongArch::BLT32; -+ case LoongArch::BGE: return LoongArch::BLT; -+ case LoongArch::BLTU32: return LoongArch::BGEU32; -+ case LoongArch::BLTU: return LoongArch::BGEU; -+ case LoongArch::BGEU32: return LoongArch::BLTU32; -+ case LoongArch::BGEU: return LoongArch::BLTU; -+ } -+} -+ -+void LoongArchInstrInfo::adjustReg(unsigned DestReg, unsigned SrcReg, -+ int64_t Amount, MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I, -+ MachineInstr::MIFlag Flag) const { -+ LoongArchABIInfo ABI = Subtarget.getABI(); -+ DebugLoc DL; -+ unsigned ADDI = ABI.GetPtrAddiOp(); -+ -+ if (Amount == 0) -+ return; -+ -+ if (isInt<12>(Amount)) { -+ // addi $DestReg, $SrcReg, amount -+ BuildMI(MBB, I, DL, get(ADDI), DestReg) -+ .addReg(SrcReg) -+ .addImm(Amount) -+ .setMIFlag(Flag); -+ } else { -+ // For numbers which are not 12bit integers we synthesize Amount inline -+ // then add or subtract it from $SrcReg. -+ unsigned Opc = ABI.GetPtrAddOp(); -+ if (Amount < 0) { -+ Opc = ABI.GetPtrSubOp(); -+ Amount = -Amount; -+ } -+ unsigned Reg = loadImmediate(Amount, MBB, I, DL); -+ BuildMI(MBB, I, DL, get(Opc), DestReg) -+ .addReg(SrcReg) -+ .addReg(Reg, RegState::Kill) -+ .setMIFlag(Flag); -+ } -+} -+ -+/// This function generates the sequence of instructions needed to get the -+/// result of adding register REG and immediate IMM. -+unsigned LoongArchInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator II, -+ const DebugLoc &DL) const { -+ const TargetRegisterClass *RC = Subtarget.isABI_LP64() -+ ? &LoongArch::GPR64RegClass -+ : &LoongArch::GPR32RegClass; -+ LoongArchAnalyzeImmediate::InstSeq Seq = -+ LoongArchAnalyzeImmediate::generateInstSeq(Imm, Subtarget.is64Bit()); -+ unsigned DstReg = MBB.getParent()->getRegInfo().createVirtualRegister(RC); -+ unsigned SrcReg = -+ Subtarget.isABI_LP64() ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ -+ // Build the instructions in Seq. -+ for (auto &Inst : Seq) { -+ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) -+ BuildMI(MBB, II, DL, get(Inst.Opc), DstReg).addImm(Inst.Imm); -+ else -+ BuildMI(MBB, II, DL, get(Inst.Opc), DstReg) -+ .addReg(SrcReg, RegState::Kill) -+ .addImm(Inst.Imm); -+ SrcReg = DstReg; -+ } -+ return DstReg; -+} -+ -+unsigned LoongArchInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { -+ return (Opc == LoongArch::B || Opc == LoongArch::B32 || -+ Opc == LoongArch::BEQZ || Opc == LoongArch::BEQZ32 || -+ Opc == LoongArch::BNEZ || Opc == LoongArch::BNEZ32 || -+ Opc == LoongArch::BCEQZ || -+ Opc == LoongArch::BCNEZ || -+ Opc == LoongArch::BEQ || Opc == LoongArch::BEQ32 || -+ Opc == LoongArch::BNE || Opc == LoongArch::BNE32 || -+ Opc == LoongArch::BLT || Opc == LoongArch::BLT32 || -+ Opc == LoongArch::BGE || Opc == LoongArch::BGE32 || -+ Opc == LoongArch::BLTU || Opc == LoongArch::BLTU32 || -+ Opc == LoongArch::BGEU || Opc == LoongArch::BGEU32) ? Opc : 0; -+} -+ -+void LoongArchInstrInfo::expandRetRA(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const { -+ -+ MachineInstrBuilder MIB; -+ -+ if (Subtarget.is64Bit()) -+ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::PseudoReturn64)) -+ .addReg(LoongArch::RA_64, RegState::Undef); -+ else -+ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::PseudoReturn)) -+ .addReg(LoongArch::RA, RegState::Undef); -+ -+ // Retain any imp-use flags. -+ for (auto & MO : I->operands()) { -+ if (MO.isImplicit()) -+ MIB.add(MO); -+ } -+} -+ -+void LoongArchInstrInfo::expandERet(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const { -+ BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::ERTN)); -+} -+ -+std::pair -+LoongArchInstrInfo::compareOpndSize(unsigned Opc, -+ const MachineFunction &MF) const { -+ const MCInstrDesc &Desc = get(Opc); -+ assert(Desc.NumOperands == 2 && "Unary instruction expected."); -+ const LoongArchRegisterInfo *RI = &getRegisterInfo(); -+ unsigned DstRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 0, RI, MF)); -+ unsigned SrcRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 1, RI, MF)); -+ -+ return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize); -+} -+ -+void LoongArchInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I, -+ unsigned CvtOpc, unsigned MovOpc, -+ bool IsI64) const { -+ const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc); -+ const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1); -+ unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg; -+ unsigned KillSrc = getKillRegState(Src.isKill()); -+ DebugLoc DL = I->getDebugLoc(); -+ bool DstIsLarger, SrcIsLarger; -+ -+ std::tie(DstIsLarger, SrcIsLarger) = -+ compareOpndSize(CvtOpc, *MBB.getParent()); -+ -+ if (DstIsLarger) -+ TmpReg = getRegisterInfo().getSubReg(DstReg, LoongArch::sub_lo); -+ -+ if (SrcIsLarger) -+ DstReg = getRegisterInfo().getSubReg(DstReg, LoongArch::sub_lo); -+ -+ BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc); -+ BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill); -+} -+ -+void LoongArchInstrInfo::expandEhReturn(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const { -+ // This pseudo instruction is generated as part of the lowering of -+ // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and -+ // indirect jump to TargetReg -+ LoongArchABIInfo ABI = Subtarget.getABI(); -+ unsigned ADD = ABI.GetPtrAddOp(); -+ unsigned SP = Subtarget.is64Bit() ? LoongArch::SP_64 : LoongArch::SP; -+ unsigned RA = Subtarget.is64Bit() ? LoongArch::RA_64 : LoongArch::RA; -+ unsigned T8 = Subtarget.is64Bit() ? LoongArch::T8_64 : LoongArch::T8; -+ unsigned ZERO = Subtarget.is64Bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ unsigned OffsetReg = I->getOperand(0).getReg(); -+ unsigned TargetReg = I->getOperand(1).getReg(); -+ -+ // add $ra, $v0, $zero -+ // add $sp, $sp, $v1 -+ // jr $ra (via RetRA) -+ const TargetMachine &TM = MBB.getParent()->getTarget(); -+ if (TM.isPositionIndependent()) -+ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), T8) -+ .addReg(TargetReg) -+ .addReg(ZERO); -+ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), RA) -+ .addReg(TargetReg) -+ .addReg(ZERO); -+ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), SP).addReg(SP).addReg(OffsetReg); -+ expandRetRA(MBB, I); -+} -+ -+ -+bool LoongArchInstrInfo::isZeroImm(const MachineOperand &op) const { -+ return op.isImm() && op.getImm() == 0; -+} -+ -+/// insertNoop - If data hazard condition is found insert the target nop -+/// instruction. -+// FIXME: This appears to be dead code. -+void LoongArchInstrInfo:: -+insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const -+{ -+ DebugLoc DL; -+ BuildMI(MBB, MI, DL, get(LoongArch::NOP)); -+} -+ -+MachineMemOperand * -+LoongArchInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, -+ MachineMemOperand::Flags Flags) const { -+ MachineFunction &MF = *MBB.getParent(); -+ MachineFrameInfo &MFI = MF.getFrameInfo(); -+ -+ return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), -+ Flags, MFI.getObjectSize(FI), -+ MFI.getObjectAlign(FI)); -+} -+ -+//===----------------------------------------------------------------------===// -+// Branch Analysis -+//===----------------------------------------------------------------------===// -+ -+void LoongArchInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, -+ MachineBasicBlock *&BB, -+ SmallVectorImpl &Cond) const { -+ assert(getAnalyzableBrOpc(Opc) && "Not an analyzable branch"); -+ int NumOp = Inst->getNumExplicitOperands(); -+ -+ // for both int and fp branches, the last explicit operand is the -+ // MBB. -+ BB = Inst->getOperand(NumOp-1).getMBB(); -+ Cond.push_back(MachineOperand::CreateImm(Opc)); -+ -+ for (int i = 0; i < NumOp-1; i++) -+ Cond.push_back(Inst->getOperand(i)); -+} -+ -+bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB, -+ MachineBasicBlock *&TBB, -+ MachineBasicBlock *&FBB, -+ SmallVectorImpl &Cond, -+ bool AllowModify) const { -+ SmallVector BranchInstrs; -+ BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); -+ -+ return (BT == BT_None) || (BT == BT_Indirect); -+} -+ -+MachineInstr * -+LoongArchInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, -+ const DebugLoc &DL, -+ ArrayRef Cond) const { -+ unsigned Opc = Cond[0].getImm(); -+ const MCInstrDesc &MCID = get(Opc); -+ MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); -+ -+ for (unsigned i = 1; i < Cond.size(); ++i) { -+ assert((Cond[i].isImm() || Cond[i].isReg()) && -+ "Cannot copy operand for conditional branch!"); -+ MIB.add(Cond[i]); -+ } -+ MIB.addMBB(TBB); -+ return MIB.getInstr(); -+} -+ -+unsigned LoongArchInstrInfo::insertBranch(MachineBasicBlock &MBB, -+ MachineBasicBlock *TBB, -+ MachineBasicBlock *FBB, -+ ArrayRef Cond, -+ const DebugLoc &DL, -+ int *BytesAdded) const { -+ unsigned UncondBrOpc = LoongArch::B; -+ // Shouldn't be a fall through. -+ assert(TBB && "insertBranch must not be told to insert a fallthrough"); -+ if (BytesAdded) -+ *BytesAdded = 0; -+ -+ // # of condition operands: -+ // Unconditional branches: 0 -+ // Floating point branches: 1 (opc) -+ // Int BranchZero: 2 (opc, reg) -+ // Int Branch: 3 (opc, reg0, reg1) -+ assert((Cond.size() <= 3) && -+ "# of LoongArch branch conditions must be <= 3!"); -+ -+ // Two-way Conditional branch. -+ if (FBB) { -+ MachineInstr &MI1 = *BuildCondBr(MBB, TBB, DL, Cond); -+ if (BytesAdded) -+ *BytesAdded += getInstSizeInBytes(MI1); -+ MachineInstr &MI2 = *BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB); -+ if (BytesAdded) -+ *BytesAdded += getInstSizeInBytes(MI2); -+ return 2; -+ } -+ -+ // One way branch. -+ // Unconditional branch. -+ if (Cond.empty()) { -+ MachineInstr &MI = *BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB); -+ if (BytesAdded) -+ *BytesAdded += getInstSizeInBytes(MI); -+ } -+ else {// Conditional branch. -+ MachineInstr &MI = *BuildCondBr(MBB, TBB, DL, Cond); -+ if (BytesAdded) -+ *BytesAdded += getInstSizeInBytes(MI); -+ } -+ return 1; -+} -+ -+void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, -+ MachineBasicBlock &DestBB, -+ MachineBasicBlock &RestoreBB, -+ const DebugLoc &DL, -+ int64_t BrOffset, -+ RegScavenger *RS) const { -+ assert(RS && "RegScavenger required for long branching"); -+ assert(MBB.empty() && -+ "new block should be inserted for expanding unconditional branch"); -+ assert(MBB.pred_size() == 1); -+ -+ MachineFunction *MF = MBB.getParent(); -+ MachineRegisterInfo &MRI = MF->getRegInfo(); -+ const LoongArchSubtarget &Subtarget = MF->getSubtarget(); -+ bool is64 = Subtarget.isABI_LP64(); -+ const TargetRegisterClass *RC = -+ is64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ -+ if (!is64 && !isInt<32>(BrOffset)) -+ report_fatal_error( -+ "Branch offsets outside of the signed 32-bit range not supported"); -+ -+ unsigned ScratchReg = MRI.createVirtualRegister(RC); -+ unsigned ZeroReg = is64 ? LoongArch::ZERO_64 : LoongArch::ZERO; -+ auto II = MBB.end(); -+ -+ MachineInstr &Pcaddu12iMI = -+ *BuildMI(MBB, II, DL, get(LoongArch::LONG_BRANCH_PCADDU12I), ScratchReg) -+ .addMBB(&DestBB, LoongArchII::MO_PCREL_HI); -+ BuildMI(MBB, II, DL, get(LoongArch::LONG_BRANCH_ADDID2Op), ScratchReg) -+ .addReg(ScratchReg) -+ .addMBB(&DestBB, LoongArchII::MO_PCREL_LO); -+ BuildMI(MBB, II, DL, get(LoongArch::JIRL)) -+ .addReg(ZeroReg) -+ .addReg(ScratchReg, RegState::Kill) -+ .addImm(0); -+ RS->enterBasicBlockEnd(MBB); -+ unsigned Scav = RS->scavengeRegisterBackwards( -+ *RC, MachineBasicBlock::iterator(Pcaddu12iMI), false, 0); -+ MRI.replaceRegWith(ScratchReg, Scav); -+ MRI.clearVirtRegs(); -+ RS->setRegUsed(Scav); -+} -+ -+unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, -+ int *BytesRemoved) const { -+ if (BytesRemoved) -+ *BytesRemoved = 0; -+ -+ MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); -+ unsigned removed = 0; -+ -+ // Up to 2 branches are removed. -+ // Note that indirect branches are not removed. -+ while (I != REnd && removed < 2) { -+ // Skip past debug instructions. -+ if (I->isDebugInstr()) { -+ ++I; -+ continue; -+ } -+ if (!getAnalyzableBrOpc(I->getOpcode())) -+ break; -+ // Remove the branch. -+ I->eraseFromParent(); -+ if (BytesRemoved) -+ *BytesRemoved += getInstSizeInBytes(*I); -+ I = MBB.rbegin(); -+ ++removed; -+ } -+ -+ return removed; -+} -+ -+/// reverseBranchCondition - Return the inverse opcode of the -+/// specified Branch instruction. -+bool LoongArchInstrInfo::reverseBranchCondition( -+ SmallVectorImpl &Cond) const { -+ assert( (Cond.size() && Cond.size() <= 3) && -+ "Invalid LoongArch branch condition!"); -+ Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); -+ return false; -+} -+ -+LoongArchInstrInfo::BranchType LoongArchInstrInfo::analyzeBranch( -+ MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, -+ SmallVectorImpl &Cond, bool AllowModify, -+ SmallVectorImpl &BranchInstrs) const { -+ MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); -+ -+ // Skip all the debug instructions. -+ while (I != REnd && I->isDebugInstr()) -+ ++I; -+ -+ if (I == REnd || !isUnpredicatedTerminator(*I)) { -+ // This block ends with no branches (it just falls through to its succ). -+ // Leave TBB/FBB null. -+ TBB = FBB = nullptr; -+ return BT_NoBranch; -+ } -+ -+ MachineInstr *LastInst = &*I; -+ unsigned LastOpc = LastInst->getOpcode(); -+ BranchInstrs.push_back(LastInst); -+ -+ // Not an analyzable branch (e.g., indirect jump). -+ if (!getAnalyzableBrOpc(LastOpc)) -+ return LastInst->isIndirectBranch() ? BT_Indirect : BT_None; -+ -+ // Get the second to last instruction in the block. -+ unsigned SecondLastOpc = 0; -+ MachineInstr *SecondLastInst = nullptr; -+ -+ // Skip past any debug instruction to see if the second last actual -+ // is a branch. -+ ++I; -+ while (I != REnd && I->isDebugInstr()) -+ ++I; -+ -+ if (I != REnd) { -+ SecondLastInst = &*I; -+ SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); -+ -+ // Not an analyzable branch (must be an indirect jump). -+ if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) -+ return BT_None; -+ } -+ -+ // If there is only one terminator instruction, process it. -+ if (!SecondLastOpc) { -+ // Unconditional branch. -+ if (LastInst->isUnconditionalBranch()) { -+ TBB = LastInst->getOperand(0).getMBB(); -+ return BT_Uncond; -+ } -+ -+ // Conditional branch -+ AnalyzeCondBr(LastInst, LastOpc, TBB, Cond); -+ return BT_Cond; -+ } -+ -+ // If we reached here, there are two branches. -+ // If there are three terminators, we don't know what sort of block this is. -+ if (++I != REnd && isUnpredicatedTerminator(*I)) -+ return BT_None; -+ -+ BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); -+ -+ // If second to last instruction is an unconditional branch, -+ // analyze it and remove the last instruction. -+ if (SecondLastInst->isUnconditionalBranch()) { -+ // Return if the last instruction cannot be removed. -+ if (!AllowModify) -+ return BT_None; -+ -+ TBB = SecondLastInst->getOperand(0).getMBB(); -+ LastInst->eraseFromParent(); -+ BranchInstrs.pop_back(); -+ return BT_Uncond; -+ } -+ -+ // Conditional branch followed by an unconditional branch. -+ // The last one must be unconditional. -+ if (!LastInst->isUnconditionalBranch()) -+ return BT_None; -+ -+ AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); -+ FBB = LastInst->getOperand(0).getMBB(); -+ -+ return BT_CondUncond; -+} -+ -+MachineBasicBlock * -+LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { -+ assert(MI.getDesc().isBranch() && "Unexpected opcode!"); -+ // The branch target is always the last operand. -+ int NumOp = MI.getNumExplicitOperands(); -+ return MI.getOperand(NumOp - 1).getMBB(); -+} -+ -+bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const { -+/* -+ switch (BranchOpc) { -+ case LoongArch::B: -+ case LoongArch::BAL: -+ case LoongArch::BAL_BR: -+ case LoongArch::BC1F: -+ case LoongArch::BC1FL: -+ case LoongArch::BC1T: -+ case LoongArch::BC1TL: -+ case LoongArch::BEQ: case LoongArch::BEQ64: -+ case LoongArch::BEQL: -+ case LoongArch::BGEZ: case LoongArch::BGEZ64: -+ case LoongArch::BGEZL: -+ case LoongArch::BGEZAL: -+ case LoongArch::BGEZALL: -+ case LoongArch::BGTZ: case LoongArch::BGTZ64: -+ case LoongArch::BGTZL: -+ case LoongArch::BLEZ: case LoongArch::BLEZ64: -+ case LoongArch::BLEZL: -+ case LoongArch::BLTZ: case LoongArch::BLTZ64: -+ case LoongArch::BLTZL: -+ case LoongArch::BLTZAL: -+ case LoongArch::BLTZALL: -+ case LoongArch::BNE: case LoongArch::BNE64: -+ case LoongArch::BNEL: -+ return isInt<18>(BrOffset); -+ -+ case LoongArch::BC1EQZ: -+ case LoongArch::BC1NEZ: -+ case LoongArch::BC2EQZ: -+ case LoongArch::BC2NEZ: -+ case LoongArch::BEQC: case LoongArch::BEQC64: -+ case LoongArch::BNEC: case LoongArch::BNEC64: -+ case LoongArch::BGEC: case LoongArch::BGEC64: -+ case LoongArch::BGEUC: case LoongArch::BGEUC64: -+ case LoongArch::BGEZC: case LoongArch::BGEZC64: -+ case LoongArch::BGTZC: case LoongArch::BGTZC64: -+ case LoongArch::BLEZC: case LoongArch::BLEZC64: -+ case LoongArch::BLTC: case LoongArch::BLTC64: -+ case LoongArch::BLTUC: case LoongArch::BLTUC64: -+ case LoongArch::BLTZC: case LoongArch::BLTZC64: -+ case LoongArch::BNVC: -+ case LoongArch::BOVC: -+ case LoongArch::BGEZALC: -+ case LoongArch::BEQZALC: -+ case LoongArch::BGTZALC: -+ case LoongArch::BLEZALC: -+ case LoongArch::BLTZALC: -+ case LoongArch::BNEZALC: -+ return isInt<18>(BrOffset); -+ -+ case LoongArch::BEQZC: case LoongArch::BEQZC64: -+ case LoongArch::BNEZC: case LoongArch::BNEZC64: -+ return isInt<23>(BrOffset); -+ } -+ */ -+ switch (BranchOpc) { -+ case LoongArch::B: case LoongArch::B32: -+ return isInt<28>(BrOffset); -+ -+ case LoongArch::BEQZ: case LoongArch::BEQZ32: -+ case LoongArch::BNEZ: case LoongArch::BNEZ32: -+ case LoongArch::BCEQZ: -+ case LoongArch::BCNEZ: -+ return isInt<23>(BrOffset); -+ -+ case LoongArch::BEQ: case LoongArch::BEQ32: -+ case LoongArch::BNE: case LoongArch::BNE32: -+ case LoongArch::BLT: case LoongArch::BLT32: -+ case LoongArch::BGE: case LoongArch::BGE32: -+ case LoongArch::BLTU: case LoongArch::BLTU32: -+ case LoongArch::BGEU: case LoongArch::BGEU32: -+ return isInt<18>(BrOffset); -+ } -+ -+ llvm_unreachable("Unknown branch instruction!"); -+} -+ -+ -+/// Predicate for distingushing between control transfer instructions and all -+/// other instructions for handling forbidden slots. Consider inline assembly -+/// as unsafe as well. -+bool LoongArchInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { -+ if (MI.isInlineAsm()) -+ return false; -+ -+ return (MI.getDesc().TSFlags & LoongArchII::IsCTI) == 0; -+} -+ -+/// Predicate for distingushing instructions that have forbidden slots. -+bool LoongArchInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { -+ return (MI.getDesc().TSFlags & LoongArchII::HasForbiddenSlot) != 0; -+} -+ -+/// Return the number of bytes of code the specified instruction may be. -+unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { -+ switch (MI.getOpcode()) { -+ default: -+ return MI.getDesc().getSize(); -+ case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. -+ const MachineFunction *MF = MI.getParent()->getParent(); -+ const char *AsmStr = MI.getOperand(0).getSymbolName(); -+ return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); -+ } -+ } -+} -+ -+MachineInstrBuilder -+LoongArchInstrInfo::genInstrWithNewOpc(unsigned NewOpc, -+ MachineBasicBlock::iterator I) const { -+ MachineInstrBuilder MIB; -+ -+ int ZeroOperandPosition = -1; -+ bool BranchWithZeroOperand = false; -+ if (I->isBranch() && !I->isPseudo()) { -+ auto TRI = I->getParent()->getParent()->getSubtarget().getRegisterInfo(); -+ ZeroOperandPosition = I->findRegisterUseOperandIdx(LoongArch::ZERO, false, TRI); -+ BranchWithZeroOperand = ZeroOperandPosition != -1; -+ } -+ -+ MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); -+ -+ if (NewOpc == LoongArch::JIRL) { -+ MIB->removeOperand(0); -+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { -+ MIB.add(I->getOperand(J)); -+ } -+ MIB.addImm(0); -+ } else { -+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { -+ if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) -+ continue; -+ -+ MIB.add(I->getOperand(J)); -+ } -+ } -+ -+ MIB.copyImplicitOps(*I); -+ MIB.cloneMemRefs(*I); -+ return MIB; -+} -+ -+bool LoongArchInstrInfo::findCommutedOpIndices(const MachineInstr &MI, -+ unsigned &SrcOpIdx1, -+ unsigned &SrcOpIdx2) const { -+ assert(!MI.isBundle() && -+ "TargetInstrInfo::findCommutedOpIndices() can't handle bundles"); -+ -+ const MCInstrDesc &MCID = MI.getDesc(); -+ if (!MCID.isCommutable()) -+ return false; -+ -+ return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); -+} -+ -+// bstrins, bstrpick have the following constraints: -+// 0 <= lsb <= msb <= High -+static bool verifyBstrInstruction(const MachineInstr &MI, StringRef &ErrInfo, -+ const int64_t High) { -+ MachineOperand MOMsb = MI.getOperand(2); -+ if (!MOMsb.isImm()) { -+ ErrInfo = "Msb operand is not an immediate!"; -+ return false; -+ } -+ MachineOperand MOLsb = MI.getOperand(3); -+ if (!MOLsb.isImm()) { -+ ErrInfo = "Lsb operand is not an immediate!"; -+ return false; -+ } -+ -+ int64_t Lsb = MOLsb.getImm(); -+ if (!((0 <= Lsb) && (Lsb <= High))) { -+ ErrInfo = "Lsb operand is out of range!"; -+ return false; -+ } -+ -+ int64_t Msb = MOMsb.getImm(); -+ if (!((0 <= Msb) && (Msb <= High))) { -+ ErrInfo = "Msb operand is out of range!"; -+ return false; -+ } -+ -+ if (!(Lsb <= Msb)) { -+ ErrInfo = "Lsb operand is not less than or equal to msb operand!"; -+ return false; -+ } -+ -+ return true; -+} -+ -+// Perform target specific instruction verification. -+bool LoongArchInstrInfo::verifyInstruction(const MachineInstr &MI, -+ StringRef &ErrInfo) const { -+ // Verify that bstrins and bstrpick instructions are well formed. -+ switch (MI.getOpcode()) { -+ case LoongArch::BSTRINS_W: -+ case LoongArch::BSTRPICK_W: -+ return verifyBstrInstruction(MI, ErrInfo, 31); -+ case LoongArch::BSTRINS_D: -+ case LoongArch::BSTRPICK_D: -+ return verifyBstrInstruction(MI, ErrInfo, 63); -+ default: -+ return true; -+ } -+ -+ return true; -+} -+ -+std::pair -+LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { -+ return std::make_pair(TF, 0u); -+} -+ -+ArrayRef> -+LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { -+ using namespace LoongArchII; -+ -+ static const std::pair Flags[] = { -+ {MO_PCREL_HI, "larch-pcrel-hi"}, -+ {MO_PCREL_LO, "larch-pcrel-lo"}, -+ {MO_TLSGD_HI, "larch-tlsgd-hi"}, -+ {MO_TLSGD_LO, "larch-tlsgd-lo"}, -+ {MO_TLSIE_HI, "larch-tlsie-hi"}, -+ {MO_TLSIE_LO, "larch-tlsie-lo"}, -+ {MO_TLSLE_HI, "larch-tlsle-hi"}, -+ {MO_TLSLE_LO, "larch-tlsle-lo"}, -+ {MO_ABS_HI, "larch-abs-hi"}, -+ {MO_ABS_LO, "larch-abs-lo"}, -+ {MO_ABS_HIGHER, "larch-abs-higher"}, -+ {MO_ABS_HIGHEST, "larch-abs-highest"}, -+ {MO_GOT_HI, "larch-got-hi"}, -+ {MO_GOT_LO, "larch-got-lo"}, -+ {MO_CALL_HI, "larch-call-hi"}, -+ {MO_CALL_LO, "larch-call-lo"} -+ }; -+ return makeArrayRef(Flags); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h -index 0a8c86a5e..53191a94d 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h -@@ -1,4 +1,4 @@ --//=- LoongArchInstrInfo.h - LoongArch Instruction Information ---*- C++ -*-===// -+//===- LoongArchInstrInfo.h - LoongArch Instruction Information -----------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -8,39 +8,239 @@ - // - // This file contains the LoongArch implementation of the TargetInstrInfo class. - // -+// FIXME: We need to override TargetInstrInfo::getInlineAsmLength method in -+// order for LoongArchLongBranch pass to work correctly when the code has inline -+// assembly. The returned value doesn't have to be the asm instruction's exact -+// size in bytes; LoongArchLongBranch only expects it to be the correct upper bound. - //===----------------------------------------------------------------------===// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H - -+#define DBAR_HINT 0x700 -+ -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "LoongArch.h" - #include "LoongArchRegisterInfo.h" -+#include "llvm/ADT/ArrayRef.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" -+#include "llvm/CodeGen/MachineInstrBuilder.h" -+#include "llvm/CodeGen/MachineMemOperand.h" - #include "llvm/CodeGen/TargetInstrInfo.h" -+#include - - #define GET_INSTRINFO_HEADER - #include "LoongArchGenInstrInfo.inc" - - namespace llvm { - -+class MachineInstr; -+class MachineOperand; - class LoongArchSubtarget; -+class TargetRegisterClass; -+class TargetRegisterInfo; - - class LoongArchInstrInfo : public LoongArchGenInstrInfo { -+ virtual void anchor(); -+ const LoongArchRegisterInfo RI; -+ const LoongArchSubtarget &Subtarget; -+ - public: -- explicit LoongArchInstrInfo(LoongArchSubtarget &STI); -+ enum BranchType { -+ BT_None, // Couldn't analyze branch. -+ BT_NoBranch, // No branches found. -+ BT_Uncond, // One unconditional branch. -+ BT_Cond, // One conditional branch. -+ BT_CondUncond, // A conditional branch followed by an unconditional branch. -+ BT_Indirect // One indirct branch. -+ }; -+ -+ explicit LoongArchInstrInfo(const LoongArchSubtarget &STI); - -- void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, -- const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, -+ /// isLoadFromStackSlot - If the specified machine instruction is a direct -+ /// load from a stack slot, return the virtual or physical register number of -+ /// the destination along with the FrameIndex of the loaded stack slot. If -+ /// not, return 0. This predicate must return 0 if the instruction has -+ /// any side effects other than loading from the stack slot. -+ unsigned isLoadFromStackSlot(const MachineInstr &MI, -+ int &FrameIndex) const override; -+ -+ /// isStoreToStackSlot - If the specified machine instruction is a direct -+ /// store to a stack slot, return the virtual or physical register number of -+ /// the source reg along with the FrameIndex of the loaded stack slot. If -+ /// not, return 0. This predicate must return 0 if the instruction has -+ /// any side effects other than storing to the stack slot. -+ unsigned isStoreToStackSlot(const MachineInstr &MI, -+ int &FrameIndex) const override; -+ -+ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, -+ const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, - bool KillSrc) const override; - -+ /// Branch Analysis -+ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, -+ MachineBasicBlock *&FBB, -+ SmallVectorImpl &Cond, -+ bool AllowModify) const override; -+ -+ unsigned removeBranch(MachineBasicBlock &MBB, -+ int *BytesRemoved = nullptr) const override; -+ -+ unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, -+ MachineBasicBlock *FBB, ArrayRef Cond, -+ const DebugLoc &DL, -+ int *BytesAdded = nullptr) const override; -+ -+ void insertIndirectBranch(MachineBasicBlock &MBB, -+ MachineBasicBlock &NewDestBB, -+ MachineBasicBlock &RestoreBB, const DebugLoc &DL, -+ int64_t BrOffset, -+ RegScavenger *RS = nullptr) const override; -+ bool -+ reverseBranchCondition(SmallVectorImpl &Cond) const override; -+ -+ BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, -+ MachineBasicBlock *&FBB, -+ SmallVectorImpl &Cond, -+ bool AllowModify, -+ SmallVectorImpl &BranchInstrs) const; -+ -+ /// Get the block that branch instruction jumps to. -+ MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; -+ -+ /// Determine if the branch target is in range. -+ bool isBranchOffsetInRange(unsigned BranchOpc, -+ int64_t BrOffset) const override; -+ -+ /// Predicate to determine if an instruction can go in a forbidden slot. -+ bool SafeInForbiddenSlot(const MachineInstr &MI) const; -+ -+ /// Predicate to determine if an instruction has a forbidden slot. -+ bool HasForbiddenSlot(const MachineInstr &MI) const; -+ -+ /// Insert nop instruction when hazard condition is found -+ void insertNoop(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MI) const override; -+ -+ /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As -+ /// such, whenever a client has an instance of instruction info, it should -+ /// always be able to get register info as well (through this method). -+ const LoongArchRegisterInfo &getRegisterInfo() const; -+ -+ bool expandPostRAPseudo(MachineInstr &MI) const override; -+ -+ unsigned getOppositeBranchOpc(unsigned Opc) const; -+ -+ /// Emit a series of instructions to load an immediate. -+ unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator II, -+ const DebugLoc &DL) const; -+ -+ /// Return the number of bytes of code the specified instruction may be. -+ unsigned getInstSizeInBytes(const MachineInstr &MI) const override; -+ - void storeRegToStackSlot(MachineBasicBlock &MBB, -- MachineBasicBlock::iterator MBBI, Register SrcReg, -- bool IsKill, int FrameIndex, -+ MachineBasicBlock::iterator MBBI, -+ Register SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, -- const TargetRegisterInfo *TRI) const override; -+ const TargetRegisterInfo *TRI) const override { -+ storeRegToStack(MBB, MBBI, SrcReg, isKill, FrameIndex, RC, TRI, 0); -+ } -+ - void loadRegFromStackSlot(MachineBasicBlock &MBB, -- MachineBasicBlock::iterator MBBI, Register DstReg, -- int FrameIndex, const TargetRegisterClass *RC, -- const TargetRegisterInfo *TRI) const override; -+ MachineBasicBlock::iterator MBBI, -+ Register DestReg, int FrameIndex, -+ const TargetRegisterClass *RC, -+ const TargetRegisterInfo *TRI) const override { -+ loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0); -+ } -+ -+ void storeRegToStack(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MI, -+ Register SrcReg, bool isKill, int FrameIndex, -+ const TargetRegisterClass *RC, -+ const TargetRegisterInfo *TRI, -+ int64_t Offset) const; -+ -+ void loadRegFromStack(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator MI, -+ Register DestReg, int FrameIndex, -+ const TargetRegisterClass *RC, -+ const TargetRegisterInfo *TRI, -+ int64_t Offset) const; -+ -+ /// Adjust register value(DestReg = SrcReg + Amount). -+ void -+ adjustReg(unsigned DestReg, unsigned SrcReg, int64_t Amount, -+ MachineBasicBlock &MBB, MachineBasicBlock::iterator I, -+ MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags) const; -+ -+ /// Create an instruction which has the same operands and memory operands -+ /// as MI but has a new opcode. -+ MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, -+ MachineBasicBlock::iterator I) const; -+ -+ bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, -+ unsigned &SrcOpIdx2) const override; -+ -+ /// Perform target specific instruction verification. -+ bool verifyInstruction(const MachineInstr &MI, -+ StringRef &ErrInfo) const override; -+ -+ std::pair -+ decomposeMachineOperandsTargetFlags(unsigned TF) const override; -+ -+ ArrayRef> -+ getSerializableDirectMachineOperandTargetFlags() const override; -+ -+protected: -+ /// If the specific machine instruction is a instruction that moves/copies -+ /// value from one register to another register return true along with -+ /// @Source machine operand and @Destination machine operand. -+ Optional -+ isCopyInstrImpl(const MachineInstr &MI) const override; -+ -+private: -+ -+ bool isZeroImm(const MachineOperand &op) const; -+ -+ MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI, -+ MachineMemOperand::Flags Flags) const; -+ -+ unsigned getAnalyzableBrOpc(unsigned Opc) const; -+ -+ void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, -+ MachineBasicBlock *&BB, -+ SmallVectorImpl &Cond) const; -+ -+ MachineInstr * -+ BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, -+ const DebugLoc &DL, ArrayRef Cond) const; -+ -+ void expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; -+ -+ void expandERet(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; -+ -+ std::pair compareOpndSize(unsigned Opc, -+ const MachineFunction &MF) const; -+ -+ /// Expand pseudo Int-to-FP conversion instructions. -+ /// -+ /// For example, the following pseudo instruction -+ /// PseudoCVT_D32_W D2, A5 -+ /// gets expanded into these two instructions: -+ /// MTC1 F4, A5 -+ /// CVT_D32_W D2, F4 -+ /// -+ /// We do this expansion post-RA to avoid inserting a floating point copy -+ /// instruction between MTC1 and CVT_D32_W. -+ void expandCvtFPInt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, -+ unsigned CvtOpc, unsigned MovOpc, bool IsI64) const; -+ -+ void expandEhReturn(MachineBasicBlock &MBB, -+ MachineBasicBlock::iterator I) const; - }; - - } // end namespace llvm -+ - #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td -index d07d086bd..2d505ee25 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td -@@ -1,4 +1,4 @@ --//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-// -+//===- LoongArchInstrInfo.td - Target Description for LoongArch Target -*- tablegen -*-=// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,929 +6,1883 @@ - // - //===----------------------------------------------------------------------===// - // --// This file describes the LoongArch instructions in TableGen format. -+// This file contains the LoongArch implementation of the TargetInstrInfo class. - // - //===----------------------------------------------------------------------===// -+include "LoongArchInstrFormats.td" - --//===----------------------------------------------------------------------===// --// LoongArch specific DAG Nodes. --//===----------------------------------------------------------------------===// -+def SDT_Bstrpick : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, -+ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>; -+def SDT_Bstrins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, -+ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, -+ SDTCisSameAs<0, 4>]>; - --// Target-independent type requirements, but with target-specific formats. --def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, -- SDTCisVT<1, i32>]>; --def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, -- SDTCisVT<1, i32>]>; -- --// Target-dependent type requirements. --def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>; --def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [ -- SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> --]>; -- --def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [ -- SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>, -- SDTCisSameAs<3, 4> --]>; -- --def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [ -- SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3> --]>; -- --// TODO: Add LoongArch specific DAG Nodes --// Target-independent nodes, but with target-specific formats. --def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, -- [SDNPHasChain, SDNPOutGlue]>; --def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, -- [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; -- --// Target-dependent nodes. --def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall, -- [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, -- SDNPVariadic]>; --def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone, -- [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; --def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>; --def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>; --def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>; --def loongarch_bstrins -- : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>; --def loongarch_bstrpick -- : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>; -+def LoongArchBstrpick : SDNode<"LoongArchISD::BSTRPICK", SDT_Bstrpick>; - --//===----------------------------------------------------------------------===// --// Operand and SDNode transformation definitions. --//===----------------------------------------------------------------------===// -+def LoongArchBstrins : SDNode<"LoongArchISD::BSTRINS", SDT_Bstrins>; - --class ImmAsmOperand -- : AsmOperandClass { -- let Name = prefix # "Imm" # width # suffix; -- let DiagnosticType = !strconcat("Invalid", Name); -+def SDT_DBAR : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; -+def LoongArchDBAR : SDNode<"LoongArchISD::DBAR", SDT_DBAR, [SDNPHasChain,SDNPSideEffect]>; -+ -+def SDT_LoongArchEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>; -+ -+def LoongArchehret : SDNode<"LoongArchISD::EH_RETURN", SDT_LoongArchEHRET, -+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -+ -+//===---------------------------------------------------------------------===/ -+// Operand, Complex Patterns and Transformations Definitions. -+//===---------------------------------------------------------------------===/ -+ -+def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ -+ return cast(N->getOperand(1))->getVT().bitsLT(MVT::i32); -+}]>; -+ -+def immz : PatLeaf<(imm), [{ return N->getSExtValue() == 0; }]>; -+def immZExt12 : PatLeaf<(imm), [{ return isUInt<12>(N->getZExtValue()); }]>; -+def immSExt12 : PatLeaf<(imm), [{ return isInt<12>(N->getSExtValue()); }]>; -+def immSExt13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; -+ -+def immZExt2Alsl : ImmLeaf(Imm - 1);}]>; -+//class ImmAsmOperand : AsmOperandClass { -+// let RenderMethod = "addImmOperands"; -+// let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; -+// let DiagnosticString = "operand must be an immediate in the range [" # Low # "," # High # "]"; -+//} -+// -+//def Imm8AsmOperand: ImmAsmOperand<8,8> { let Name = "Imm8"; } -+//def imm8 : Operand, ImmLeaf { -+// let ParserMatchClass = Imm8AsmOperand; -+//} -+ -+def HasLSX : Predicate<"Subtarget->hasLSX()">, -+ AssemblerPredicate<(all_of FeatureLSX)>; -+def HasLASX : Predicate<"Subtarget->hasLASX()">, -+ AssemblerPredicate<(all_of FeatureLASX)>; -+ -+class EXT_LSX { -+ list ExtPredicate = [HasLSX]; -+} -+ -+class EXT_LASX { -+ list ExtPredicate = [HasLASX]; -+} -+ -+class SImmOperand : AsmOperandClass { -+ let Name = "SImm" # width; -+ let DiagnosticType = "InvalidSImm" # width; - let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isSImm<" # width # ">"; - } - --class SImmAsmOperand -- : ImmAsmOperand<"S", width, suffix> { -+def SImm2Operand : SImmOperand<2>; -+def simm2 : Operand, ImmLeaf= -2 && Imm < 2; }]> { -+ let ParserMatchClass = SImm2Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; -+} -+def SImm3Operand : SImmOperand<3>; -+def simm3 : Operand, ImmLeaf= -4 && Imm < 4; }]> { -+ let ParserMatchClass = SImm3Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<3>"; - } - --class UImmAsmOperand -- : ImmAsmOperand<"U", width, suffix> { -+def SImm5Operand : SImmOperand<5>; -+def simm5 : Operand, ImmLeaf= -16 && Imm < 16; }]> { -+ let ParserMatchClass = SImm5Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<5>"; - } - --def uimm2 : Operand { -- let ParserMatchClass = UImmAsmOperand<2>; -+def simm5_32 : Operand, ImmLeaf= -16 && Imm < 16; }]> { -+ let ParserMatchClass = SImm5Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<5>"; - } - --def uimm2_plus1 : Operand { -- let ParserMatchClass = UImmAsmOperand<2, "plus1">; -- let EncoderMethod = "getImmOpValueSub1"; -- let DecoderMethod = "decodeUImmOperand<2, 1>"; -+def SImm8Operand : SImmOperand<8>; -+def simm8 : Operand, ImmLeaf= -128 && Imm < 128; }]> { -+ let ParserMatchClass = SImm8Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; -+} -+def simm8_32 : Operand, ImmLeaf= -128 && Imm < 128; }]> { -+ let ParserMatchClass = SImm8Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; - } - --def uimm3 : Operand { -- let ParserMatchClass = UImmAsmOperand<3>; -+def SImm12Operand : SImmOperand<12>; -+def simm12 : Operand, ImmLeaf= -2048 && Imm < 2048; }]> { -+ let ParserMatchClass = SImm12Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; -+} -+def simm12_32 : Operand, ImmLeaf= -2048 && Imm < 2048; }]> { -+ let ParserMatchClass = SImm12Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; - } - --def uimm5 : Operand, ImmLeaf(Imm);}]> { -- let ParserMatchClass = UImmAsmOperand<5>; -+def SImm14Operand : SImmOperand<14>; -+def simm14 : Operand, ImmLeaf= -8192 && Imm < 8192; }]> { -+ let ParserMatchClass = SImm14Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<14>"; - } - --def uimm6 : Operand, ImmLeaf(Imm);}]> { -- let ParserMatchClass = UImmAsmOperand<6>; -+def SImm15Operand : SImmOperand<15>; -+def simm15 : Operand, ImmLeaf= -16384 && Imm < 16384; }]> { -+ let ParserMatchClass = SImm15Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<15>"; - } - --def uimm8 : Operand { -- let ParserMatchClass = UImmAsmOperand<8>; -+def SImm16Operand : SImmOperand<16>; -+def simm16 : Operand, ImmLeaf= -32768 && Imm < 32768; }]> { -+ let ParserMatchClass = SImm16Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; - } - --def uimm12 : Operand, ImmLeaf(Imm);}]> { -- let ParserMatchClass = UImmAsmOperand<12>; -+def SImm20Operand : SImmOperand<20>; -+def simm20 : Operand, ImmLeaf= -524288 && Imm < 524288; }]> { -+ let ParserMatchClass = SImm20Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<20>"; -+} -+def simm20_32 : Operand, ImmLeaf= -524288 && Imm < 524288; }]> { -+ let ParserMatchClass = SImm20Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<20>"; - } - --def uimm14 : Operand { -- let ParserMatchClass = UImmAsmOperand<14>; -+def SImm21Operand : SImmOperand<21>; -+def simm21 : Operand, ImmLeaf= -1048576 && Imm < 1048576; }]> { -+ let ParserMatchClass = SImm21Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<21>"; - } - --def uimm15 : Operand { -- let ParserMatchClass = UImmAsmOperand<15>; -+def SImm26Operand : SImmOperand<26>; -+def simm26 : Operand, ImmLeaf= -33554432 && Imm < 33554432; }]> { -+ let ParserMatchClass = SImm26Operand; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<26>"; - } - --def simm12 : Operand, ImmLeaf(Imm);}]> { -- let ParserMatchClass = SImmAsmOperand<12>; -- let DecoderMethod = "decodeSImmOperand<12>"; -+def UImm1Operand : AsmOperandClass { -+ let Name = "UImm1"; -+ let RenderMethod = "addUImmOperands<1>"; -+ let PredicateMethod = "isUImm<1>"; -+ let DiagnosticType = "InvalidImm0_1"; - } - --def simm14_lsl2 : Operand { -- let ParserMatchClass = SImmAsmOperand<14, "lsl2">; -- let EncoderMethod = "getImmOpValueAsr2"; -- let DecoderMethod = "decodeSImmOperand<14, 2>"; -+def UImm2Operand : AsmOperandClass { -+ let Name = "UImm2"; -+ let RenderMethod = "addUImmOperands<2>"; -+ let PredicateMethod = "isUImm<2>"; -+ let DiagnosticType = "InvalidImm0_3"; - } - --def simm16 : Operand { -- let ParserMatchClass = SImmAsmOperand<16>; -- let DecoderMethod = "decodeSImmOperand<16>"; -+def UImm3Operand : AsmOperandClass { -+ let Name = "UImm3"; -+ let RenderMethod = "addUImmOperands<3>"; -+ let PredicateMethod = "isUImm<3>"; -+ let DiagnosticType = "InvalidImm0_7"; - } - --def simm16_lsl2 : Operand, -- ImmLeaf(Imm>>2);}]> { -- let ParserMatchClass = SImmAsmOperand<16, "lsl2">; -- let EncoderMethod = "getImmOpValueAsr2"; -- let DecoderMethod = "decodeSImmOperand<16, 2>"; -+def UImm4Operand : AsmOperandClass { -+ let Name = "UImm4"; -+ let RenderMethod = "addUImmOperands<4>"; -+ let PredicateMethod = "isUImm<4>"; -+ let DiagnosticType = "InvalidImm0_15"; - } - --def simm16_lsl2_br : Operand { -- let ParserMatchClass = SImmAsmOperand<16, "lsl2">; -- let EncoderMethod = "getImmOpValueAsr2"; -- let DecoderMethod = "decodeSImmOperand<16, 2>"; -+def UImm5Operand : AsmOperandClass { -+ let Name = "UImm5"; -+ let RenderMethod = "addUImmOperands<5>"; -+ let PredicateMethod = "isUImm<5>"; -+ let DiagnosticType = "InvalidImm0_31"; - } - --def simm20 : Operand { -- let ParserMatchClass = SImmAsmOperand<20>; -- let DecoderMethod = "decodeSImmOperand<20>"; -+def uimm1i : Operand, ImmLeaf= 0 && Imm < 2; }]> { -+ let PrintMethod = "printUImm<1>"; -+ let ParserMatchClass = UImm1Operand; - } - --def simm21_lsl2 : Operand { -- let ParserMatchClass = SImmAsmOperand<21, "lsl2">; -- let EncoderMethod = "getImmOpValueAsr2"; -- let DecoderMethod = "decodeSImmOperand<21, 2>"; -+def uimm2 : Operand, ImmLeaf= 0 && Imm < 4; }]> { -+ let PrintMethod = "printUImm<2>"; -+ let ParserMatchClass = UImm2Operand; - } - --def simm26_lsl2 : Operand { -- let ParserMatchClass = SImmAsmOperand<26, "lsl2">; -- let EncoderMethod = "getImmOpValueAsr2"; -- let DecoderMethod = "decodeSImmOperand<26, 2>"; -+def uimm3 : Operand, ImmLeaf= 0 && Imm < 8; }]> { -+ let PrintMethod = "printUImm<3>"; -+ let ParserMatchClass = UImm3Operand; - } - --// Standalone (codegen-only) immleaf patterns. -+def uimm4i : Operand, ImmLeaf= 0 && Imm < 16; }]> { -+ let PrintMethod = "printUImm<4>"; -+ let ParserMatchClass = UImm4Operand; -+} - --// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048]. --def simm12_plus1 : ImmLeaf(Imm) && Imm != -2048) || Imm == 2048;}]>; -+def uimm5 : Operand, ImmLeaf= 0 && Imm < 32; }]> { -+ let PrintMethod = "printUImm<5>"; -+ let ParserMatchClass = UImm5Operand; -+} - --// Return the negation of an immediate value. --def NegImm : SDNodeXFormgetTargetConstant(-N->getSExtValue(), SDLoc(N), -- N->getValueType(0)); --}]>; -+def UImm6Operand : AsmOperandClass { -+ let Name = "UImm6"; -+ let RenderMethod = "addUImmOperands<16>"; -+ let PredicateMethod = "isUImm<6>"; -+ let DiagnosticType = "InvalidImm0_63"; -+} -+def uimm6 : Operand, ImmLeaf= 0 && Imm < 64; }]> { -+ let PrintMethod = "printUImm<6>"; -+ let ParserMatchClass = UImm6Operand; -+} - --// FP immediate patterns. --def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>; --def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>; --def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; -+def UImm7Operand : AsmOperandClass { -+ let Name = "UImm7"; -+ let RenderMethod = "addUImmOperands<16>"; -+ let PredicateMethod = "isUImm<7>"; -+ let DiagnosticType = "InvalidImm0_127"; -+} - --def CallSymbol: AsmOperandClass { -- let Name = "CallSymbol"; -+def uimm7i : Operand, ImmLeaf= 0 && Imm < 128; }]> { -+ let PrintMethod = "printUImm<7>"; -+ let ParserMatchClass = UImm7Operand; -+} -+ -+def UImm12Operand : AsmOperandClass { -+ let Name = "UImm12"; -+ let RenderMethod = "addUImmOperands<12>"; -+ let PredicateMethod = "isUImm<12>"; -+ let DiagnosticType = "InvalidImm0_4095"; -+} -+def uimm12 : Operand, ImmLeaf= 0 && Imm < 4096; }]> { -+ let PrintMethod = "printUImm<12>"; -+ let ParserMatchClass = UImm12Operand; -+} -+def uimm12_32 : Operand, ImmLeaf= 0 && Imm < 4096; }]> { -+ let PrintMethod = "printUImm<12>"; -+ let ParserMatchClass = UImm12Operand; -+} -+ -+def UImm15Operand : AsmOperandClass { -+ let Name = "UImm15"; -+ let RenderMethod = "addUImmOperands<15>"; -+ let PredicateMethod = "isUImm<15>"; -+ let DiagnosticType = "InvalidImm0_32767"; -+} -+def uimm15 : Operand, ImmLeaf= 0 && Imm < 32768; }]> { -+ let PrintMethod = "printUImm<15>"; -+ let ParserMatchClass = UImm15Operand; -+} -+ -+def UImm14Operand : AsmOperandClass { -+ let Name = "UImm14"; -+ let RenderMethod = "addUImmOperands<14>"; -+ let PredicateMethod = "isUImm<14>"; -+ let DiagnosticType = "InvalidImm0_16383"; -+} -+def uimm14 : Operand, ImmLeaf= 0 && Imm < 16384; }]> { -+ let PrintMethod = "printUImm<14>"; -+ let ParserMatchClass = UImm14Operand; -+} -+def uimm14_32 : Operand, ImmLeaf= 0 && Imm < 16384; }]> { -+ let PrintMethod = "printUImm<14>"; -+ let ParserMatchClass = UImm14Operand; -+} -+ -+def UImm8Operand : AsmOperandClass { -+ let Name = "UImm8"; -+ let RenderMethod = "addUImmOperands<8>"; -+ let PredicateMethod = "isUImm<8>"; -+ let DiagnosticType = "InvalidImm0_255"; -+} -+def uimm8_64 : Operand, ImmLeaf= 0 && Imm < 256; }]> { -+ let PrintMethod = "printUImm<8>"; -+ let ParserMatchClass = UImm8Operand; -+} -+ -+def uimm8_32 : Operand, ImmLeaf= 0 && Imm < 256; }]> { -+ let PrintMethod = "printUImm<8>"; -+ let ParserMatchClass = UImm8Operand; -+} -+ -+def addr : -+ComplexPattern; -+ -+def addrDefault : -+ComplexPattern; -+ -+def addrRegImm : -+ComplexPattern; -+ -+def addrimm14lsl2 : ComplexPattern; -+ -+class ConstantUImmAsmOperandClass Supers = [], -+ int Offset = 0> : AsmOperandClass { -+ let Name = "ConstantUImm" # Bits # "_" # Offset; -+ let RenderMethod = "addConstantUImmOperands<" # Bits # ", " # Offset # ">"; -+ let PredicateMethod = "isConstantUImm<" # Bits # ", " # Offset # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "UImm" # Bits # "_" # Offset; -+} -+class SImmAsmOperandClass Supers = []> -+ : AsmOperandClass { -+ let Name = "SImm" # Bits; -+ let RenderMethod = "addSImmOperands<" # Bits # ">"; -+ let PredicateMethod = "isSImm<" # Bits # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "SImm" # Bits; -+} -+class UImmAnyAsmOperandClass Supers = []> -+ : AsmOperandClass { -+ let Name = "ImmAny"; -+ let RenderMethod = "addConstantUImmOperands<32>"; -+ let PredicateMethod = "isSImm<" # Bits # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "ImmAny"; -+} -+ -+def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> { -+ let Name = "UImm32_Coerced"; -+ let DiagnosticType = "UImm32_Coerced"; -+} -+def SImm32RelaxedAsmOperandClass -+ : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> { -+ let Name = "SImm32_Relaxed"; -+ let PredicateMethod = "isAnyImm<33>"; -+ let DiagnosticType = "SImm32_Relaxed"; -+} -+def SImm32AsmOperandClass -+ : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>; -+def ConstantUImm26AsmOperandClass -+ : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>; -+ -+def ConstantUImm20AsmOperandClass -+ : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>; -+ -+def ConstantUImm2Plus1AsmOperandClass -+ : ConstantUImmAsmOperandClass<2, [ConstantUImm20AsmOperandClass], 1>; -+ -+class UImmAsmOperandClass Supers = []> -+ : AsmOperandClass { -+ let Name = "UImm" # Bits; -+ let RenderMethod = "addUImmOperands<" # Bits # ">"; -+ let PredicateMethod = "isUImm<" # Bits # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "UImm" # Bits; -+} -+ -+def UImm16RelaxedAsmOperandClass -+ : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> { -+ let Name = "UImm16_Relaxed"; -+ let PredicateMethod = "isAnyImm<16>"; -+ let DiagnosticType = "UImm16_Relaxed"; -+} -+ -+def ConstantSImm14Lsl2AsmOperandClass : AsmOperandClass { -+ let Name = "SImm14Lsl2"; - let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<14, 2>"; -+ let SuperClasses = [UImm16RelaxedAsmOperandClass]; -+ let DiagnosticType = "SImm14_Lsl2"; -+} -+ -+foreach I = {2} in -+ def simm14_lsl # I : Operand { -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<14, " # I # ">"; -+ let ParserMatchClass = -+ !cast("ConstantSImm14Lsl" # I # "AsmOperandClass"); -+ } -+ -+def uimm16_64_relaxed : Operand { -+ let PrintMethod = "printUImm<16>"; -+ let ParserMatchClass = -+ !cast("UImm16RelaxedAsmOperandClass"); -+} -+ -+def uimm2_plus1 : Operand { -+ let PrintMethod = "printUImm<2, 1>"; -+ let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; -+ let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; -+ let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; -+} -+ -+// like simm32 but coerces simm32 to uimm32. -+def uimm32_coerced : Operand { -+ let ParserMatchClass = !cast("UImm32CoercedAsmOperandClass"); -+} -+ -+def imm64: Operand; -+ -+def LoongArchMemAsmOperand : AsmOperandClass { -+ let Name = "Mem"; -+ let ParserMethod = "parseMemOperand"; -+} -+ -+def LoongArchAMemAsmOperand : AsmOperandClass { -+ let Name = "AMem"; -+ let ParserMethod = "parseAMemOperand"; -+ let RenderMethod = "addMemOperands"; -+ let PredicateMethod = "isZeroMemOff"; -+ let DiagnosticType = "MemZeroOff"; -+} -+ -+def LoongArchMemSimm14AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm14"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<14>"; -+ let DiagnosticType = "MemSImm14"; -+} -+ -+foreach I = {2} in -+ def LoongArchMemSimm14Lsl # I # AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm14_" # I; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<14, " # I # ">"; -+ let DiagnosticType = "MemSImm14Lsl" # I; -+ } -+ -+def LoongArchMemSimmPtrAsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimmPtr"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithPtrSizeOffset"; -+ let DiagnosticType = "MemSImmPtr"; -+} -+ -+class mem_generic : Operand { -+ let PrintMethod = "printMemOperand"; -+ let MIOperandInfo = (ops ptr_rc, simm12); -+ let EncoderMethod = "getMemEncoding"; -+ let ParserMatchClass = LoongArchMemAsmOperand; -+ let OperandType = "OPERAND_MEMORY"; -+} -+ -+// Address operand -+def mem : mem_generic; -+ -+def amem : mem_generic { -+ let PrintMethod = "printAMemOperand"; -+ let EncoderMethod = "getAMemEncoding"; -+ let ParserMatchClass = LoongArchAMemAsmOperand; -+} -+ -+def mem_simmptr : mem_generic { -+ let ParserMatchClass = LoongArchMemSimmPtrAsmOperand; -+} -+ -+foreach I = {2} in -+ def mem_simm14_lsl # I : mem_generic { -+ let MIOperandInfo = (ops ptr_rc, !cast("simm14_lsl" # I)); -+ let EncoderMethod = "getSimm14MemEncoding<" # I # ">"; -+ let ParserMatchClass = -+ !cast("LoongArchMemSimm14Lsl" # I # "AsmOperand"); -+ } -+ -+def mem_ea : Operand { -+ let PrintMethod = "printMemOperandEA"; -+ let MIOperandInfo = (ops ptr_rc, simm12); -+ let EncoderMethod = "getMemEncoding"; -+ let OperandType = "OPERAND_MEMORY"; -+} -+ -+def LoongArchJumpTargetAsmOperand : AsmOperandClass { -+ let Name = "JumpTarget"; -+ let ParserMethod = "parseJumpTarget"; - let PredicateMethod = "isImm"; -+ let RenderMethod = "addImmOperands"; - } - --// A bare symbol used in call only. --def call_symbol : Operand { -- let ParserMatchClass = CallSymbol; -+def jmptarget : Operand { -+ let EncoderMethod = "getJumpTargetOpValue"; -+ let ParserMatchClass = LoongArchJumpTargetAsmOperand; - } - --def BaseAddr : ComplexPattern; -+def brtarget : Operand { -+ let EncoderMethod = "getBranchTargetOpValue"; -+ let OperandType = "OPERAND_PCREL"; -+ let DecoderMethod = "DecodeBranchTarget"; -+ let ParserMatchClass = LoongArchJumpTargetAsmOperand; -+} - --//===----------------------------------------------------------------------===// --// Instruction Formats --//===----------------------------------------------------------------------===// -+def calltarget : Operand { -+ let EncoderMethod = "getJumpTargetOpValue"; -+ let ParserMatchClass = LoongArchJumpTargetAsmOperand; -+} - --include "LoongArchInstrFormats.td" --include "LoongArchFloatInstrFormats.td" -+// -+//SDNode -+// -+def IsGP64bit : Predicate<"Subtarget->is64Bit()">, -+ AssemblerPredicate<(all_of Feature64Bit)>; -+def IsGP32bit : Predicate<"!Subtarget->is64Bit()">, -+ AssemblerPredicate<(all_of (not Feature64Bit))>; -+def SDT_LoongArchCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -+def SDT_LoongArchCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -+ -+def LoongArchRet : SDNode<"LoongArchISD::Ret", SDTNone, -+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -+def LoongArchERet : SDNode<"LoongArchISD::ERet", SDTNone, -+ [SDNPHasChain, SDNPOptInGlue, SDNPSideEffect]>; -+ -+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_LoongArchCallSeqStart, -+ [SDNPHasChain, SDNPSideEffect, SDNPOutGlue]>; -+def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_LoongArchCallSeqEnd, -+ [SDNPHasChain, SDNPSideEffect, -+ SDNPOptInGlue, SDNPOutGlue]>; -+def LoongArchAddress : SDNode<"LoongArchISD::GlobalAddress", SDTIntUnaryOp>; -+ -+// Return RA. -+let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { -+ def RetRA : LoongArchPseudo<(outs), (ins), [(LoongArchRet)]>; -+ -+ let hasSideEffects=1 in -+ def ERet : LoongArchPseudo<(outs), (ins), [(LoongArchERet)]>; -+} - --//===----------------------------------------------------------------------===// -+let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { -+def ADJCALLSTACKDOWN : LoongArchPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), -+ [(callseq_start timm:$amt1, timm:$amt2)]>; -+def ADJCALLSTACKUP : LoongArchPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), -+ [(callseq_end timm:$amt1, timm:$amt2)]>; -+} -+ -+class LoongArchPat : Pat, PredicateControl; -+ -+def SDT_LoongArchJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -+ -+def LoongArchJmpLink : SDNode<"LoongArchISD::JmpLink",SDT_LoongArchJmpLink, -+ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, -+ SDNPVariadic]>; -+ -+def LoongArchTailCall : SDNode<"LoongArchISD::TailCall", SDT_LoongArchJmpLink, -+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -+ -+class GPR_32 { list GPRPredicates = [IsGP32bit]; } -+class GPR_64 { list GPRPredicates = [IsGP64bit]; } -+ -+//===---------------------------------------------------------------------===/ - // Instruction Class Templates --//===----------------------------------------------------------------------===// -+//===---------------------------------------------------------------------===/ -+///R2 -+class Int_Reg2 -+ : InstForm<(outs RO:$rd), (ins RO:$rj), -+ !strconcat(opstr, "\t$rd, $rj"), -+ [(set RO:$rd, (OpNode RO:$rj))], -+ FrmR, opstr>; -+ -+class Int_Reg2_Iocsrrd -+ : InstForm<(outs RD:$rd), (ins RS:$rj), -+ !strconcat(opstr, "\t$rd, $rj"), -+ [(set RD:$rd, (OpNode RS:$rj))], -+ FrmR, opstr>; -+ -+class Int_Reg2_Rdtime -+ : InstForm<(outs RO:$rd, RO:$rj), (ins), -+ !strconcat(opstr, "\t$rd, $rj"), -+ [(set (OpNode RO:$rd, RO:$rj))], -+ FrmR, opstr>; -+ -+class Int_Reg2_Iocsrwr -+ : InstForm<(outs), (ins RD:$rd, RS:$rj), -+ !strconcat(opstr, "\t$rd, $rj"), -+ [(set (OpNode RD:$rd, RS:$rj))], -+ FrmR, opstr>; -+ -+class Float_Reg2 -+ : InstForm<(outs RO:$fd), (ins RO:$fj), -+ !strconcat(opstr, "\t$fd, $fj"), -+ [(set RO:$fd, (OpNode RO:$fj))], -+ FrmFR, opstr>; -+ -+class Count1 -+ : InstForm<(outs RO:$rd), (ins RO:$rj), -+ !strconcat(opstr, "\t$rd, $rj"), -+ [(set RO:$rd, (OpNode (not RO:$rj)))], -+ FrmR, opstr>; -+ -+class SignExtInReg -+ : InstForm<(outs RO:$rd), (ins RO:$rj), !strconcat(opstr, "\t$rd, $rj"), -+ [(set RO:$rd, (sext_inreg RO:$rj, vt))], FrmR, opstr>; -+ -+///R3 -+class Int_Reg3 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set RO:$rd, (OpNode RO:$rj, RO:$rk))], -+ FrmR, opstr>; -+ -+class Int_Reg3_Crc -+ : InstForm<(outs RS:$rd), (ins RD:$rj, RS:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set RS:$rd, (OpNode RD:$rj, RS:$rk))], -+ FrmR, opstr>; -+ -+class SetCC_R -+ : InstForm<(outs GPR32Opnd:$rd), (ins RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set GPR32Opnd:$rd, (OpNode RO:$rj, RO:$rk))], -+ FrmR, opstr>; -+ -+class SetCC_I -+ : InstForm<(outs GPR32Opnd:$rd), (ins RO:$rj, ImmOpnd:$imm12), -+ !strconcat(opstr, "\t$rd, $rj, $imm12"), -+ [(set GPR32Opnd:$rd, (OpNode RO:$rj, ImmOpnd:$imm12))], -+ FrmR, opstr>; -+ -+class ATOMIC -+ : InstForm<(outs RD:$rd), (ins RD:$rk, MO:$addr), -+ !strconcat(opstr, "\t$rd, $rk, $addr"), -+ [(set RD:$rd, (OpNode RD:$rk, Addr:$addr))], -+ FrmR, opstr> { -+ let DecoderMethod = "DecodeAMem"; -+ let canFoldAsLoad = 1; -+ string BaseOpcode = opstr; -+ let mayLoad = 1; -+ let mayStore = 1; -+ let Constraints = "@earlyclobber $rd"; -+} - --class ALU_3R op, string opstr> -- : Fmt3R; --class ALU_2R op, string opstr> -- : Fmt2R; -- --class ALU_3RI2 op, string opstr, Operand ImmOpnd> -- : Fmt3RI2; --class ALU_3RI3 op, string opstr, Operand ImmOpnd> -- : Fmt3RI3; --class ALU_2RI5 op, string opstr, Operand ImmOpnd> -- : Fmt2RI5; --class ALU_2RI6 op, string opstr, Operand ImmOpnd> -- : Fmt2RI6; --class ALU_2RI12 op, string opstr, Operand ImmOpnd> -- : Fmt2RI12; --class ALU_2RI16 op, string opstr, Operand ImmOpnd> -- : Fmt2RI16; --class ALU_1RI20 op, string opstr, Operand ImmOpnd> -- : Fmt1RI20; -- --class MISC_I15 op, string opstr> -- : FmtI15; -- --class RDTIME_2R op, string opstr> -- : Fmt2R; -- --class BrCC_2RI16 op, string opstr> -- : Fmt2RI16 { -- let isBranch = 1; -- let isTerminator = 1; -+class Nor -+ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set RO:$rd, (not (or RO:$rj, RO:$rk)))], -+ FrmR, opstr>; -+ -+class Shift_Var -+ : InstForm<(outs RO:$rd), (ins RO:$rj, GPR32Opnd:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set RO:$rd, (OpNode RO:$rj, GPR32Opnd:$rk))], -+ FrmR, opstr>; -+ -+class Float_Reg3 -+ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), -+ !strconcat(opstr, "\t$fd, $fj, $fk"), -+ [(set RO:$fd, (OpNode RO:$fj, RO:$fk))], -+ FrmR, opstr>; -+ -+class Float_Reg3_MA -+ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), -+ !strconcat(opstr, "\t$fd, $fj, $fk"), -+ [(set RO:$fd, (OpNode (fabs RO:$fj), (fabs RO:$fk)))], -+ FrmR, opstr>; -+ -+class Float_Int_Reg3 -+ : InstForm<(outs RD:$fd), (ins RS:$rj, RS:$rk), -+ !strconcat(opstr, "\t$fd, $rj, $rk"), -+ [(set RS:$fd, (OpNode RS:$rj, RS:$rk))], -+ FrmR, opstr>; -+ -+///R4 -+class Mul_Reg4 -+ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk, RO:$fa), -+ !strconcat(opstr, "\t$fd, $fj, $fk, $fa"), -+ [], -+ FrmFR, opstr>; -+ -+class NMul_Reg4 -+ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk, RO:$fa), -+ !strconcat(opstr, "\t$fd, $fj, $fk, $fa"), -+ [], -+ FrmFR, opstr>; -+ -+///R2_IMM5 -+class Shift_Imm32 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm5:$imm5), -+ !strconcat(opstr, "\t$rd, $rj, $imm5"), -+ [(set RO:$rd, (OpNode RO:$rj, uimm5:$imm5))], -+ FrmR, opstr>; -+ -+///R2_IMM6 -+class Shift_Imm64 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm6:$imm6), -+ !strconcat(opstr, "\t$rd, $rj, $imm6"), -+ [(set RO:$rd, (OpNode RO:$rj, uimm6:$imm6))], -+ FrmR, opstr>; -+ -+///LOAD_STORE -+class FLd -+ : InstForm<(outs RD:$rd), (ins MO:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [(set RD:$rd, (OpNode addrDefault:$addr))], -+ FrmR, opstr> { -+ let DecoderMethod = "DecodeFMem"; -+ let mayLoad = 1; -+} -+ -+class Ld -+ : InstForm<(outs RD:$rd), (ins MO:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [(set RD:$rd, (OpNode Addr:$addr))], -+ FrmR, opstr> { -+ let DecoderMethod = "DecodeMem"; -+ let canFoldAsLoad = 1; -+ string BaseOpcode = opstr; -+ let mayLoad = 1; -+} -+ -+class FSt -+ : InstForm<(outs), (ins RD:$rd, MO:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [(OpNode RD:$rd, addrDefault:$addr)], -+ FrmR, opstr> { -+ let DecoderMethod = "DecodeFMem"; -+ let mayStore = 1; -+} -+ -+class St -+ : InstForm<(outs), (ins RS:$rd, MO:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [(OpNode RS:$rd, addr:$addr)], -+ FrmR, opstr> { -+ let DecoderMethod = "DecodeMem"; -+ string BaseOpcode = opstr; -+ let mayStore = 1; -+} -+ -+/// R2_IMM12 -+class Int_Reg2_Imm12 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$imm12), -+ !strconcat(opstr, "\t$rd, $rj, $imm12"), -+ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$imm12))], -+ FrmR, opstr>; -+class RELOC_rrii -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$imm12, ImmOpnd:$i12), -+ !strconcat(opstr, "\t$rd, $rj, $imm12"), -+ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$imm12, ImmOpnd:$i12))], -+ FrmR, opstr>; -+ -+///R2_IMM14 -+class LdPtr -+ : InstForm<(outs RO:$rd), (ins mem_simm14_lsl2:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [], FrmI, opstr>{ -+ let DecoderMethod = "DecodeMemSimm14"; -+ let canFoldAsLoad = 1; -+ string BaseOpcode = opstr; -+ let mayLoad = 1; -+} -+ -+class StPtr -+ : InstForm<(outs), (ins RO:$rd, mem_simm14_lsl2:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [], FrmI, opstr> { -+ let DecoderMethod = "DecodeMemSimm14"; -+ string BaseOpcode = opstr; -+ let mayStore = 1; - } --class BrCCZ_1RI21 op, string opstr> -- : Fmt1RI21 { -- let isBranch = 1; -+ -+///R2_IMM16 -+class FJirl -+ : InstForm<(outs RO:$rd), (ins RO:$rj, opnd:$offs16), -+ !strconcat(opstr, "\t$rd, $rj, $offs16"), -+ [], FrmJ, opstr>; -+ -+class Beq -+ : InstForm<(outs), (ins RO:$rj, RO:$rd, opnd:$offs16), -+ !strconcat(opstr, "\t$rj, $rd, $offs16"), -+ [(brcond (i32 (cond_op RO:$rj, RO:$rd)), bb:$offs16)], -+ FrmI, opstr> { -+ let isBranch = 1; -+ let isTerminator = 1; -+ bit isCTI = 1; -+} -+ -+///R1_IMM21 -+class Beqz -+ : InstForm<(outs), (ins RO:$rj, opnd:$offs21), -+ !strconcat(opstr, "\t$rj, $offs21"), -+ [(brcond (i32 (cond_op RO:$rj, 0)), bb:$offs21)], -+ FrmI, opstr> { -+ let isBranch = 1; -+ let isTerminator = 1; -+ bit isCTI = 1; -+} -+ -+///IMM26 -+class JumpFB : -+ InstForm<(outs), (ins opnd:$offset26), !strconcat(opstr, "\t$offset26"), -+ [(operator targetoperator:$offset26)], FrmJ, opstr> { -+ let isBranch = 1; -+ let isTerminator=1; -+ let isBarrier=1; -+ let DecoderMethod = "DecodeJumpTarget"; -+ bit isCTI = 1; -+} -+ -+/// R3_SA -+class Reg3_Sa -+ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk, ImmOpnd:$sa), -+ !strconcat(opstr, "\t$rd, $rj, $rk, $sa"), -+ [(set RO:$rd, (OpNode RO:$rj, RO:$rk, ImmOpnd:$sa))], -+ FrmR, opstr>; -+ -+class Reg3_SaU -+ : InstForm<(outs RD:$rd), (ins RS:$rj, RS:$rk, ImmOpnd:$sa), -+ !strconcat(opstr, "\t$rd, $rj, $rk, $sa"), -+ [(set RD:$rd, (OpNode RS:$rj, RS:$rk, ImmOpnd:$sa))], -+ FrmR, opstr>; -+ -+/// Assert -+class Assert -+ : InstForm<(outs), (ins RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$rj, $rk"), -+ [(set (OpNode RO:$rj, RO:$rk))], -+ FrmR, opstr>; -+ -+class Code15 -+ : InstForm<(outs), (ins uimm15:$Code), -+ !strconcat(opstr, "\t$Code"), -+ [(set (OpNode uimm15:$Code))], -+ FrmOther, opstr>; -+ -+class TrapBase -+ : LoongArchPseudo<(outs), (ins), [(trap)]>, -+ PseudoInstExpansion<(RealInst 0)> { -+ let isBarrier = 1; -+ let isTerminator = 1; -+ let isCodeGenOnly = 1; -+ let isCTI = 1; -+} -+ -+class CSR -+ : InstForm<(outs RO:$rd), (ins ImmOpnd:$csr), -+ !strconcat(opstr, "\t$rd, $csr"), -+ [(set RO:$rd, (OpNode ImmOpnd:$csr))], -+ FrmOther, opstr>; -+ -+class CSRW -+ : InstForm<(outs RO:$dst), (ins RO:$rd, ImmOpnd:$csr), -+ !strconcat(opstr, "\t$rd, $csr"), -+ [(set RO:$dst, (OpNode RO:$rd, ImmOpnd:$csr))], -+ FrmOther, opstr>{ -+ let Constraints = "$rd = $dst"; -+} -+ -+class CSRX -+ : InstForm<(outs RO:$dst), (ins RO:$rd, RO:$rj, ImmOpnd:$csr), -+ !strconcat(opstr, "\t$rd, $rj, $csr"), -+ [(set RO:$dst, (OpNode RO:$rd, RO:$rj, ImmOpnd:$csr))], -+ FrmOther, opstr>{ -+ let Constraints = "$rd = $dst"; -+} -+ -+class CAC -+ : InstForm<(outs), (ins uimm5:$op, RO:$rj, ImmOpnd:$si12), -+ !strconcat(opstr, "\t$op, $rj, $si12"), -+ [(set (OpNode uimm5:$op, RO:$rj, ImmOpnd:$si12))], -+ FrmOther, opstr>; -+ -+class LEVEL -+ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm8_64:$level), -+ !strconcat(opstr, "\t$rd, $rj, $level"), -+ [(set RO:$rd, (OpNode RO:$rj, uimm8_64:$level))], -+ FrmOther, opstr>; -+ -+class SEQ -+ : InstForm<(outs), (ins RO:$rj, uimm8_64:$seq), -+ !strconcat(opstr, "\t$rj, $seq"), -+ [(set (OpNode RO:$rj, uimm8_64:$seq))], -+ FrmOther, opstr>; -+ -+class Wait -+ : InstForm<(outs), (ins uimm15:$hint), -+ !strconcat(opstr, "\t$hint"), -+ [(set (OpNode uimm15:$hint))], -+ FrmOther, opstr>; -+ -+class Invtlb -+ : InstForm<(outs), (ins uimm5:$op, RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$op, $rj, $rk"), -+ [(set (OpNode uimm5:$op, RO:$rj, RO:$rk))], -+ FrmOther, opstr>; -+ -+class OP32 -+ : InstForm<(outs), (ins), -+ !strconcat(opstr, ""), -+ [(set (OpNode))], -+ FrmOther, opstr>; -+ -+class Bar -+ : InstForm<(outs), (ins uimm15:$hint), -+ !strconcat(opstr, "\t$hint"), -+ [(set (OpNode uimm15:$hint))], -+ FrmOther, opstr>; -+ -+//class CA op, string opstr> -+// : R3_CA; -+ -+class SI16_R2 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, simm16:$si16), -+ !strconcat(opstr, "\t$rd, $rj, $si16"), -+ [(set RO:$rd, (OpNode RO:$rj, simm16:$si16))], -+ FrmR, opstr>; -+ -+class SI20 -+ : InstForm<(outs RO:$rd), (ins ImmOpnd:$si20), -+ !strconcat(opstr, "\t$rd, $si20"), -+ [(set RO:$rd, (OpNode ImmOpnd:$si20))], -+ FrmR, opstr>; -+let isCodeGenOnly = 1, Constraints = "$dst = $rd" in -+class SI20_R2 -+ : InstForm<(outs RO:$dst), (ins RO:$rd, ImmOpnd:$si20), -+ !strconcat(opstr, "\t$rd, $si20"), -+ [(set RO:$dst, (OpNode RO:$rd, ImmOpnd:$si20))], -+ FrmR, opstr>; -+class RELOC_rii -+ : InstForm<(outs RO:$rd), (ins ImmOpnd:$si20, ImmOpnd:$i20), -+ !strconcat(opstr, "\t$rd, $si20"), -+ [(set RO:$rd, (OpNode ImmOpnd:$si20, ImmOpnd:$i20))], -+ FrmR, opstr>; -+ -+// preld -+class Preld -+ : InstForm<(outs), (ins RO:$rj, MemOpnd:$addr, uimm5:$hint), -+ !strconcat(opstr, "\t$hint, $rj, $addr"), -+ [(set (OpNode RO:$rj, MemOpnd:$addr, uimm5:$hint))], -+ FrmR, opstr>; -+class Preld_Raw -+ : InstForm<(outs), (ins RO:$rj, simm12:$imm12, uimm5:$hint), -+ !strconcat(opstr, "\t$hint, $rj, $imm12"), -+ [], -+ FrmR, opstr>; -+class IsCall { -+ bit isCall = 1; -+ bit isCTI = 1; -+} -+ -+class EffectiveAddress -+ : InstForm<(outs RO:$rd), (ins mem_ea:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), -+ [(set RO:$rd, addr:$addr)], FrmI, -+ !strconcat(opstr, "_lea")> { -+ let isCodeGenOnly = 1; -+ let hasNoSchedulingInfo = 1; -+ let DecoderMethod = "DecodeMem"; -+} -+ -+def PtrRC : Operand { -+ let MIOperandInfo = (ops ptr_rc); -+ let DecoderMethod = "DecodePtrRegisterClass"; -+ let ParserMatchClass = GPR32AsmOperand; -+} -+ -+class Atomic2Ops : -+ LoongArchPseudo<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), -+ [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; -+ -+class Atomic2OpsPostRA : -+ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { -+ let mayLoad = 1; -+ let mayStore = 1; -+} -+ -+class Atomic2OpsSubwordPostRA : -+ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, -+ RC:$shiftamnt), []>; -+class AtomicCmpSwap : -+ LoongArchPseudo<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), -+ [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; -+ -+class AtomicCmpSwapPostRA : -+ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { -+ let mayLoad = 1; -+ let mayStore = 1; -+} -+ -+class AtomicCmpSwapSubwordPostRA : -+ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$mask, RC:$ShiftCmpVal, -+ RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> { -+ let mayLoad = 1; -+ let mayStore = 1; -+} -+ -+class LoongArchInstAlias : -+ InstAlias, PredicateControl; -+ -+//===---------------------------------------------------------------------===/ -+// Instruction Definitions. -+//===---------------------------------------------------------------------===/ -+/// -+/// R2 -+/// -+ -+def CLO_D : Count1<"clo.d", GPR64Opnd, ctlz>, R2I<0b01000>; -+def CLZ_D : Int_Reg2<"clz.d", GPR64Opnd, ctlz>, R2I<0b01001>; -+def CTO_D : Count1<"cto.d", GPR64Opnd, cttz>, R2I<0b01010>; -+def CTZ_D : Int_Reg2<"ctz.d", GPR64Opnd, cttz>, R2I<0b01011>; -+ -+def REVB_4H : Int_Reg2<"revb.4h", GPR64Opnd>, R2I<0b01101>; //[] -+def REVB_2W : Int_Reg2<"revb.2w", GPR64Opnd>, R2I<0b01110>; -+def REVB_D : Int_Reg2<"revb.d", GPR64Opnd>, R2I<0b01111>; -+def REVH_2W : Int_Reg2<"revh.2w", GPR64Opnd>, R2I<0b10000>; -+def REVH_D : Int_Reg2<"revh.d", GPR64Opnd>, R2I<0b10001>; //[] -+ -+def BITREV_8B : Int_Reg2<"bitrev.8b", GPR64Opnd>, R2I<0b10011>; //[] -+def BITREV_D : Int_Reg2<"bitrev.d", GPR64Opnd, bitreverse>, R2I<0b10101>; -+ -+def EXT_W_H : SignExtInReg<"ext.w.h", GPR64Opnd, i16>, R2I<0b10110>; -+def EXT_W_B : SignExtInReg<"ext.w.b", GPR64Opnd, i8>, R2I<0b10111>; -+ -+def RDTIME_D : Int_Reg2_Rdtime<"rdtime.d", GPR64Opnd>, R2I<0b11010>; -+def RDTIMEL_W : Int_Reg2_Rdtime<"rdtimel.w", GPR64Opnd>, R2I<0b11000>; -+def RDTIMEH_W : Int_Reg2_Rdtime<"rdtimeh.w", GPR64Opnd>, R2I<0b11001>; -+/// -+/// R3 -+/// -+def ADD_D : Int_Reg3<"add.d", GPR64Opnd, add>, R3I<0b0100001>; -+def SUB_D : Int_Reg3<"sub.d", GPR64Opnd, sub>, R3I<0b0100011>; -+ -+def SLT : SetCC_R<"slt", GPR64Opnd, setlt>, R3I<0b0100100>; -+def SLTU : SetCC_R<"sltu", GPR64Opnd, setult>, R3I<0b0100101>; -+def MASKEQZ : Int_Reg3<"maskeqz", GPR64Opnd>, R3I<0b0100110>; //[] -+def MASKNEZ : Int_Reg3<"masknez", GPR64Opnd>, R3I<0b0100111>; //[] -+ -+def NOR : Nor<"nor", GPR64Opnd>, R3I<0b0101000>; -+def AND : Int_Reg3<"and", GPR64Opnd, and>, R3I<0b0101001>; -+def OR : Int_Reg3<"or", GPR64Opnd, or>, R3I<0b0101010>; -+def XOR : Int_Reg3<"xor", GPR64Opnd, xor>, R3I<0b0101011>; -+def ORN : Int_Reg3<"orn", GPR64Opnd>, R3I<0b0101100>; -+def ANDN : Int_Reg3<"andn", GPR64Opnd>, R3I<0b0101101>; -+ -+def SLL_D : Shift_Var<"sll.d", GPR64Opnd, shl>, R3I<0b0110001>; -+def SRL_D : Shift_Var<"srl.d", GPR64Opnd, srl>, R3I<0b0110010>; -+def SRA_D : Shift_Var<"sra.d", GPR64Opnd, sra>, R3I<0b0110011>; -+def ROTR_D: Shift_Var<"rotr.d", GPR64Opnd, rotr>, R3I<0b0110111>; -+ -+def MUL_D : Int_Reg3<"mul.d", GPR64Opnd, mul>, R3I<0b0111011>; -+def MULH_D : Int_Reg3<"mulh.d", GPR64Opnd, mulhs>, R3I<0b0111100>; -+def MULH_DU : Int_Reg3<"mulh.du", GPR64Opnd, mulhu>, R3I<0b0111101>; -+def MULW_D_W : Int_Reg3<"mulw.d.w", GPR64Opnd>, R3I<0b0111110>; -+def MULW_D_WU : Int_Reg3<"mulw.d.wu", GPR64Opnd>, R3I<0b0111111>; -+ -+let usesCustomInserter = 1 in { -+def DIV_D : Int_Reg3<"div.d", GPR64Opnd, sdiv>, R3I<0b1000100>; -+def MOD_D : Int_Reg3<"mod.d", GPR64Opnd, srem>, R3I<0b1000101>; -+def DIV_DU : Int_Reg3<"div.du", GPR64Opnd, udiv>, R3I<0b1000110>; -+def MOD_DU : Int_Reg3<"mod.du", GPR64Opnd, urem>, R3I<0b1000111>; -+} -+ -+def CRC_W_D_W : Int_Reg3_Crc<"crc.w.d.w", GPR64Opnd, GPR32Opnd, int_loongarch_crc_w_d_w>, R3I<0b1001011>; -+def CRCC_W_D_W : Int_Reg3_Crc<"crcc.w.d.w", GPR64Opnd, GPR32Opnd, int_loongarch_crcc_w_d_w>, R3I<0b1001111>; -+/// -+/// SLLI -+/// -+def SLLI_D : Shift_Imm64<"slli.d", GPR64Opnd, shl>, R2_IMM6<0b00>; -+def SRLI_D : Shift_Imm64<"srli.d", GPR64Opnd, srl>, R2_IMM6<0b01>; -+def SRAI_D : Shift_Imm64<"srai.d", GPR64Opnd, sra>, R2_IMM6<0b10>; -+def ROTRI_D : Shift_Imm64<"rotri.d", GPR64Opnd, rotr>, R2_IMM6<0b11>; -+/// -+/// Misc -+/// -+def ALSL_WU : Reg3_SaU<"alsl.wu", GPR64Opnd, GPR32Opnd, uimm2_plus1>, R3_SA2<0b00011> { -+ let Pattern = [(set GPR64Opnd:$rd, -+ (i64 (zext (add GPR32Opnd:$rk, (shl GPR32Opnd:$rj, immZExt2Alsl:$sa)))))]; -+} -+ -+def ALSL_D : Reg3_Sa<"alsl.d", GPR64Opnd, uimm2_plus1>, R3_SA2<0b10110> { -+ let Pattern = [(set GPR64Opnd:$rd, -+ (add GPR64Opnd:$rk, (shl GPR64Opnd:$rj, immZExt2Alsl:$sa)))]; -+} -+def BYTEPICK_D : Reg3_Sa<"bytepick.d", GPR64Opnd, uimm3>, R3_SA3; //[] -+ -+def ASRTLE_D : Assert<"asrtle.d", GPR64Opnd, int_loongarch_asrtle_d>, ASSERT<0b10>; -+def ASRTGT_D : Assert<"asrtgt.d", GPR64Opnd, int_loongarch_asrtgt_d>, ASSERT<0b11>; -+ -+def DBCL : Code15<"dbcl">, CODE15<0b1010101>; -+def HYPCALL : Code15<"hypcall">, CODE15<0b1010111>; -+ -+/// -+/// R2_IMM12 -+/// -+def SLTI : SetCC_I<"slti", GPR64Opnd, simm12, setlt>, R2_IMM12<0b000>; -+def SLTUI : SetCC_I<"sltui", GPR64Opnd, simm12, setult>, R2_IMM12<0b001>; -+def ADDI_W64 : Int_Reg2_Imm12<"addi.w", GPR64Opnd, simm12>, R2_IMM12<0b010>; -+def ADDI_D : Int_Reg2_Imm12<"addi.d", GPR64Opnd, simm12, add>, R2_IMM12<0b011>; -+def LU52I_D : Int_Reg2_Imm12<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; -+def ANDI : Int_Reg2_Imm12<"andi", GPR64Opnd, uimm12, and>, R2_IMM12<0b101>; -+def ORI : Int_Reg2_Imm12<"ori", GPR64Opnd, uimm12, or>, R2_IMM12<0b110>; -+def XORI : Int_Reg2_Imm12<"xori", GPR64Opnd, uimm12, xor>, R2_IMM12<0b111>; -+ -+/// -+/// Privilege Instructions -+/// -+def CSRRD : CSR<"csrrd", GPR64Opnd, uimm14, int_loongarch_csrrd_d>, R1_CSR<0b0000000000100>; -+def CSRWR : CSRW<"csrwr", GPR64Opnd, uimm14, int_loongarch_csrwr_d>, R1_CSR<0b0000100000100>; -+def CSRXCHG : CSRX<"csrxchg", GPR64Opnd, uimm14, int_loongarch_csrxchg_d>, R2_CSR<0b00000100>; -+def IOCSRRD_D : Int_Reg2_Iocsrrd<"iocsrrd.d", GPR64Opnd, GPR32Opnd, int_loongarch_iocsrrd_d>, R2P<0b011>; -+def IOCSRWR_D : Int_Reg2_Iocsrwr<"iocsrwr.d", GPR64Opnd, GPR32Opnd, int_loongarch_iocsrwr_d>, R2P<0b111>; -+def CACOP : CAC<"cacop", GPR64Opnd, simm12, int_loongarch_cacop_d>, R1_CACHE; -+def LDDIR : LEVEL<"lddir", GPR64Opnd>, R2_LEVEL<0b00000110010000>; -+def LDPTE : SEQ<"ldpte", GPR64Opnd>, R1_SEQ<0b00000110010001>; -+ -+def IDLE : Wait<"idle">, WAIT_FM; -+def INVTLB : Invtlb<"invtlb", GPR64Opnd>, R2_INVTLB; -+// -+def IOCSRRD_B : Int_Reg2<"iocsrrd.b", GPR64Opnd>, R2P<0b000>; -+def IOCSRRD_H : Int_Reg2<"iocsrrd.h", GPR64Opnd>, R2P<0b001>; -+def IOCSRRD_W : Int_Reg2<"iocsrrd.w", GPR64Opnd>, R2P<0b010>; -+// -+def TLBCLR : OP32<"tlbclr", int_loongarch_tlbclr>, IMM32<0b001000>; -+def TLBFLUSH : OP32<"tlbflush", int_loongarch_tlbflush>, IMM32<0b001001>; -+def TLBSRCH : OP32<"tlbsrch", int_loongarch_tlbsrch>, IMM32<0b001010>; -+def TLBRD : OP32<"tlbrd", int_loongarch_tlbrd>, IMM32<0b001011>; -+def TLBWR : OP32<"tlbwr", int_loongarch_tlbwr>, IMM32<0b001100>; -+def TLBFILL : OP32<"tlbfill", int_loongarch_tlbfill>, IMM32<0b001101>; -+def ERTN : OP32<"ertn">, IMM32<0b001110>; -+ -+/// -+/// R1_IMM20 -+/// -+def ADDU16I_D : SI16_R2<"addu16i.d", GPR64Opnd>, R2_SI16<0b000100>; -+def LU12I_W : SI20<"lu12i.w", GPR64Opnd, simm20>, R1_SI20<0b0001010>; -+def LU32I_D : SI20<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; -+def LU32I_D_R2 : SI20_R2<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; -+def PCADDI : SI20<"pcaddi", GPR64Opnd, simm20>, R1_SI20<0b0001100>; -+def PCALAU12I : SI20<"pcalau12i", GPR64Opnd, simm20>, R1_SI20<0b0001101>; -+def PCADDU12I : SI20<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; -+def PCADDU18I : SI20<"pcaddu18i", GPR64Opnd, simm20>, R1_SI20<0b0001111>; -+ -+ -+def BEQZ : Beqz<"beqz", brtarget, seteq, GPR64Opnd>, R1_IMM21BEQZ<0b010000>; -+def BNEZ : Beqz<"bnez", brtarget, setne, GPR64Opnd>, R1_IMM21BEQZ<0b010001>; -+ -+def JIRL : FJirl<"jirl", simm16, GPR64Opnd>, R2_IMM16JIRL; -+let isCall = 1, isCTI=1, isCodeGenOnly = 1 in { -+def JIRL_CALL : FJirl<"jirl", simm16, GPR64Opnd>, R2_IMM16JIRL; -+} -+ -+def B : JumpFB, IMM26B<0b010100>; -+ -+def BEQ : Beq<"beq", brtarget, seteq, GPR64Opnd>, R2_IMM16BEQ<0b010110>; -+def BNE : Beq<"bne", brtarget, setne, GPR64Opnd>, R2_IMM16BEQ<0b010111>; -+def BLT : Beq<"blt", brtarget, setlt, GPR64Opnd>, R2_IMM16BEQ<0b011000>; -+def BGE : Beq<"bge", brtarget, setge, GPR64Opnd>, R2_IMM16BEQ<0b011001>; -+def BLTU : Beq<"bltu", brtarget, setult, GPR64Opnd>, R2_IMM16BEQ<0b011010>; -+def BGEU : Beq<"bgeu", brtarget, setuge, GPR64Opnd>, R2_IMM16BEQ<0b011011>; -+ -+/// -+/// Mem access -+/// -+class LLBase : -+ InstForm<(outs RO:$rd), (ins MO:$addr), !strconcat(opstr, "\t$rd, $addr"), -+ [], FrmI, opstr> { -+ let DecoderMethod = "DecodeMemSimm14"; -+ let mayLoad = 1; -+} -+ -+class SCBase : -+ InstForm<(outs RO:$dst), (ins RO:$rd, MO:$addr), -+ !strconcat(opstr, "\t$rd, $addr"), [], FrmI> { -+ let DecoderMethod = "DecodeMemSimm14"; -+ let mayStore = 1; -+ let Constraints = "$rd = $dst"; -+} -+ -+class STGT_LE : -+ InstForm<(outs), (ins RO:$rd, RO:$rj, RO:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [], FrmI, opstr>; -+ -+class Float_STGT_LE -+ : InstForm<(outs), (ins RD:$fd, RS:$rj, RS:$rk), -+ !strconcat(opstr, "\t$fd, $rj, $rk"), -+ [], FrmR, opstr>; -+ -+def LL_D : LLBase<"ll.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b010>; -+def SC_D : SCBase<"sc.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b011>; -+ -+def LDPTR_W : LdPtr<"ldptr.w", GPR64Opnd>, LL_SC<0b100>; -+def STPTR_W : StPtr<"stptr.w", GPR64Opnd>, LL_SC<0b101>; -+def LDPTR_D : LdPtr<"ldptr.d", GPR64Opnd>, LL_SC<0b110>; -+def STPTR_D : StPtr<"stptr.d", GPR64Opnd>, LL_SC<0b111>; -+ -+def LD_B : Ld<"ld.b", GPR64Opnd, mem, sextloadi8>, LOAD_STORE<0b0000>; -+def LD_H : Ld<"ld.h", GPR64Opnd, mem, sextloadi16>, LOAD_STORE<0b0001>; -+def LD_W : Ld<"ld.w", GPR64Opnd, mem, sextloadi32>, LOAD_STORE<0b0010>; -+def LD_D : Ld<"ld.d", GPR64Opnd, mem_simmptr, load>, LOAD_STORE<0b0011>; -+def ST_B : St<"st.b", GPR64Opnd, mem, truncstorei8>, LOAD_STORE<0b0100>; -+def ST_H : St<"st.h", GPR64Opnd, mem, truncstorei16>, LOAD_STORE<0b0101>; -+def ST_W : St<"st.w", GPR64Opnd, mem, truncstorei32>, LOAD_STORE<0b0110>; -+def ST_D : St<"st.d", GPR64Opnd, mem_simmptr, store>, LOAD_STORE<0b0111>; -+def LD_BU : Ld<"ld.bu", GPR64Opnd, mem, zextloadi8>, LOAD_STORE<0b1000>; -+def LD_HU : Ld<"ld.hu", GPR64Opnd, mem, zextloadi16>, LOAD_STORE<0b1001>; -+def LD_WU : Ld<"ld.wu", GPR64Opnd, mem, zextloadi32>, LOAD_STORE<0b1010>; -+ -+def AMSWAP_W : ATOMIC<"amswap.w", GPR32Opnd, amem>, AM<0b000000>; -+def AMSWAP_D : ATOMIC<"amswap.d", GPR64Opnd, amem>, AM<0b000001>; -+def AMADD_W : ATOMIC<"amadd.w", GPR32Opnd, amem>, AM<0b000010>; -+def AMADD_D : ATOMIC<"amadd.d", GPR64Opnd, amem>, AM<0b000011>; -+def AMAND_W : ATOMIC<"amand.w", GPR32Opnd, amem>, AM<0b000100>; -+def AMAND_D : ATOMIC<"amand.d", GPR64Opnd, amem>, AM<0b000101>; -+def AMOR_W : ATOMIC<"amor.w", GPR32Opnd, amem>, AM<0b000110>; -+def AMOR_D : ATOMIC<"amor.d", GPR64Opnd, amem>, AM<0b000111>; -+def AMXOR_W : ATOMIC<"amxor.w", GPR32Opnd, amem>, AM<0b001000>; -+def AMXOR_D : ATOMIC<"amxor.d", GPR64Opnd, amem>, AM<0b001001>; -+def AMMAX_W : ATOMIC<"ammax.w", GPR32Opnd, amem>, AM<0b001010>; -+def AMMAX_D : ATOMIC<"ammax.d", GPR64Opnd, amem>, AM<0b001011>; -+def AMMIN_W : ATOMIC<"ammin.w", GPR32Opnd, amem>, AM<0b001100>; -+def AMMIN_D : ATOMIC<"ammin.d", GPR64Opnd, amem>, AM<0b001101>; -+def AMMAX_WU : ATOMIC<"ammax.wu", GPR32Opnd, amem>, AM<0b001110>; -+def AMMAX_DU : ATOMIC<"ammax.du", GPR64Opnd, amem>, AM<0b001111>; -+def AMMIN_WU : ATOMIC<"ammin.wu", GPR32Opnd, amem>, AM<0b010000>; -+def AMMIN_DU : ATOMIC<"ammin.du", GPR64Opnd, amem>, AM<0b010001>; -+ -+ -+def AMSWAP_DB_W : ATOMIC<"amswap_db.w", GPR32Opnd, amem>, AM<0b010010>; -+def AMSWAP_DB_D : ATOMIC<"amswap_db.d", GPR64Opnd, amem>, AM<0b010011>; -+def AMADD_DB_W : ATOMIC<"amadd_db.w", GPR32Opnd, amem>, AM<0b010100>; -+def AMADD_DB_D : ATOMIC<"amadd_db.d", GPR64Opnd, amem>, AM<0b010101>; -+def AMAND_DB_W : ATOMIC<"amand_db.w", GPR32Opnd, amem>, AM<0b010110>; -+def AMAND_DB_D : ATOMIC<"amand_db.d", GPR64Opnd, amem>, AM<0b010111>; -+def AMOR_DB_W : ATOMIC<"amor_db.w", GPR32Opnd, amem>, AM<0b011000>; -+def AMOR_DB_D : ATOMIC<"amor_db.d", GPR64Opnd, amem>, AM<0b011001>; -+def AMXOR_DB_W : ATOMIC<"amxor_db.w", GPR32Opnd, amem>, AM<0b011010>; -+def AMXOR_DB_D : ATOMIC<"amxor_db.d", GPR64Opnd, amem>, AM<0b011011>; -+def AMMAX_DB_W : ATOMIC<"ammax_db.w", GPR32Opnd, amem>, AM<0b011100>; -+def AMMAX_DB_D : ATOMIC<"ammax_db.d", GPR64Opnd, amem>, AM<0b011101>; -+def AMMIN_DB_W : ATOMIC<"ammin_db.w", GPR32Opnd, amem>, AM<0b011110>; -+def AMMIN_DB_D : ATOMIC<"ammin_db.d", GPR64Opnd, amem>, AM<0b011111>; -+def AMMAX_DB_WU : ATOMIC<"ammax_db.wu", GPR32Opnd, amem>, AM<0b100000>; -+def AMMAX_DB_DU : ATOMIC<"ammax_db.du", GPR64Opnd, amem>, AM<0b100001>; -+def AMMIN_DB_WU : ATOMIC<"ammin_db.wu", GPR32Opnd, amem>, AM<0b100010>; -+def AMMIN_DB_DU : ATOMIC<"ammin_db.du", GPR64Opnd, amem>, AM<0b100011>; -+ -+def LDGT_B : Int_Reg3<"ldgt.b", GPR64Opnd>, R3MI<0b11110000>; -+def LDGT_H : Int_Reg3<"ldgt.h", GPR64Opnd>, R3MI<0b11110001>; -+def LDGT_W : Int_Reg3<"ldgt.w", GPR64Opnd>, R3MI<0b11110010>; -+def LDGT_D : Int_Reg3<"ldgt.d", GPR64Opnd>, R3MI<0b11110011>; -+def LDLE_B : Int_Reg3<"ldle.b", GPR64Opnd>, R3MI<0b11110100>; -+def LDLE_H : Int_Reg3<"ldle.h", GPR64Opnd>, R3MI<0b11110101>; -+def LDLE_W : Int_Reg3<"ldle.w", GPR64Opnd>, R3MI<0b11110110>; -+def LDLE_D : Int_Reg3<"ldle.d", GPR64Opnd>, R3MI<0b11110111>; -+def STGT_B : STGT_LE<"stgt.b", GPR64Opnd>, R3MI<0b11111000>; -+def STGT_H : STGT_LE<"stgt.h", GPR64Opnd>, R3MI<0b11111001>; -+def STGT_W : STGT_LE<"stgt.w", GPR64Opnd>, R3MI<0b11111010>; -+def STGT_D : STGT_LE<"stgt.d", GPR64Opnd>, R3MI<0b11111011>; -+def STLE_B : STGT_LE<"stle.b", GPR64Opnd>, R3MI<0b11111100>; -+def STLE_H : STGT_LE<"stle.h", GPR64Opnd>, R3MI<0b11111101>; -+def STLE_W : STGT_LE<"stle.w", GPR64Opnd>, R3MI<0b11111110>; -+def STLE_D : STGT_LE<"stle.d", GPR64Opnd>, R3MI<0b11111111>; -+ -+let isCodeGenOnly = 1 in { -+def PRELD : Preld<"preld", mem, GPR64Opnd>, PRELD_FM; -+} -+ -+def PRELD_Raw : Preld_Raw<"preld", GPR64Opnd>, PRELD_FM; -+ -+let isCall=1, isCTI=1, Defs = [RA] in { -+ class JumpLink : -+ InstForm<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), -+ [(LoongArchJmpLink tglobaladdr:$target)], FrmJ, opstr> { -+ let DecoderMethod = "DecodeJumpTarget"; -+ } -+} -+def LONG_BRANCH_PCADDU12I : LoongArchPseudo<(outs GPR64Opnd:$dst), -+ (ins brtarget:$tgt), []>, GPR_64; -+ -+def LONG_BRANCH_ADDID2Op : LoongArchPseudo<(outs GPR64Opnd:$dst), -+ (ins GPR64Opnd:$src, brtarget:$tgt), []>, GPR_64; -+ -+def LONG_BRANCH_ADDID : LoongArchPseudo<(outs GPR64Opnd:$dst), -+ (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64; -+ -+def LEA_ADDI_D: EffectiveAddress<"addi.d", GPR64Opnd>, LEA_ADDI_FM<0b011>, GPR_64; -+ -+class PseudoReturnBase : LoongArchPseudo<(outs), (ins RO:$rs), -+ []> { - let isTerminator = 1; -+ let isBarrier = 1; -+ let isReturn = 1; -+ let isCodeGenOnly = 1; -+ let hasCtrlDep = 1; -+ let hasExtraSrcRegAllocReq = 1; -+ bit isCTI = 1; -+} -+ -+def PseudoReturn64 : PseudoReturnBase; -+//def PseudoReturn : PseudoReturnBase; -+ -+ -+let isCall=1, isCTI=1, Defs=[RA], isCodeGenOnly=1 in { -+def PseudoCall : LoongArchPseudo<(outs), (ins calltarget:$target), -+ []>; - } --class Br_I26 op, string opstr> -- : FmtI26 { -- let isBranch = 1; -+ -+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in -+def PseudoTailCall : LoongArchPseudo<(outs), (ins calltarget:$target), -+ []>; -+ -+class PseudoTailBase : LoongArchPseudo<(outs), (ins opnd:$offset26), -+ []> { - let isTerminator = 1; -+ let isBarrier = 1; -+ let isReturn = 1; -+ let isCodeGenOnly = 1; - } -+def PseudoTailReturn : PseudoTailBase; - --let mayLoad = 1 in { --class LOAD_3R op, string opstr> -- : Fmt3R; --class LOAD_2RI12 op, string opstr> -- : Fmt2RI12; --class LOAD_2RI14 op, string opstr> -- : Fmt2RI14; --} // mayLoad = 1 -- --let mayStore = 1 in { --class STORE_3R op, string opstr> -- : Fmt3R; --class STORE_2RI12 op, string opstr> -- : Fmt2RI12; --class STORE_2RI14 op, string opstr> -- : Fmt2RI14; --} // mayStore = 1 -- --let mayLoad = 1, mayStore = 1 in --class AM_3R op, string opstr> -- : Fmt3R; -- --let mayLoad = 1 in --class LLBase op, string opstr> -- : Fmt2RI14; -- --let mayStore = 1, Constraints = "$rd = $dst" in --class SCBase op, string opstr> -- : Fmt2RI14; -- --class IOCSRRD op, string opstr> -- : Fmt2R; -- --class IOCSRWR op, string opstr> -- : Fmt2R; - --//===----------------------------------------------------------------------===// --// Basic Integer Instructions --//===----------------------------------------------------------------------===// -+def : LoongArchPat<(LoongArchTailCall tglobaladdr:$dst), -+ (PseudoTailCall tglobaladdr:$dst)>; - --// Arithmetic Operation Instructions --def ADD_W : ALU_3R<0b00000000000100000, "add.w">; --def SUB_W : ALU_3R<0b00000000000100010, "sub.w">; --def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>; --def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>; --def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>; --def SLT : ALU_3R<0b00000000000100100, "slt">; --def SLTU : ALU_3R<0b00000000000100101, "sltu">; --def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>; --def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>; --def PCADDI : ALU_1RI20<0b0001100, "pcaddi", simm20>; --def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>; --def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20>; --def AND : ALU_3R<0b00000000000101001, "and">; --def OR : ALU_3R<0b00000000000101010, "or">; --def NOR : ALU_3R<0b00000000000101000, "nor">; --def XOR : ALU_3R<0b00000000000101011, "xor">; --def ANDN : ALU_3R<0b00000000000101101, "andn">; --def ORN : ALU_3R<0b00000000000101100, "orn">; --def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>; --def ORI : ALU_2RI12<0b0000001110, "ori", uimm12>; --def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>; --def MUL_W : ALU_3R<0b00000000000111000, "mul.w">; --def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">; --def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">; --let usesCustomInserter = true in { --def DIV_W : ALU_3R<0b00000000001000000, "div.w">; --def MOD_W : ALU_3R<0b00000000001000001, "mod.w">; --def DIV_WU : ALU_3R<0b00000000001000010, "div.wu">; --def MOD_WU : ALU_3R<0b00000000001000011, "mod.wu">; --} // usesCustomInserter = true -- --// Bit-shift Instructions --def SLL_W : ALU_3R<0b00000000000101110, "sll.w">; --def SRL_W : ALU_3R<0b00000000000101111, "srl.w">; --def SRA_W : ALU_3R<0b00000000000110000, "sra.w">; --def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">; -- --def SLLI_W : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>; --def SRLI_W : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>; --def SRAI_W : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>; --def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>; -- --// Bit-manipulation Instructions --def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">; --def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">; --def CLO_W : ALU_2R<0b0000000000000000000100, "clo.w">; --def CLZ_W : ALU_2R<0b0000000000000000000101, "clz.w">; --def CTO_W : ALU_2R<0b0000000000000000000110, "cto.w">; --def CTZ_W : ALU_2R<0b0000000000000000000111, "ctz.w">; --def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>; --def REVB_2H : ALU_2R<0b0000000000000000001100, "revb.2h">; --def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">; --def BITREV_W : ALU_2R<0b0000000000000000010100, "bitrev.w">; --let Constraints = "$rd = $dst" in { --def BSTRINS_W : FmtBSTR_W<0b000000000110, (outs GPR:$dst), -- (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw), -- "bstrins.w", "$rd, $rj, $msbw, $lsbw">; --} --def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd), -- (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw), -- "bstrpick.w", "$rd, $rj, $msbw, $lsbw">; --def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">; --def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">; -- --// Branch Instructions --def BEQ : BrCC_2RI16<0b010110, "beq">; --def BNE : BrCC_2RI16<0b010111, "bne">; --def BLT : BrCC_2RI16<0b011000, "blt">; --def BGE : BrCC_2RI16<0b011001, "bge">; --def BLTU : BrCC_2RI16<0b011010, "bltu">; --def BGEU : BrCC_2RI16<0b011011, "bgeu">; --def BEQZ : BrCCZ_1RI21<0b010000, "beqz">; --def BNEZ : BrCCZ_1RI21<0b010001, "bnez">; --def B : Br_I26<0b010100, "b">; -- --let isCall = 1 in --def BL : FmtI26<0b010101, (outs), (ins simm26_lsl2:$imm26), "bl", "$imm26">; --def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd), -- (ins GPR:$rj, simm16_lsl2:$imm16), "jirl", -- "$rd, $rj, $imm16">; -- --// Common Memory Access Instructions --def LD_B : LOAD_2RI12<0b0010100000, "ld.b">; --def LD_H : LOAD_2RI12<0b0010100001, "ld.h">; --def LD_W : LOAD_2RI12<0b0010100010, "ld.w">; --def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">; --def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">; --def ST_B : STORE_2RI12<0b0010100100, "st.b">; --def ST_H : STORE_2RI12<0b0010100101, "st.h">; --def ST_W : STORE_2RI12<0b0010100110, "st.w">; --def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld", -- "$imm5, $rj, $imm12">; -- --// Atomic Memory Access Instructions --def LL_W : LLBase<0b00100000, "ll.w">; --def SC_W : SCBase<0b00100001, "sc.w">; -- --// Barrier Instructions --def DBAR : MISC_I15<0b00111000011100100, "dbar">; --def IBAR : MISC_I15<0b00111000011100101, "ibar">; -- --// Other Miscellaneous Instructions --def SYSCALL : MISC_I15<0b00000000001010110, "syscall">; --def BREAK : MISC_I15<0b00000000001010100, "break">; --def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">; --def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">; --def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">; -- --/// LA64 instructions -- --let Predicates = [IsLA64] in { -- --// Arithmetic Operation Instructions for 64-bits --def ADD_D : ALU_3R<0b00000000000100001, "add.d">; --def SUB_D : ALU_3R<0b00000000000100011, "sub.d">; --def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>; --def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>; --def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>; --def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>; --let Constraints = "$rd = $dst" in { --def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst), -- (ins GPR:$rd, simm20:$imm20), "lu32i.d", -- "$rd, $imm20">; --} --def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>; --def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>; --def MUL_D : ALU_3R<0b00000000000111011, "mul.d">; --def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">; --def MULH_DU : ALU_3R<0b00000000000111101, "mulh.du">; --def MULW_D_W : ALU_3R<0b00000000000111110, "mulw.d.w">; --def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">; --let usesCustomInserter = true in { --def DIV_D : ALU_3R<0b00000000001000100, "div.d">; --def MOD_D : ALU_3R<0b00000000001000101, "mod.d">; --def DIV_DU : ALU_3R<0b00000000001000110, "div.du">; --def MOD_DU : ALU_3R<0b00000000001000111, "mod.du">; --} // usesCustomInserter = true -- --// Bit-shift Instructions for 64-bits --def SLL_D : ALU_3R<0b00000000000110001, "sll.d">; --def SRL_D : ALU_3R<0b00000000000110010, "srl.d">; --def SRA_D : ALU_3R<0b00000000000110011, "sra.d">; --def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">; --def SLLI_D : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>; --def SRLI_D : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>; --def SRAI_D : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>; --def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>; -- --// Bit-manipulation Instructions for 64-bits --def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">; --def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">; --def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">; --def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">; --def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>; --def REVB_4H : ALU_2R<0b0000000000000000001101, "revb.4h">; --def REVB_2W : ALU_2R<0b0000000000000000001110, "revb.2w">; --def REVB_D : ALU_2R<0b0000000000000000001111, "revb.d">; --def REVH_2W : ALU_2R<0b0000000000000000010000, "revh.2w">; --def REVH_D : ALU_2R<0b0000000000000000010001, "revh.d">; --def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">; --def BITREV_D : ALU_2R<0b0000000000000000010101, "bitrev.d">; --let Constraints = "$rd = $dst" in { --def BSTRINS_D : FmtBSTR_D<0b0000000010, (outs GPR:$dst), -- (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), -- "bstrins.d", "$rd, $rj, $msbd, $lsbd">; --} --def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd), -- (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd), -- "bstrpick.d", "$rd, $rj, $msbd, $lsbd">; -- --// Common Memory Access Instructions for 64-bits --def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">; --def LD_D : LOAD_2RI12<0b0010100011, "ld.d">; --def ST_D : STORE_2RI12<0b0010100111, "st.d">; --def LDX_B : LOAD_3R<0b00111000000000000, "ldx.b">; --def LDX_H : LOAD_3R<0b00111000000001000, "ldx.h">; --def LDX_W : LOAD_3R<0b00111000000010000, "ldx.w">; --def LDX_D : LOAD_3R<0b00111000000011000, "ldx.d">; --def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">; --def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">; --def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">; --def STX_B : STORE_3R<0b00111000000100000, "stx.b">; --def STX_H : STORE_3R<0b00111000000101000, "stx.h">; --def STX_W : STORE_3R<0b00111000000110000, "stx.w">; --def STX_D : STORE_3R<0b00111000000111000, "stx.d">; --def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">; --def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">; --def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">; --def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">; --def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx", -- "$imm5, $rj, $rk">; -- --// Bound Check Memory Access Instructions --def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">; --def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">; --def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">; --def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">; --def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">; --def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">; --def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">; --def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">; --def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">; --def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">; --def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">; --def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">; --def STLE_B : STORE_3R<0b00111000011111100, "stle.b">; --def STLE_H : STORE_3R<0b00111000011111101, "stle.h">; --def STLE_W : STORE_3R<0b00111000011111110, "stle.w">; --def STLE_D : STORE_3R<0b00111000011111111, "stle.d">; -- --// Atomic Memory Access Instructions for 64-bits --def AMSWAP_W : AM_3R<0b00111000011000000, "amswap.w">; --def AMSWAP_D : AM_3R<0b00111000011000001, "amswap.d">; --def AMADD_W : AM_3R<0b00111000011000010, "amadd.w">; --def AMADD_D : AM_3R<0b00111000011000011, "amadd.d">; --def AMAND_W : AM_3R<0b00111000011000100, "amand.w">; --def AMAND_D : AM_3R<0b00111000011000101, "amand.d">; --def AMOR_W : AM_3R<0b00111000011000110, "amor.w">; --def AMOR_D : AM_3R<0b00111000011000111, "amor.d">; --def AMXOR_W : AM_3R<0b00111000011001000, "amxor.w">; --def AMXOR_D : AM_3R<0b00111000011001001, "amxor.d">; --def AMMAX_W : AM_3R<0b00111000011001010, "ammax.w">; --def AMMAX_D : AM_3R<0b00111000011001011, "ammax.d">; --def AMMIN_W : AM_3R<0b00111000011001100, "ammin.w">; --def AMMIN_D : AM_3R<0b00111000011001101, "ammin.d">; --def AMMAX_WU : AM_3R<0b00111000011001110, "ammax.wu">; --def AMMAX_DU : AM_3R<0b00111000011001111, "ammax.du">; --def AMMIN_WU : AM_3R<0b00111000011010000, "ammin.wu">; --def AMMIN_DU : AM_3R<0b00111000011010001, "ammin.du">; --def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">; --def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">; --def AMADD_DB_W : AM_3R<0b00111000011010100, "amadd_db.w">; --def AMADD_DB_D : AM_3R<0b00111000011010101, "amadd_db.d">; --def AMAND_DB_W : AM_3R<0b00111000011010110, "amand_db.w">; --def AMAND_DB_D : AM_3R<0b00111000011010111, "amand_db.d">; --def AMOR_DB_W : AM_3R<0b00111000011011000, "amor_db.w">; --def AMOR_DB_D : AM_3R<0b00111000011011001, "amor_db.d">; --def AMXOR_DB_W : AM_3R<0b00111000011011010, "amxor_db.w">; --def AMXOR_DB_D : AM_3R<0b00111000011011011, "amxor_db.d">; --def AMMAX_DB_W : AM_3R<0b00111000011011100, "ammax_db.w">; --def AMMAX_DB_D : AM_3R<0b00111000011011101, "ammax_db.d">; --def AMMIN_DB_W : AM_3R<0b00111000011011110, "ammin_db.w">; --def AMMIN_DB_D : AM_3R<0b00111000011011111, "ammin_db.d">; --def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">; --def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">; --def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">; --def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">; --def LL_D : LLBase<0b00100010, "ll.d">; --def SC_D : SCBase<0b00100011, "sc.d">; -- --// CRC Check Instructions --def CRC_W_B_W : ALU_3R<0b00000000001001000, "crc.w.b.w">; --def CRC_W_H_W : ALU_3R<0b00000000001001001, "crc.w.h.w">; --def CRC_W_W_W : ALU_3R<0b00000000001001010, "crc.w.w.w">; --def CRC_W_D_W : ALU_3R<0b00000000001001011, "crc.w.d.w">; --def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">; --def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">; --def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">; --def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">; -- --// Other Miscellaneous Instructions for 64-bits --def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk), -- "asrtle.d", "$rj, $rk">; --def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk), -- "asrtgt.d", "$rj, $rk">; --def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">; --} // Predicates = [IsLA64] -+def : LoongArchPat<(LoongArchTailCall texternalsym:$dst), -+ (PseudoTailCall texternalsym:$dst)>; - --//===----------------------------------------------------------------------===// --// Pseudo-instructions and codegen patterns --// --// Naming convention: For 'generic' pattern classes, we use the naming --// convention PatTy1Ty2. --//===----------------------------------------------------------------------===// -+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, isIndirectBranch = 1, Uses = [SP] in -+def PseudoTAILIndirect : LoongArchPseudo<(outs), (ins GPRTC64Opnd:$rj), [(LoongArchTailCall GPRTC64Opnd:$rj)]>, -+ PseudoInstExpansion<(JIRL ZERO_64, GPR64Opnd:$rj, 0)>; - --/// Generic pattern classes -- --class PatGprGpr -- : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; --class PatGprGpr_32 -- : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; -- --class PatGprImm -- : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), -- (Inst GPR:$rj, ImmOpnd:$imm)>; --class PatGprImm_32 -- : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), -- (Inst GPR:$rj, ImmOpnd:$imm)>; -- --/// Simple arithmetic operations -- --// Match both a plain shift and one where the shift amount is masked (this is --// typically introduced when the legalizer promotes the shift amount and --// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the --// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64). --def shiftMaskGRLen -- : ComplexPattern; --def shiftMask32 : ComplexPattern; -- --def sexti32 : ComplexPattern; --def zexti32 : ComplexPattern; -- --class shiftop -- : PatFrag<(ops node:$val, node:$count), -- (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>; --class shiftopw -- : PatFrag<(ops node:$val, node:$count), -- (operator node:$val, (i64 (shiftMask32 node:$count)))>; -- --let Predicates = [IsLA32] in { --def : PatGprGpr; --def : PatGprImm; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --} // Predicates = [IsLA32] -- --let Predicates = [IsLA64] in { --def : PatGprGpr; --def : PatGprGpr_32; --def : PatGprImm; --def : PatGprImm_32; --def : PatGprGpr; --def : PatGprGpr_32; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the --// product are used. --def : PatGprGpr; --def : PatGprGpr; --def : PatGprGpr; --// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed --// multiplication. --def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))), -- (MULW_D_W GPR:$rj, GPR:$rk)>; --// Select MULW_D_WU for calculating the full 64 bits product of i32xi32 --// unsigned multiplication. --def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)), -- (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))), -- (MULW_D_WU GPR:$rj, GPR:$rk)>; --} // Predicates = [IsLA64] -- --def : PatGprGpr; --def : PatGprImm; --def : PatGprGpr; --def : PatGprImm; --def : PatGprGpr; --def : PatGprImm; -- --/// Shift -- --let Predicates = [IsLA32] in { --def : PatGprGpr, SLL_W>; --def : PatGprGpr, SRA_W>; --def : PatGprGpr, SRL_W>; --def : PatGprImm; --def : PatGprImm; --def : PatGprImm; --} // Predicates = [IsLA32] -- --let Predicates = [IsLA64] in { --def : PatGprGpr, SLL_W>; --def : PatGprGpr, SRA_W>; --def : PatGprGpr, SRL_W>; --def : PatGprGpr, SLL_D>; --def : PatGprGpr, SRA_D>; --def : PatGprGpr, SRL_D>; --def : PatGprImm; --def : PatGprImm; --def : PatGprImm; --} // Predicates = [IsLA64] -- --/// sext and zext -- --def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>; --def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>; -- --let Predicates = [IsLA64] in { --def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; --} // Predicates = [IsLA64] -- --/// Setcc -- --def : PatGprGpr; --def : PatGprImm; --def : PatGprGpr; --def : PatGprImm; -- --// Define pattern expansions for setcc operations that aren't directly --// handled by a LoongArch instruction. --def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>; --def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>; --let Predicates = [IsLA32] in { --def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), -- (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; --} // Predicates = [IsLA32] --let Predicates = [IsLA64] in { --def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), -- (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; --} // Predicates = [IsLA64] --def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>; --def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>; --let Predicates = [IsLA32] in { --def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), -- (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>; --} // Predicates = [IsLA32] --let Predicates = [IsLA64] in { --def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), -- (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>; --} // Predicates = [IsLA64] --def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>; --def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>; --def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>; --def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>; --def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>; --def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>; -- --/// Select -- --def : Pat<(select GPR:$cond, GPR:$t, GPR:$f), -- (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>; -- --/// Branches and jumps -- --class BccPat -- : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16), -- (Inst GPR:$rj, GPR:$rd, bb:$imm16)>; -- --def : BccPat; --def : BccPat; --def : BccPat; --def : BccPat; --def : BccPat; --def : BccPat; -- --class BccSwapPat -- : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16), -- (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>; -- --// Condition codes that don't have matching LoongArch branch instructions, but --// are trivially supported by swapping the two input operands. --def : BccSwapPat; --def : BccSwapPat; --def : BccSwapPat; --def : BccSwapPat; -- --// An extra pattern is needed for a brcond without a setcc (i.e. where the --// condition was calculated elsewhere). --def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>; -- --let isBarrier = 1, isBranch = 1, isTerminator = 1 in --def PseudoBR : Pseudo<(outs), (ins simm26_lsl2:$imm26), [(br bb:$imm26)]>, -- PseudoInstExpansion<(B simm26_lsl2:$imm26)>; -- --let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in --def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16), []>, -- PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; -- --def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>; --def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)), -- (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>; -- --let isCall = 1, Defs = [R1] in --def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { -- let AsmString = "bl\t$func"; --} -- --def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; --def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; -- --let isCall = 1, Defs = [R1] in --def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj), -- [(loongarch_call GPR:$rj)]>, -- PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; -- --let isBarrier = 1, isReturn = 1, isTerminator = 1 in --def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, -- PseudoInstExpansion<(JIRL R0, R1, 0)>; -- --/// BSTRINS and BSTRPICK -- --let Predicates = [IsLA32] in { --def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd), -- (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; --def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd), -- (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; --} // Predicates = [IsLA32] -- --let Predicates = [IsLA64] in { --def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), -- (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; --def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd), -- (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; --} // Predicates = [IsLA64] -- --/// Loads -- --multiclass LdPat { -- def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; -- def : Pat<(vt (LoadOp (add BaseAddr:$rj, simm12:$imm12))), -- (Inst BaseAddr:$rj, simm12:$imm12)>; --} -- --defm : LdPat; --defm : LdPat; --defm : LdPat; --defm : LdPat; --defm : LdPat, Requires<[IsLA32]>; --defm : LdPat; --defm : LdPat; --let Predicates = [IsLA64] in { --defm : LdPat; --defm : LdPat; --defm : LdPat; --defm : LdPat; --} // Predicates = [IsLA64] -- --/// Stores -- --multiclass StPat { -- def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), -- (Inst StTy:$rd, BaseAddr:$rj, 0)>; -- def : Pat<(StoreOp (vt StTy:$rd), (add BaseAddr:$rj, simm12:$imm12)), -- (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; --} -- --defm : StPat; --defm : StPat; --defm : StPat, Requires<[IsLA32]>; --let Predicates = [IsLA64] in { --defm : StPat; --defm : StPat; --} // Predicates = [IsLA64] -- --/// Atomic loads and stores -- --def : Pat<(atomic_fence timm, timm), (DBAR 0)>; -- --defm : LdPat; --defm : LdPat; --defm : LdPat; -- --defm : StPat; --defm : StPat; --defm : StPat, Requires<[IsLA32]>; --let Predicates = [IsLA64] in { --defm : LdPat; --defm : StPat; --defm : StPat; --} // Predicates = [IsLA64] -- --/// Other pseudo-instructions -- --// Pessimistically assume the stack pointer will be clobbered --let Defs = [R3], Uses = [R3] in { --def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), -- [(callseq_start timm:$amt1, timm:$amt2)]>; --def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), -- [(callseq_end timm:$amt1, timm:$amt2)]>; --} // Defs = [R3], Uses = [R3] - --//===----------------------------------------------------------------------===// --// Assembler Pseudo Instructions --//===----------------------------------------------------------------------===// -+def : LoongArchPat<(LoongArchJmpLink tglobaladdr:$dst), -+ (PseudoCall tglobaladdr:$dst)>; -+ -+def : LoongArchPat<(LoongArchJmpLink (i32 texternalsym:$dst)), -+ (PseudoCall texternalsym:$dst)>; -+def : LoongArchPat<(LoongArchJmpLink (i64 texternalsym:$dst)), -+ (PseudoCall texternalsym:$dst)>; -+ -+def : LoongArchPat<(LoongArchJmpLink (i64 texternalsym:$dst)), -+ (PseudoCall texternalsym:$dst)>; -+ -+def BL : JumpLink<"bl", calltarget>, FJ<0b010101>; -+ -+class IsAsCheapAsAMove { -+ bit isAsCheapAsAMove = 1; -+} -+class LoadUpper: -+ InstForm<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), -+ [], FrmI, opstr>, IsAsCheapAsAMove { -+ let hasSideEffects = 0; -+ let isReMaterializable = 1; -+ let mayLoad = 1; -+} -+ -+let isCodeGenOnly = 1 in { -+def LAPCREL : LoadUpper<"la.pcrel", GPR64Opnd, uimm16_64_relaxed>, LUI_FM, GPR_64; -+} -+ -+def NOP : LoongArchPseudo<(outs), (ins), []>, -+ PseudoInstExpansion<(ANDI ZERO_64, ZERO_64, 0)>; -+ -+def : LoongArchInstAlias<"nop", (ANDI ZERO_64, ZERO_64, 0), 1>; -+def : LoongArchInstAlias<"jr $rd", (JIRL ZERO_64, GPR64Opnd:$rd, 0), 1>; -+def : LoongArchInstAlias<"move $dst, $src", -+ (OR GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, GPR_64; -+ -+def UImm12RelaxedAsmOperandClass -+: UImmAsmOperandClass<12, [ConstantUImm20AsmOperandClass]> { -+ let Name = "UImm12_Relaxed"; -+ let PredicateMethod = "isAnyImm<12>"; -+ let DiagnosticType = "UImm12_Relaxed"; -+} -+ -+def SImm12RelaxedAsmOperandClass -+: SImmAsmOperandClass<12, [UImm12RelaxedAsmOperandClass]> { -+ let Name = "SImm12_Relaxed"; -+ let PredicateMethod = "isAnyImm<12>"; -+ let DiagnosticType = "SImm12_Relaxed"; -+} -+ -+def simm12_relaxed : Operand { -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; -+ let ParserMatchClass = !cast("SImm12RelaxedAsmOperandClass"); -+} -+ -+def : LoongArchPat<(i64 (anyext GPR32:$src)), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>,GPR_64; -+ -+let usesCustomInserter = 1 in { -+ def ATOMIC_LOAD_ADD_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_SUB_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_AND_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_OR_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_XOR_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_NAND_I64 : Atomic2Ops; -+ def ATOMIC_SWAP_I64 : Atomic2Ops; -+ def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap; -+ -+ def ATOMIC_LOAD_MAX_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_MIN_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_UMAX_I64 : Atomic2Ops; -+ def ATOMIC_LOAD_UMIN_I64 : Atomic2Ops; -+} -+ -+def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_SUB_I64_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_AND_I64_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_OR_I64_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_XOR_I64_POSTRA : Atomic2OpsPostRA; -+def ATOMIC_LOAD_NAND_I64_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA; -+ -+def ATOMIC_LOAD_MAX_I64_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_MIN_I64_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_UMAX_I64_POSTRA : Atomic2OpsPostRA; -+ -+def ATOMIC_LOAD_UMIN_I64_POSTRA : Atomic2OpsPostRA; -+ -+def : LoongArchPat<(atomic_load_8 addr:$a), (LD_B addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_load_16 addr:$a), (LD_H addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_load_32 addrimm14lsl2:$a), (LDPTR_W addrimm14lsl2:$a)>, GPR_64; -+def : LoongArchPat<(atomic_load_32 addr:$a), (LD_W addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_load_64 addrimm14lsl2:$a), (LDPTR_D addrimm14lsl2:$a)>, GPR_64; -+def : LoongArchPat<(atomic_load_64 addr:$a), (LD_D addr:$a)>, GPR_64; -+ -+def : LoongArchPat<(atomic_store_8 addr:$a, GPR64:$v), -+ (ST_B GPR64:$v, addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_store_16 addr:$a, GPR64:$v), -+ (ST_H GPR64:$v, addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_store_32 addrimm14lsl2:$a, GPR64:$v), -+ (STPTR_W GPR64:$v, addrimm14lsl2:$a)>, GPR_64; -+def : LoongArchPat<(atomic_store_32 addr:$a, GPR64:$v), -+ (ST_W GPR64:$v, addr:$a)>, GPR_64; -+def : LoongArchPat<(atomic_store_64 addrimm14lsl2:$a, GPR64:$v), -+ (STPTR_D GPR64:$v, addrimm14lsl2:$a)>, GPR_64; -+def : LoongArchPat<(atomic_store_64 addr:$a, GPR64:$v), -+ (ST_D GPR64:$v, addr:$a)>, GPR_64; -+ -+def : LoongArchPat<(bswap GPR64:$rt), (REVH_D (REVB_4H GPR64:$rt))>; -+ -+def immZExt5 : ImmLeaf; - --def : InstAlias<"nop", (ANDI R0, R0, 0)>; --def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; -+def immZExtRange2To64 : PatLeaf<(imm), [{ -+ return isUInt<7>(N->getZExtValue()) && (N->getZExtValue() >= 2) && -+ (N->getZExtValue() <= 64); -+}]>; -+ -+// bstrins and bstrpick -+class InsBase -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd, RO:$src), -+ !strconcat(opstr, "\t$rd, $rj, $msbd, $lsbd"), -+ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd, RO:$src))], -+ FrmR, opstr> { -+ let Constraints = "$src = $rd"; -+ } -+ -+class InsBase_32 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw, RO:$src), -+ !strconcat(opstr, "\t$rd, $rj, $msbw, $lsbw"), -+ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw, RO:$src))], -+ FrmR, opstr> { -+ let Constraints = "$src = $rd"; -+} -+ -+class PickBase -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd), -+ !strconcat(opstr, "\t$rd, $rj, $msbd, $lsbd"), -+ [(set RO:$rd, (Op RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd))], -+ FrmR, opstr>; -+ -+class PickBase_32 -+ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw), -+ !strconcat(opstr, "\t$rd, $rj, $msbw, $lsbw"), -+ [(set RO:$rd, (Op RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw))], -+ FrmR, opstr>; -+ -+ def BSTRINS_D : InsBase<"bstrins.d", GPR64Opnd, uimm6, LoongArchBstrins>, -+ INSERT_BIT64<0>; -+ def BSTRPICK_D : PickBase<"bstrpick.d", GPR64Opnd, uimm6, LoongArchBstrpick>, -+ INSERT_BIT64<1>; -+ -+let isCodeGenOnly = 1 in { -+ def ZEXT64_32 : InstForm<(outs GPR64Opnd:$rd), -+ (ins GPR32Opnd:$rj, uimm6:$msbd, -+ uimm6:$lsbd), -+ "bstrpick.d $rd, $rj, $msbd, $lsbd", [], FrmR, "bstrpick.d">, -+ INSERT_BIT64<1>; -+} -+ -+//32-to-64-bit extension -+def : LoongArchPat<(i64 (zext GPR32:$src)), (ZEXT64_32 GPR32:$src, 31, 0)>; -+def : LoongArchPat<(i64 (extloadi1 addr:$src)), (LD_B addr:$src)>, -+ GPR_64; -+def : LoongArchPat<(i64 (extloadi8 addr:$src)), (LD_B addr:$src)>, -+ GPR_64; -+def : LoongArchPat<(i64 (extloadi16 addr:$src)), (LD_H addr:$src)>, -+ GPR_64; -+def : LoongArchPat<(i64 (extloadi32 addr:$src)), (LD_W addr:$src)>, -+ GPR_64; -+ -+class LDX_FT_LA : -+ InstForm<(outs DRC:$rd), (ins PtrRC:$rj, PtrRC:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(set DRC:$rd, (OpNode (add iPTR:$rj, iPTR:$rk)))], -+ FrmR, opstr> { -+ let AddedComplexity = 20; -+ let canFoldAsLoad = 1; -+ string BaseOpcode = opstr; -+ let mayLoad = 1; -+} -+ -+class STX_FT_LA : -+ InstForm<(outs), (ins DRC:$rd, PtrRC:$rj, PtrRC:$rk), -+ !strconcat(opstr, "\t$rd, $rj, $rk"), -+ [(OpNode DRC:$rd, (add iPTR:$rj, iPTR:$rk))], -+ FrmI, opstr> { -+ string BaseOpcode = opstr; -+ let mayStore = 1; -+ let AddedComplexity = 20; -+} -+ -+ -+def LDX_B : LDX_FT_LA<"ldx.b", GPR64Opnd, sextloadi8>, -+ R3MI<0b00000000>; -+def LDX_H : LDX_FT_LA<"ldx.h", GPR64Opnd, sextloadi16>, -+ R3MI<0b00001000>; -+def LDX_W : LDX_FT_LA<"ldx.w", GPR64Opnd, sextloadi32>, -+ R3MI<0b00010000>; -+def LDX_D : LDX_FT_LA<"ldx.d", GPR64Opnd, load>, -+ R3MI<0b00011000>; -+def STX_B : STX_FT_LA<"stx.b", GPR64Opnd, truncstorei8>, -+ R3MI<0b00100000>; -+def STX_H : STX_FT_LA<"stx.h", GPR64Opnd, truncstorei16>, -+ R3MI<0b00101000>; -+def STX_W : STX_FT_LA<"stx.w", GPR64Opnd, truncstorei32>, -+ R3MI<0b00110000>; -+def STX_D : STX_FT_LA<"stx.d", GPR64Opnd, store>, -+ R3MI<0b00111000>; -+def LDX_BU : LDX_FT_LA<"ldx.bu", GPR64Opnd, extloadi8>, -+ R3MI<0b01000000>; -+def LDX_HU : LDX_FT_LA<"ldx.hu", GPR64Opnd, extloadi16>, -+ R3MI<0b01001000>; -+def LDX_WU : LDX_FT_LA<"ldx.wu", GPR64Opnd, zextloadi32>, -+ R3MI<0b01010000>; -+ -+//def : LoongArchPat<(bswap GPR64:$rj), (REVH_D (REVB_4H GPR64:$rj))>; -+//def : LoongArchPat<(bswap GPR64:$rj), (ROTRI_D (REVB_2W GPR64:$rj), 32)>; -+def : LoongArchPat<(bswap GPR64:$rj), (REVB_D GPR64:$rj)>; -+ -+let isCodeGenOnly = 1 in { -+ def SLLI_D_64_32 : Shift_Imm64<"", GPR64Opnd>, R2_IMM6<0b00>, GPR_64 { -+ let imm6 = 0; -+ let AsmString = "slli.d\t$rd, $rj, 32"; -+ let InOperandList = (ins GPR32:$rj); -+ let OutOperandList = (outs GPR64:$rd); -+ } -+ -+ let isMoveReg = 1, imm5 = 0, -+ AsmString = "slli.w\t$rd, $rj, 0", -+ OutOperandList = (outs GPR64:$rd) in { -+ let InOperandList = (ins GPR32:$rj) in -+ def SLLI_W_64_32 : Shift_Imm32<"", GPR32Opnd>, R2_IMM5<0b00>, GPR_64; -+ let InOperandList = (ins GPR64:$rj) in -+ def SLLI_W_64_64 : Shift_Imm32<"", GPR32Opnd>, R2_IMM5<0b00>, GPR_64; -+ } -+ -+ let AsmString = "sltui\t$rd, $rj, $imm12", -+ OutOperandList = (outs GPR64:$rd) in { -+ let InOperandList = (ins GPR64:$rj, simm12:$imm12) in -+ def SLTUI_64 : SetCC_I<"", GPR64Opnd, simm12>, R2_IMM12<0b001>, GPR_64; -+ } -+} -+ -+// 32-to-64-bit extension -+//def : LoongArchPat<(i64 (zext GPR32:$src)), (SRLI_D (SLLI_D_64_32 GPR32:$src), 32)>, GPR_64; -+def : LoongArchPat<(i64 (sext GPR32:$src)), (SLLI_W_64_32 GPR32:$src)>, GPR_64; -+def : LoongArchPat<(i64 (sext_inreg GPR64:$src, i32)), (SLLI_W_64_64 GPR64:$src)>, GPR_64; -+ -+let Uses = [A0, A1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { -+ def LoongArcheh_return32 : LoongArchPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), -+ [(LoongArchehret GPR32:$spoff, GPR32:$dst)]>; -+ def LoongArcheh_return64 : LoongArchPseudo<(outs), (ins GPR64:$spoff,GPR64:$dst), -+ [(LoongArchehret GPR64:$spoff, GPR64:$dst)]>; -+} -+ -+def : LoongArchPat<(select i32:$cond, i64:$t, i64:$f), -+ (OR (MASKEQZ i64:$t, (SLLI_W_64_32 i32:$cond)), -+ (MASKNEZ i64:$f, (SLLI_W_64_32 i32:$cond)))>; -+// setcc patterns -+multiclass SeteqPats { -+ def : LoongArchPat<(seteq RC:$lhs, 0), -+ (SLTiuOp RC:$lhs, 1)>; -+ def : LoongArchPat<(setne RC:$lhs, 0), -+ (SLTuOp ZEROReg, RC:$lhs)>; -+ def : LoongArchPat<(seteq RC:$lhs, RC:$rhs), -+ (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>; -+ def : LoongArchPat<(setne RC:$lhs, RC:$rhs), -+ (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; -+} -+ -+multiclass SetlePats { -+ def : LoongArchPat<(setle RC:$lhs, RC:$rhs), -+ (XORiOp (SLTOp RC:$rhs, RC:$lhs), 1)>; -+ def : LoongArchPat<(setule RC:$lhs, RC:$rhs), -+ (XORiOp (SLTuOp RC:$rhs, RC:$lhs), 1)>; -+} -+ -+multiclass SetgtPats { -+ def : LoongArchPat<(setgt RC:$lhs, RC:$rhs), -+ (SLTOp RC:$rhs, RC:$lhs)>; -+ def : LoongArchPat<(setugt RC:$lhs, RC:$rhs), -+ (SLTuOp RC:$rhs, RC:$lhs)>; -+} -+ -+multiclass SetgePats { -+ def : LoongArchPat<(setge RC:$lhs, RC:$rhs), -+ (XORiOp (SLTOp RC:$lhs, RC:$rhs), 1)>; -+ def : LoongArchPat<(setuge RC:$lhs, RC:$rhs), -+ (XORiOp (SLTuOp RC:$lhs, RC:$rhs), 1)>; -+} -+ -+multiclass SetgeImmPats { -+ def : LoongArchPat<(setge RC:$lhs, immSExt12:$rhs), -+ (XORiOp (SLTiOp RC:$lhs, immSExt12:$rhs), 1)>; -+ def : LoongArchPat<(setuge RC:$lhs, immSExt12:$rhs), -+ (XORiOp (SLTiuOp RC:$lhs, immSExt12:$rhs), 1)>; -+} -+ -+class LoadRegImmPat : -+ LoongArchPat<(ValTy (Node addrRegImm:$a)), (LoadInst addrRegImm:$a)>; -+ -+class StoreRegImmPat : -+ LoongArchPat<(Node ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>; -+ -+class LoadRegImm14Lsl2Pat : -+ LoongArchPat<(ValTy (Node addrimm14lsl2:$a)), (LoadInst addrimm14lsl2:$a)>; -+ -+class StoreRegImm14Lsl2Pat : -+ LoongArchPat<(Node ValTy:$v, addrimm14lsl2:$a), (StoreInst ValTy:$v, addrimm14lsl2:$a)>; -+ -+// Patterns for loads/stores with a reg+imm operand. -+// let AddedComplexity = 40 so that these instructions are selected instead of -+// LDX/STX which needs one more register and an ANDI instruction. -+let AddedComplexity = 40 in { -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : LoadRegImmPat; -+ def : StoreRegImmPat; -+ def : StoreRegImmPat; -+ def : StoreRegImmPat; -+ def : StoreRegImmPat; -+ -+ def : LoadRegImm14Lsl2Pat; -+ def : LoadRegImm14Lsl2Pat; -+ def : StoreRegImm14Lsl2Pat; -+ def : StoreRegImm14Lsl2Pat; -+} - - //===----------------------------------------------------------------------===// --// Basic Floating-Point Instructions -+// Base Extension Support - //===----------------------------------------------------------------------===// - --include "LoongArchFloat32InstrInfo.td" --include "LoongArchFloat64InstrInfo.td" -+include "LoongArch32InstrInfo.td" -+include "LoongArchInstrInfoF.td" -+include "LoongArchLSXInstrFormats.td" -+include "LoongArchLSXInstrInfo.td" -+include "LoongArchLASXInstrFormats.td" -+include "LoongArchLASXInstrInfo.td" -+ -+defm : SeteqPats, GPR_64; -+defm : SetlePats, GPR_64; -+defm : SetgtPats, GPR_64; -+defm : SetgePats, GPR_64; -+defm : SetgeImmPats, GPR_64; -+ -+/// -+/// for relocation -+/// -+let isCodeGenOnly = 1 in { -+def PCADDU12I_ri : SI20<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; -+def PCADDU12I_rii : RELOC_rii<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; -+def ORI_rri : Int_Reg2_Imm12<"ori", GPR64Opnd, uimm12, or>, R2_IMM12<0b110>; -+def ORI_rrii : RELOC_rrii<"ori", GPR64Opnd, uimm12>, R2_IMM12<0b110>; -+def LU12I_W_ri : SI20<"lu12i.w", GPR64Opnd, simm20>, R1_SI20<0b0001010>; -+def LU32I_D_ri : SI20<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; -+def LU32I_D_rii : RELOC_rii<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; -+def LU52I_D_rri : Int_Reg2_Imm12<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; -+def LU52I_D_rrii : RELOC_rrii<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; -+def ADDI_D_rri : Int_Reg2_Imm12<"addi.d", GPR64Opnd, simm12, add>, R2_IMM12<0b011>; -+def ADDI_D_rrii : RELOC_rrii<"addi.d", GPR64Opnd, simm12>, R2_IMM12<0b011>; -+def LD_D_rri : Ld<"ld.d", GPR64Opnd, mem_simmptr, load>, LOAD_STORE<0b0011>; -+def LD_D_rrii : RELOC_rrii<"ld.d", GPR64Opnd, simm12>, LOAD_STORE_RRI<0b0011>; -+def ADD_D_rrr : Int_Reg3<"add.d", GPR64Opnd, add>, R3I<0b0100001>; -+def LDX_D_rrr : LDX_FT_LA<"ldx.d", GPR64Opnd, load>, -+ R3MI<0b00011000>; -+} - - //===----------------------------------------------------------------------===// --// Privilege Instructions -+// Assembler Pseudo Instructions - //===----------------------------------------------------------------------===// -- --// CSR Access Instructions --def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num), -- "csrrd", "$rd, $csr_num">; --let Constraints = "$rd = $dst" in { --def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst), -- (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">; --def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst), -- (ins GPR:$rd, GPR:$rj, uimm14:$csr_num), -- "csrxchg", "$rd, $rj, $csr_num">; --} // Constraints = "$rd = $dst" -- --// IOCSR Access Instructions --def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">; --def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">; --def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">; --def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">; --def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">; --def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">; --let Predicates = [IsLA64] in { --def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">; --def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">; --} // Predicates = [IsLA64] -- --// Cache Maintenance Instructions --def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop", -- "$op, $rj, $imm12">; -- --// TLB Maintenance Instructions --def TLBSRCH : FmtI32<0b00000110010010000010100000000000, "tlbsrch">; --def TLBRD : FmtI32<0b00000110010010000010110000000000, "tlbrd">; --def TLBWR : FmtI32<0b00000110010010000011000000000000, "tlbwr">; --def TLBFILL : FmtI32<0b00000110010010000011010000000000, "tlbfill">; --def TLBCLR : FmtI32<0b00000110010010000010000000000000, "tlbclr">; --def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">; --def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb", -- "$op, $rj, $rk">; -- --// Software Page Walking Instructions --def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd), -- (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">; --def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">; -- -- --// Other Miscellaneous Instructions --def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">; --def DBCL : MISC_I15<0b00000000001010101, "dbcl">; --def IDLE : MISC_I15<0b00000110010010001, "idle">; -+def LoadImm32 : LoongArchAsmPseudoInst<(outs GPR32Opnd:$rd), -+ (ins uimm32_coerced:$imm32), -+ "li.w\t$rd, $imm32">; -+def LoadImm64 : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "li.d\t$rd, $imm64">; -+// load address -+def LoadAddrLocal : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.local\t$rd, $imm64">; -+def : InstAlias<"la.pcrel $rd, $imm", -+ (LoadAddrLocal GPR64Opnd:$rd, imm64:$imm), 1>; -+def LoadAddrGlobal : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.global\t$rd, $imm64">; -+def LoadAddrGlobal_Alias : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la\t$rd, $imm64">; -+def : InstAlias<"la.got $rd, $imm", -+ (LoadAddrGlobal GPR64Opnd:$rd, imm64:$imm), 1>; -+ -+def LoadAddrTLS_LE : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.tls.le\t$rd, $imm64">; -+def LoadAddrTLS_IE : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.tls.ie\t$rd, $imm64">; -+def LoadAddrTLS_GD : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.tls.gd\t$rd, $imm64">; -+def LoadAddrTLS_LD : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins imm64:$imm64), -+ "la.tls.ld\t$rd, $imm64">; -+ -+// load address with a temp reg -+def LoadAddrLocalRR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins GPR64Opnd:$rt, imm64:$imm64), -+ "la.local\t$rd, $rt, $imm64">; -+def LoadAddrGlobalRR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins GPR64Opnd:$rt, imm64:$imm64), -+ "la.global\t$rd, $rt, $imm64">; -+def LoadAddrTLS_IE_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins GPR64Opnd:$rt, imm64:$imm64), -+ "la.tls.ie\t$rd, $rt, $imm64">; -+def LoadAddrTLS_GD_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins GPR64Opnd:$rt, imm64:$imm64), -+ "la.tls.gd\t$rd, $rt, $imm64">; -+def LoadAddrTLS_LD_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), -+ (ins GPR64Opnd:$rt, imm64:$imm64), -+ "la.tls.ld\t$rd, $rt, $imm64">; -+ -+// trap when div zero -+def PseudoTEQ : LoongArchPseudo<(outs), (ins GPR64Opnd:$rt), []>; -+ -+ -+def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, immSExt12:$imm12)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ADDI_W GPR32:$src, immSExt12:$imm12), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (ADD_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SUB_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (MUL_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SLLI_W GPR32:$src, immZExt5:$imm5), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SLL_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRLI_W GPR32:$src, immZExt5:$imm5), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRL_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRAI_W GPR32:$src, immZExt5:$imm5), sub_32)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))), -+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), -+ (SRA_W GPR32:$src, GPR32:$src2), sub_32)>; -+ -+ -+def : LoongArchPat<(i64 (xor GPR64:$rj, (i64 -1))), -+ (NOR ZERO_64, GPR64:$rj)>; -+ -+def : LoongArchPat<(and GPR64:$rj, (i64 (xor GPR64:$rk, (i64 -1)))), -+ (ANDN GPR64:$rj, GPR64:$rk)>; -+ -+def : LoongArchPat<(i64 (or GPR64:$rj, (xor GPR64:$rk, (i64 -1)))), -+ (ORN GPR64:$rj, GPR64:$rk)>; -+ -+def : LoongArchPat<(i64 (zext (i32 (seteq GPR64:$rj, (i64 0))))), -+ (SLTUI_64 GPR64:$rj, (i64 1))>; -+ -+ -+def : LoongArchPat<(i64 (zext (i32 (srl GPR32:$src, immZExt5:$imm5)))), -+ (BSTRPICK_D (INSERT_SUBREG -+ (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32), -+ (i32 31), immZExt5:$imm5)>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td -new file mode 100644 -index 000000000..4df5fc88e ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td -@@ -0,0 +1,630 @@ -+//===- LoongArchInstrInfoF.td - Target Description for LoongArch Target -*- tablegen -*-=// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file contains the LoongArch implementation of the TargetInstrInfo class. -+// -+//===----------------------------------------------------------------------===// -+// FP immediate patterns. -+def fpimm0 : PatLeaf<(fpimm), [{ -+ return N->isExactlyValue(+0.0); -+}]>; -+ -+def fpimm0neg : PatLeaf<(fpimm), [{ -+ return N->isExactlyValue(-0.0); -+}]>; -+ -+def fpimm1 : PatLeaf<(fpimm), [{ -+ return N->isExactlyValue(+1.0); -+}]>; -+ -+def IsNotSoftFloat : Predicate<"!Subtarget->useSoftFloat()">, -+ AssemblerPredicate<(all_of FeatureSoftFloat)>; -+ -+class HARDFLOAT { list HardFloatPredicate = [IsNotSoftFloat]; } -+ -+def SDT_LoongArchTruncIntFP : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>; -+ -+def LoongArchTruncIntFP : SDNode<"LoongArchISD::TruncIntFP", SDT_LoongArchTruncIntFP>; -+ -+def SDT_LoongArchFPBrcond : SDTypeProfile<0, 3, [SDTCisInt<0>, -+ SDTCisVT<1, i32>, -+ SDTCisVT<2, OtherVT>]>; -+ -+def LoongArchFPBrcond : SDNode<"LoongArchISD::FPBrcond", SDT_LoongArchFPBrcond, -+ [SDNPHasChain, SDNPOptInGlue]>; -+ -+def SDT_LoongArchCMovFP : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, i32>, -+ SDTCisSameAs<1, 3>]>; -+ -+def LoongArchCMovFP_T : SDNode<"LoongArchISD::CMovFP_T", SDT_LoongArchCMovFP, [SDNPInGlue]>; -+ -+def LoongArchCMovFP_F : SDNode<"LoongArchISD::CMovFP_F", SDT_LoongArchCMovFP, [SDNPInGlue]>; -+ -+def SDT_LoongArchFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, -+ SDTCisVT<2, i32>]>; -+ -+def LoongArchFPCmp : SDNode<"LoongArchISD::FPCmp", SDT_LoongArchFPCmp, [SDNPOutGlue]>; -+ -+def SDT_LoongArchFSEL : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, -+ SDTCisVT<2, i32>, -+ SDTCisSameAs<1, 3>]>; -+ -+def LoongArchFSEL : SDNode<"LoongArchISD::FSEL", SDT_LoongArchFSEL, -+ [SDNPInGlue]>; -+ -+//===---------------------------------------------------------------------===/ -+//Instruction Class Templates -+//===---------------------------------------------------------------------===/ -+ -+class Float_MOVF -+ : InstForm<(outs RO:$rd), (ins RC:$fj), -+ !strconcat(opstr, "\t$rd, $fj"), -+ [(set RO:$rd, (OpNode RC:$fj))], -+ FrmFR, opstr>, HARDFLOAT { -+ let isMoveReg = 1; -+} -+ -+class Float_MOVT -+ : InstForm<(outs RO:$fd), (ins RC:$rj), -+ !strconcat(opstr, "\t$fd, $rj"), -+ [(set RO:$fd, (OpNode RC:$rj))], -+ FrmFR, opstr>, HARDFLOAT { -+ let isMoveReg = 1; -+} -+ -+class Float_CVT -+ : InstForm<(outs RO:$fd), (ins RS:$fj), -+ !strconcat(opstr, "\t$fd, $fj"), -+ [(set RO:$fd, (OpNode RS:$fj))], -+ FrmFR, opstr>, -+ HARDFLOAT { -+ let hasSideEffects = 0; -+} -+ -+/// float mov -+class Gpr_2_Fcsr -+ : InstForm<(outs FCSROpnd:$fcsr), (ins RO:$rj), -+ !strconcat(opstr, "\t$fcsr, $rj"), -+ [(set FCSROpnd:$fcsr, (OpNode RO:$rj))], -+ FrmR, opstr>; -+class Fcsr_2_Gpr -+ : InstForm<(outs RO:$rd), (ins FCSROpnd:$fcsr), -+ !strconcat(opstr, "\t$rd, $fcsr"), -+ [(set RO:$rd, (OpNode FCSROpnd:$fcsr))], -+ FrmR, opstr>; -+class Fgr_2_Fcfr -+ : InstForm<(outs FCFROpnd:$cd), (ins RO:$fj), -+ !strconcat(opstr, "\t$cd, $fj"), -+ [(set FCFROpnd:$cd, (OpNode RO:$fj))], -+ FrmR, opstr>; -+class Fcfr_2_Fgr -+ : InstForm<(outs RO:$fd), (ins FCFROpnd:$cj), -+ !strconcat(opstr, "\t$fd, $cj"), -+ [(set RO:$fd, (OpNode FCFROpnd:$cj))], -+ FrmR, opstr>; -+class Gpr_2_Fcfr -+ : InstForm<(outs FCFROpnd:$cd), (ins RO:$rj), -+ !strconcat(opstr, "\t$cd, $rj"), -+ [(set FCFROpnd:$cd, (OpNode RO:$rj))], -+ FrmR, opstr>; -+class Fcfr_2_Gpr -+ : InstForm<(outs RO:$rd), (ins FCFROpnd:$cj), -+ !strconcat(opstr, "\t$rd, $cj"), -+ [(set RO:$rd, (OpNode FCFROpnd:$cj))], -+ FrmR, opstr>; -+ -+class FLDX : -+ InstForm<(outs DRC:$fd), (ins PtrRC:$rj, PtrRC:$rk), -+ !strconcat(opstr, "\t$fd, $rj, $rk"), -+ [(set DRC:$fd, (OpNode (add iPTR:$rj, iPTR:$rk)))], -+ FrmR, opstr> { -+ let AddedComplexity = 20; -+} -+ -+class FSTX : -+ InstForm<(outs), (ins DRC:$fd, PtrRC:$rj, PtrRC:$rk), -+ !strconcat(opstr, "\t$fd, $rj, $rk"), -+ [(OpNode DRC:$fd, (add iPTR:$rj, iPTR:$rk))], -+ FrmR, opstr> { -+ let AddedComplexity = 20; -+} -+ -+/// f{maxa/mina}.{s/d} -+class Float_Reg3_Fmaxa -+ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), -+ !strconcat(opstr, "\t$fd, $fj, $fk"), -+ [], FrmR, opstr>; -+/// frecip -+class Float_Reg2_Frecip -+ : InstForm<(outs RO:$fd), (ins RO:$fj), -+ !strconcat(opstr, "\t$fd, $fj"), -+ [(set RO:$fd, (OpNode fpimm1, RO:$fj))], -+ FrmR, opstr>; -+/// frsqrt -+class Float_Reg2_Frsqrt -+ : InstForm<(outs RO:$fd), (ins RO:$fj), -+ !strconcat(opstr, "\t$fd, $fj"), -+ [(set RO:$fd, (OpNode fpimm1, (fsqrt RO:$fj)))], -+ FrmR, opstr>; -+ -+class BceqzBr : -+ InstForm<(outs), (ins FCFROpnd:$cj, opnd:$offset), -+ !strconcat(opstr, "\t$cj, $offset"), -+ [(LoongArchFPBrcond Op, FCFROpnd:$cj, bb:$offset)], -+ FrmFI, opstr>, HARDFLOAT { -+ let isBranch = 1; -+ let isTerminator = 1; -+ let hasFCCRegOperand = 1; -+} -+ -+class FCMP_COND -+ : InstForm<(outs FCFROpnd:$cd), (ins RO:$fj, RO:$fk), -+ !strconcat("fcmp.", CondStr, ".", TypeStr, "\t$cd, $fj, $fk"), -+ [(set FCFROpnd:$cd, (OpNode RO:$fj, RO:$fk))], -+ FrmOther, -+ !strconcat("fcmp.", CondStr, ".", TypeStr)> { -+ bit isCTI = 1; // for what? from Mips32r6InstrInfo.td line 219 -+} -+ -+class FIELD_CMP_COND Val> { -+ bits<5> Value = Val; -+} -+def FIELD_CMP_COND_CAF : FIELD_CMP_COND<0x0>; -+def FIELD_CMP_COND_CUN : FIELD_CMP_COND<0x8>; -+def FIELD_CMP_COND_CEQ : FIELD_CMP_COND<0x4>; -+def FIELD_CMP_COND_CUEQ : FIELD_CMP_COND<0xC>; -+def FIELD_CMP_COND_CLT : FIELD_CMP_COND<0x2>; -+def FIELD_CMP_COND_CULT : FIELD_CMP_COND<0xA>; -+def FIELD_CMP_COND_CLE : FIELD_CMP_COND<0x6>; -+def FIELD_CMP_COND_CULE : FIELD_CMP_COND<0xE>; -+def FIELD_CMP_COND_CNE : FIELD_CMP_COND<0x10>; -+def FIELD_CMP_COND_COR : FIELD_CMP_COND<0x14>; -+def FIELD_CMP_COND_CUNE : FIELD_CMP_COND<0x18>; -+def FIELD_CMP_COND_SAF : FIELD_CMP_COND<0x1>; -+def FIELD_CMP_COND_SUN : FIELD_CMP_COND<0x9>; -+def FIELD_CMP_COND_SEQ : FIELD_CMP_COND<0x5>; -+def FIELD_CMP_COND_SUEQ : FIELD_CMP_COND<0xD>; -+def FIELD_CMP_COND_SLT : FIELD_CMP_COND<0x3>; -+def FIELD_CMP_COND_SULT : FIELD_CMP_COND<0xB>; -+def FIELD_CMP_COND_SLE : FIELD_CMP_COND<0x7>; -+def FIELD_CMP_COND_SULE : FIELD_CMP_COND<0xF>; -+def FIELD_CMP_COND_SNE : FIELD_CMP_COND<0x11>; -+def FIELD_CMP_COND_SOR : FIELD_CMP_COND<0x15>; -+def FIELD_CMP_COND_SUNE : FIELD_CMP_COND<0x19>; -+ -+multiclass FCMP_COND_M op, string TypeStr, -+ RegisterOperand RO> { -+ def FCMP_CAF_#NAME : FCMP_COND<"caf", TypeStr, RO>, -+ R2_COND; -+ def FCMP_CUN_#NAME : FCMP_COND<"cun", TypeStr, RO, setuo>, -+ R2_COND; -+ def FCMP_CEQ_#NAME : FCMP_COND<"ceq", TypeStr, RO, setoeq>, -+ R2_COND; -+ def FCMP_CUEQ_#NAME : FCMP_COND<"cueq", TypeStr, RO, setueq>, -+ R2_COND; -+ def FCMP_CLT_#NAME : FCMP_COND<"clt", TypeStr, RO, setolt>, -+ R2_COND; -+ def FCMP_CULT_#NAME : FCMP_COND<"cult", TypeStr, RO, setult>, -+ R2_COND; -+ def FCMP_CLE_#NAME : FCMP_COND<"cle", TypeStr, RO, setole>, -+ R2_COND; -+ def FCMP_CULE_#NAME : FCMP_COND<"cule", TypeStr, RO, setule>, -+ R2_COND; -+ def FCMP_CNE_#NAME : FCMP_COND<"cne", TypeStr, RO, setone>, -+ R2_COND; -+ def FCMP_COR_#NAME : FCMP_COND<"cor", TypeStr, RO, seto>, -+ R2_COND; -+ def FCMP_CUNE_#NAME : FCMP_COND<"cune", TypeStr, RO, setune>, -+ R2_COND; -+ -+ def FCMP_SAF_#NAME : FCMP_COND<"saf", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SUN_#NAME : FCMP_COND<"sun", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SEQ_#NAME : FCMP_COND<"seq", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SUEQ_#NAME : FCMP_COND<"sueq", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SLT_#NAME : FCMP_COND<"slt", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SULT_#NAME : FCMP_COND<"sult", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SLE_#NAME : FCMP_COND<"sle", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SULE_#NAME : FCMP_COND<"sule", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SNE_#NAME : FCMP_COND<"sne", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SOR_#NAME : FCMP_COND<"sor", TypeStr, RO>, -+ R2_COND; -+ def FCMP_SUNE_#NAME : FCMP_COND<"sune", TypeStr, RO>, -+ R2_COND; -+} -+ -+//// comparisons supported via another comparison -+//multiclass FCmp_Pats { -+// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), -+// (!cast("FCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), -+// (!cast("FCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), -+// (!cast("FCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), -+// (!cast("FCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), -+// (!cast("FCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), -+// (NOROp -+// (!cast("FCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), -+// ZEROReg)>; -+//} -+ -+ -+/// -+/// R2 -+/// -+def FABS_S : Float_Reg2<"fabs.s", FGR32Opnd, fabs>, R2F<0b0100000001>; -+def FABS_D : Float_Reg2<"fabs.d", FGR64Opnd, fabs>, R2F<0b0100000010>; -+def FNEG_S : Float_Reg2<"fneg.s", FGR32Opnd, fneg>, R2F<0b0100000101>; -+def FNEG_D : Float_Reg2<"fneg.d", FGR64Opnd, fneg>, R2F<0b0100000110>; -+def FLOGB_S : Float_Reg2<"flogb.s", FGR32Opnd>, R2F<0b0100001001>; -+def FLOGB_D : Float_Reg2<"flogb.d", FGR64Opnd>, R2F<0b0100001010>; -+def FCLASS_S : Float_Reg2<"fclass.s", FGR32Opnd>, R2F<0b0100001101>; -+def FCLASS_D : Float_Reg2<"fclass.d", FGR64Opnd>, R2F<0b0100001110>; -+def FSQRT_S : Float_Reg2<"fsqrt.s", FGR32Opnd, fsqrt>, R2F<0b0100010001>; -+def FSQRT_D : Float_Reg2<"fsqrt.d", FGR64Opnd, fsqrt>, R2F<0b0100010010>; -+def FRECIP_S : Float_Reg2_Frecip<"frecip.s", FGR32Opnd, fdiv>, R2F<0b0100010101>; -+def FRECIP_D : Float_Reg2_Frecip<"frecip.d", FGR64Opnd, fdiv>, R2F<0b0100010110>; -+def FRSQRT_S : Float_Reg2_Frsqrt<"frsqrt.s", FGR32Opnd, fdiv>, R2F<0b0100011001>; -+def FRSQRT_D : Float_Reg2_Frsqrt<"frsqrt.d", FGR64Opnd, fdiv>, R2F<0b0100011010>; -+def FMOV_S : Float_Reg2<"fmov.s", FGR32Opnd>, R2F<0b0100100101>; -+def FMOV_D : Float_Reg2<"fmov.d", FGR64Opnd>, R2F<0b0100100110>; -+ -+def MOVGR2FR_W : Float_MOVT<"movgr2fr.w", FGR32Opnd, GPR32Opnd, bitconvert>, MOVFI<0b0100101001>; -+def MOVGR2FR_D : Float_MOVT<"movgr2fr.d", FGR64Opnd, GPR64Opnd, bitconvert>, MOVFI<0b0100101010>; -+def MOVGR2FRH_W : Float_MOVT<"movgr2frh.w", FGR64Opnd, GPR32Opnd>, MOVFI<0b0100101011>; //not realize -+def MOVFR2GR_S : Float_MOVF<"movfr2gr.s", GPR32Opnd, FGR32Opnd, bitconvert>, MOVIF<0b0100101101>; -+def MOVFR2GR_D : Float_MOVF<"movfr2gr.d", GPR64Opnd, FGR64Opnd, bitconvert>, MOVIF<0b0100101110>; -+def MOVFRH2GR_S : Float_MOVF<"movfrh2gr.s", GPR32Opnd, FGR32Opnd>, MOVIF<0b0100101111>; //not realize -+ -+let isCodeGenOnly = 1 in { -+ def MOVFR2GR_DS : Float_MOVF<"movfr2gr.s", GPR64Opnd, FGR32Opnd>, MOVIF<0b0100101101>; -+} -+ -+def FCVT_S_D : Float_CVT<"fcvt.s.d", FGR32Opnd, FGR64Opnd>, R2F<0b1001000110>; -+def FCVT_D_S : Float_CVT<"fcvt.d.s", FGR64Opnd, FGR32Opnd>, R2F<0b1001001001>; -+ -+def FTINTRM_W_S : Float_Reg2<"ftintrm.w.s", FGR32Opnd>, R2F<0b1010000001>; -+def FTINTRM_W_D : Float_Reg2<"ftintrm.w.d", FGR64Opnd>, R2F<0b1010000010>; -+def FTINTRM_L_S : Float_Reg2<"ftintrm.l.s", FGR32Opnd>, R2F<0b1010001001>; -+def FTINTRM_L_D : Float_Reg2<"ftintrm.l.d", FGR64Opnd>, R2F<0b1010001010>; -+def FTINTRP_W_S : Float_Reg2<"ftintrp.w.s", FGR32Opnd>, R2F<0b1010010001>; -+def FTINTRP_W_D : Float_Reg2<"ftintrp.w.d", FGR64Opnd>, R2F<0b1010010010>; -+def FTINTRP_L_S : Float_Reg2<"ftintrp.l.s", FGR32Opnd>, R2F<0b1010011001>; -+def FTINTRP_L_D : Float_Reg2<"ftintrp.l.d", FGR64Opnd>, R2F<0b1010011010>; -+def FTINTRZ_W_S : Float_Reg2<"ftintrz.w.s", FGR32Opnd>, R2F<0b1010100001>; -+def FTINTRZ_L_D : Float_Reg2<"ftintrz.l.d", FGR64Opnd>, R2F<0b1010101010>; -+def FTINTRNE_W_S : Float_Reg2<"ftintrne.w.s", FGR32Opnd>, R2F<0b1010110001>; -+def FTINTRNE_W_D : Float_Reg2<"ftintrne.w.d", FGR64Opnd>, R2F<0b1010110010>; -+def FTINTRNE_L_S : Float_Reg2<"ftintrne.l.s", FGR32Opnd>, R2F<0b1010111001>; -+def FTINTRNE_L_D : Float_Reg2<"ftintrne.l.d", FGR64Opnd>, R2F<0b1010111010>; -+ -+def FTINT_W_S : Float_CVT<"ftint.w.s", FGR32Opnd, FGR32Opnd>, R2F<0b1011000001>; -+def FTINT_W_D : Float_CVT<"ftint.w.d", FGR32Opnd, FGR64Opnd>, R2F<0b1011000010>; -+def FTINT_L_S : Float_CVT<"ftint.l.s", FGR64Opnd, FGR32Opnd>, R2F<0b1011001001>; -+def FTINT_L_D : Float_CVT<"ftint.l.d", FGR64Opnd, FGR64Opnd>, R2F<0b1011001010>; -+def FFINT_S_W : Float_CVT<"ffint.s.w", FGR32Opnd, FGR32Opnd>, R2F<0b1101000100>; -+def FFINT_S_L : Float_CVT<"ffint.s.l", FGR32Opnd, FGR64Opnd>, R2F<0b1101000110>; -+def FFINT_D_W : Float_CVT<"ffint.d.w", FGR64Opnd, FGR32Opnd>, R2F<0b1101001000>; -+def FFINT_D_L : Float_CVT<"ffint.d.l", FGR64Opnd, FGR64Opnd>, R2F<0b1101001010>; -+ -+def FRINT_S : Float_Reg2<"frint.s", FGR32Opnd, frint>, R2F<0b1110010001>; -+def FRINT_D : Float_Reg2<"frint.d", FGR64Opnd, frint>, R2F<0b1110010010>; -+ -+/// -+/// R3 -+/// -+def FADD_S : Float_Reg3<"fadd.s", FGR32Opnd, fadd>, R3F<0b000001>; -+def FADD_D : Float_Reg3<"fadd.d", FGR64Opnd, fadd>, R3F<0b000010>; -+def FSUB_S : Float_Reg3<"fsub.s", FGR32Opnd, fsub>, R3F<0b000101>; -+def FSUB_D : Float_Reg3<"fsub.d", FGR64Opnd, fsub>, R3F<0b000110>; -+def FMUL_S : Float_Reg3<"fmul.s", FGR32Opnd, fmul>, R3F<0b001001>; -+def FMUL_D : Float_Reg3<"fmul.d", FGR64Opnd, fmul>, R3F<0b001010>; -+def FDIV_S : Float_Reg3<"fdiv.s", FGR32Opnd, fdiv>, R3F<0b001101>; -+def FDIV_D : Float_Reg3<"fdiv.d", FGR64Opnd, fdiv>, R3F<0b001110>; -+def FMAX_S : Float_Reg3<"fmax.s", FGR32Opnd, fmaxnum_ieee>, R3F<0b010001>; -+def FMAX_D : Float_Reg3<"fmax.d", FGR64Opnd, fmaxnum_ieee>, R3F<0b010010>; -+def FMIN_S : Float_Reg3<"fmin.s", FGR32Opnd, fminnum_ieee>, R3F<0b010101>; -+def FMIN_D : Float_Reg3<"fmin.d", FGR64Opnd, fminnum_ieee>, R3F<0b010110>; -+def FMAXA_S : Float_Reg3_Fmaxa<"fmaxa.s", FGR32Opnd>, R3F<0b011001>; -+def FMAXA_D : Float_Reg3_Fmaxa<"fmaxa.d", FGR64Opnd>, R3F<0b011010>; -+def FMINA_S : Float_Reg3_Fmaxa<"fmina.s", FGR32Opnd>, R3F<0b011101>; -+def FMINA_D : Float_Reg3_Fmaxa<"fmina.d", FGR64Opnd>, R3F<0b011110>; -+def FSCALEB_S : Float_Reg3<"fscaleb.s", FGR32Opnd>, R3F<0b100001>; -+def FSCALEB_D : Float_Reg3<"fscaleb.d", FGR64Opnd>, R3F<0b100010>; -+def FCOPYSIGN_S : Float_Reg3<"fcopysign.s", FGR32Opnd, fcopysign>, R3F<0b100101>; -+def FCOPYSIGN_D : Float_Reg3<"fcopysign.d", FGR64Opnd, fcopysign>, R3F<0b100110>; -+/// -+/// R4_IMM21 -+/// -+def FMADD_S : Mul_Reg4<"fmadd.s", FGR32Opnd>, R4MUL<0b0001>; -+def FMADD_D : Mul_Reg4<"fmadd.d", FGR64Opnd>, R4MUL<0b0010>; -+def FMSUB_S : Mul_Reg4<"fmsub.s", FGR32Opnd>, R4MUL<0b0101>; -+def FMSUB_D : Mul_Reg4<"fmsub.d", FGR64Opnd>, R4MUL<0b0110>; -+def FNMADD_S : NMul_Reg4<"fnmadd.s", FGR32Opnd>, R4MUL<0b1001>; -+def FNMADD_D : NMul_Reg4<"fnmadd.d", FGR64Opnd>, R4MUL<0b1010>; -+def FNMSUB_S : NMul_Reg4<"fnmsub.s", FGR32Opnd>, R4MUL<0b1101>; -+def FNMSUB_D : NMul_Reg4<"fnmsub.d", FGR64Opnd>, R4MUL<0b1110>; -+ -+ -+// fmadd: fj * fk + fa -+def : LoongArchPat<(fma FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa), -+ (FMADD_D $fj, $fk, $fa)>; -+ -+def : LoongArchPat<(fma FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa), -+ (FMADD_S $fj, $fk, $fa)>; -+ -+ -+// fmsub: fj * fk - fa -+def : LoongArchPat<(fma FGR64Opnd:$fj, FGR64Opnd:$fk, (fneg FGR64Opnd:$fa)), -+ (FMSUB_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; -+ -+def : LoongArchPat<(fma FGR32Opnd:$fj, FGR32Opnd:$fk, (fneg FGR32Opnd:$fa)), -+ (FMSUB_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; -+ -+ -+// fnmadd: -(fj * fk + fa) -+def : LoongArchPat<(fma (fneg FGR64Opnd:$fj), FGR64Opnd:$fk, (fneg FGR64Opnd:$fa)), -+ (FNMADD_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; -+ -+def : LoongArchPat<(fma (fneg FGR32Opnd:$fj), FGR32Opnd:$fk, (fneg FGR32Opnd:$fa)), -+ (FNMADD_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; -+ -+// fnmsub: -(fj * fk - fa) -+def : LoongArchPat<(fma (fneg FGR64Opnd:$fj), FGR64Opnd:$fk, FGR64Opnd:$fa), -+ (FNMSUB_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; -+ -+def : LoongArchPat<(fma (fneg FGR32Opnd:$fj), FGR32Opnd:$fk, FGR32Opnd:$fa), -+ (FNMSUB_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; -+ -+let Pattern = [] in { -+defm S : FCMP_COND_M<0b01, "s", FGR32Opnd>; -+defm D : FCMP_COND_M<0b10, "d", FGR64Opnd>; -+} -+// -+//defm S : FCmp_Pats; -+//defm D : FCmp_Pats; -+ -+/// -+/// Float point branching -+/// -+def LoongArch_BRANCH_F : PatLeaf<(i32 0)>; -+def LoongArch_BRANCH_T : PatLeaf<(i32 1)>; -+ -+def BCEQZ : BceqzBr<"bceqz", brtarget, LoongArch_BRANCH_F>, R1_BCEQZ<0>; -+def BCNEZ : BceqzBr<"bcnez", brtarget, LoongArch_BRANCH_T>, R1_BCEQZ<1>; -+ -+/// -+/// FMOV -+/// -+def MOVGR2FCSR : Gpr_2_Fcsr<"movgr2fcsr", GPR64Opnd>, MOVGPR2FCSR; -+def MOVFCSR2GR : Fcsr_2_Gpr<"movfcsr2gr", GPR64Opnd>, MOVFCSR2GPR; -+def MOVFR2CF : Fgr_2_Fcfr<"movfr2cf", FGR64Opnd>, MOVFGR2FCFR; -+def MOVCF2FR : Fcfr_2_Fgr<"movcf2fr", FGR64Opnd>, MOVFCFR2FGR; -+def MOVGR2CF : Gpr_2_Fcfr<"movgr2cf", GPR64Opnd>, MOVGPR2FCFR; -+def MOVCF2GR : Fcfr_2_Gpr<"movcf2gr", GPR64Opnd>, MOVFCFR2GPR; -+ -+let isCodeGenOnly = 1 in { -+ def MOVFR2CF32 : Fgr_2_Fcfr<"movfr2cf", FGR32Opnd>, MOVFGR2FCFR; -+ def MOVCF2FR32 : Fcfr_2_Fgr<"movcf2fr", FGR32Opnd>, MOVFCFR2FGR; -+ def MOVGR2CF32 : Gpr_2_Fcfr<"movgr2cf", GPR32Opnd>, MOVGPR2FCFR; -+ def MOVCF2GR32 : Fcfr_2_Gpr<"movcf2gr", GPR32Opnd>, MOVFCFR2GPR; -+} -+ -+class Sel_Reg4 -+ : InstForm<(outs RO:$fd), (ins FCFROpnd:$ca, RO:$fj, RO:$fk), -+ !strconcat(opstr, "\t$fd, $fj, $fk, $ca"), -+ [(set RO:$fd, (LoongArchFSEL RO:$fj, FCFROpnd:$ca, RO:$fk))], -+ FrmR, opstr>{ -+ let Defs = [FCC0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6]; -+ let hasFCCRegOperand = 1; -+ } -+ -+def FSEL_T_S : Sel_Reg4<"fsel", FGR32Opnd>, R4SEL; -+let isCodeGenOnly = 1 in { -+ def FSEL_T_D : Sel_Reg4<"fsel", FGR64Opnd>, R4SEL; -+} -+ -+/// -+/// Mem access -+/// -+def FLD_S : FLd<"fld.s", FGR32Opnd, mem, load>, LOAD_STORE<0b1100>; -+def FST_S : FSt<"fst.s", FGR32Opnd, mem, store>, LOAD_STORE<0b1101>; -+def FLD_D : FLd<"fld.d", FGR64Opnd, mem, load>, LOAD_STORE<0b1110>; -+def FST_D : FSt<"fst.d", FGR64Opnd, mem, store>, LOAD_STORE<0b1111>; -+ -+def FLDX_S : FLDX<"fldx.s", FGR32Opnd, load>, R3MF<0b01100000>; -+def FLDX_D : FLDX<"fldx.d", FGR64Opnd, load>, R3MF<0b01101000>; -+def FSTX_S : FSTX<"fstx.s", FGR32Opnd, store>, R3MF<0b01110000>; -+def FSTX_D : FSTX<"fstx.d", FGR64Opnd, store>, R3MF<0b01111000>; -+ -+def FLDGT_S : Float_Int_Reg3<"fldgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101000>; -+def FLDGT_D : Float_Int_Reg3<"fldgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101001>; -+def FLDLE_S : Float_Int_Reg3<"fldle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101010>; -+def FLDLE_D : Float_Int_Reg3<"fldle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101011>; -+def FSTGT_S : Float_STGT_LE<"fstgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101100>; -+def FSTGT_D : Float_STGT_LE<"fstgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101101>; -+def FSTLE_S : Float_STGT_LE<"fstle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101110>; -+def FSTLE_D : Float_STGT_LE<"fstle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101111>; -+ -+let isPseudo = 1, isCodeGenOnly = 1 in { -+ def PseudoFFINT_S_W : Float_CVT<"", FGR32Opnd, GPR32Opnd>; -+ def PseudoFFINT_D_W : Float_CVT<"", FGR64Opnd, GPR32Opnd>; -+ def PseudoFFINT_S_L : Float_CVT<"", FGR64Opnd, GPR64Opnd>; -+ def PseudoFFINT_D_L : Float_CVT<"", FGR64Opnd, GPR64Opnd>; -+} -+ -+def : LoongArchPat<(f32 (fpround FGR64Opnd:$src)), -+ (FCVT_S_D FGR64Opnd:$src)>; -+def : LoongArchPat<(f64 (fpextend FGR32Opnd:$src)), -+ (FCVT_D_S FGR32Opnd:$src)>; -+ -+def : LoongArchPat<(f32 (sint_to_fp GPR32Opnd:$src)), -+ (PseudoFFINT_S_W GPR32Opnd:$src)>; -+def : LoongArchPat<(f64 (sint_to_fp GPR32Opnd:$src)), -+ (PseudoFFINT_D_W GPR32Opnd:$src)>; -+def : LoongArchPat<(f32 (sint_to_fp GPR64Opnd:$src)), -+ (EXTRACT_SUBREG (PseudoFFINT_S_L GPR64Opnd:$src), sub_lo)>; -+def : LoongArchPat<(f64 (sint_to_fp GPR64Opnd:$src)), -+ (PseudoFFINT_D_L GPR64Opnd:$src)>; -+ -+def : LoongArchPat<(f32 fpimm0), (MOVGR2FR_W ZERO)>; -+def : LoongArchPat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W ZERO))>; -+def : LoongArchPat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W ZERO, 1)))>; -+def : LoongArchPat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D ZERO_64, 1)))>; -+ -+// Patterns for loads/stores with a reg+imm operand. -+let AddedComplexity = 40 in { -+ def : LoadRegImmPat; -+ def : StoreRegImmPat; -+ def : LoadRegImmPat; -+ def : StoreRegImmPat; -+} -+ -+def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), -+ (FTINTRZ_W_S FGR32Opnd:$src)>; -+ -+def : LoongArchPat<(LoongArchTruncIntFP FGR64Opnd:$src), -+ (FTINTRZ_L_D FGR64Opnd:$src)>; -+ -+def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), -+ (FCVT_D_S (FTINTRZ_W_S FGR32Opnd:$src))>; -+ -+def : LoongArchPat<(f32 (fcopysign FGR32Opnd:$lhs, FGR64Opnd:$rhs)), -+ (FCOPYSIGN_S FGR32Opnd:$lhs, (FCVT_S_D FGR64Opnd:$rhs))>; -+def : LoongArchPat<(f64 (fcopysign FGR64Opnd:$lhs, FGR32Opnd:$rhs)), -+ (FCOPYSIGN_D FGR64Opnd:$lhs, (FCVT_D_S FGR32Opnd:$rhs))>; -+ -+let PrintMethod = "printFCCOperand",EncoderMethod = "getFCMPEncoding" in -+ def condcode : Operand; -+ -+class CEQS_FT : -+ InstForm<(outs), (ins RC:$fj, RC:$fk, condcode:$cond), -+ !strconcat("fcmp.$cond.", typestr, "\t$$fcc0, $fj, $fk"), -+ [(OpNode RC:$fj, RC:$fk, imm:$cond)], FrmFR, -+ !strconcat("fcmp.$cond.", typestr)>, HARDFLOAT { -+ let Defs = [FCC0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6, FCC7]; -+ let isCodeGenOnly = 1; -+ let hasFCCRegOperand = 1; -+} -+ -+def FCMP_S32 : CEQS_FT<"s", FGR32, LoongArchFPCmp>, CEQS_FM<0b01> { -+ bits<3> cd = 0; -+} -+def FCMP_D64 : CEQS_FT<"d", FGR64, LoongArchFPCmp>, CEQS_FM<0b10>{ -+ bits<3> cd = 0; -+} -+ -+ -+//multiclass FCmp_Pats2 { -+// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), -+// (!cast("SFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), -+// (!cast("SFCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), -+// (!cast("SFCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), -+// (!cast("SFCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), -+// (!cast("SFCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), -+// (NOROp -+// (!cast("SFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), -+// ZEROReg)>; -+// -+// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), -+// (!cast("DFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), -+// (!cast("DFCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), -+// (!cast("DFCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; -+// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), -+// (!cast("DFCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), -+// (!cast("DFCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; -+// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), -+// (NOROp -+// (!cast("DFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), -+// ZEROReg)>; -+// } -+// -+//defm S : FCmp_Pats2; -+//defm D : FCmp_Pats2; -+ -+let usesCustomInserter = 1 in { -+ class Select_Pseudo : -+ LoongArchPseudo<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), -+ [(set RC:$dst, (select GPR32Opnd:$cond, RC:$T, RC:$F))]>; -+ -+ class SelectFP_Pseudo_T : -+ LoongArchPseudo<(outs RC:$dst), (ins FCFROpnd:$cond, RC:$T, RC:$F), -+ [(set RC:$dst, (LoongArchCMovFP_T RC:$T, FCFROpnd:$cond, RC:$F))]>; -+ -+ class SelectFP_Pseudo_F : -+ LoongArchPseudo<(outs RC:$dst), (ins FCFROpnd:$cond, RC:$T, RC:$F), -+ [(set RC:$dst, (LoongArchCMovFP_F RC:$T, FCFROpnd:$cond, RC:$F))]>; -+} -+ -+def PseudoSELECT_I : Select_Pseudo; -+def PseudoSELECT_I64 : Select_Pseudo; -+def PseudoSELECT_S : Select_Pseudo; -+def PseudoSELECT_D64 : Select_Pseudo; -+ -+def PseudoSELECTFP_T_I : SelectFP_Pseudo_T; -+def PseudoSELECTFP_T_I64 : SelectFP_Pseudo_T; -+ -+def PseudoSELECTFP_F_I : SelectFP_Pseudo_F; -+def PseudoSELECTFP_F_I64 : SelectFP_Pseudo_F; -+ -+class ABSS_FT : -+ InstForm<(outs DstRC:$fd), (ins SrcRC:$fj), !strconcat(opstr, "\t$fd, $fj"), -+ [(set DstRC:$fd, (OpNode SrcRC:$fj))], FrmFR, opstr>; -+ -+def TRUNC_W_D : ABSS_FT<"ftintrz.w.d", FGR32Opnd, FGR64Opnd>, R2F<0b1010100010>; -+ -+def FTINTRZ_L_S : ABSS_FT<"ftintrz.l.s", FGR64Opnd, FGR32Opnd>, R2F<0b1010101001>; -+ -+def : LoongArchPat<(LoongArchTruncIntFP FGR64Opnd:$src), -+ (TRUNC_W_D FGR64Opnd:$src)>; -+ -+def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), -+ (FTINTRZ_L_S FGR32Opnd:$src)>; -+ -+def : Pat<(fcanonicalize FGR32Opnd:$src), (FMAX_S $src, $src)>; -+def : Pat<(fcanonicalize FGR64Opnd:$src), (FMAX_D $src, $src)>; -+ -+def : LoongArchPat<(i64 (sext (i32 (bitconvert FGR32Opnd:$src)))), -+ (MOVFR2GR_DS FGR32Opnd:$src)>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td -new file mode 100644 -index 000000000..8e255f857 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td -@@ -0,0 +1,448 @@ -+//===- LoongArchLASXInstrFormats.td - LoongArch LASX Instruction Formats ---*- tablegen -*-===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+ -+class LASXInst : InstLA<(outs), (ins), "", [], FrmOther>, -+ EXT_LASX { -+} -+ -+class LASXCBranch : LASXInst { -+} -+ -+class LASXSpecial : LASXInst { -+} -+ -+class LASXPseudo pattern>: -+ LoongArchPseudo { -+ let Predicates = [HasLASX]; -+} -+ -+class LASX_3R op>: LASXInst { -+ bits<5> xk; -+ bits<5> xj; -+ bits<5> xd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = xk; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_4R op>: LASXInst { -+ bits<5> xa; -+ bits<5> xk; -+ bits<5> xj; -+ bits<5> xd; -+ -+ let Inst{31-20} = op; -+ let Inst{19-15} = xa; -+ let Inst{14-10} = xk; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_XVFCMP op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<5> xk; -+ bits<5> cond; -+ -+ let Inst{31-20} = op; -+ let Inst{19-15} = cond; -+ let Inst{14-10} = xk; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I12_S op>: LASXInst { -+ bits<5> xd; -+ bits<17> addr; -+ -+ let Inst{31-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI12_S op>: LASXInst { -+ bits<5> xd; -+ bits<17> addr; -+ -+ let Inst{31-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI11_S op>: LASXInst { -+ bits<5> xd; -+ bits<16> addr; -+ -+ let Inst{31-21} = op; -+ let Inst{20-10} = addr{10-0}; -+ let Inst{9-5} = addr{15-11}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI10_S op>: LASXInst { -+ bits<5> xd; -+ bits<15> addr; -+ -+ let Inst{31-20} = op; -+ let Inst{19-10} = addr{9-0}; -+ let Inst{9-5} = addr{14-10}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI9_S op>: LASXInst { -+ bits<5> xd; -+ bits<14> addr; -+ -+ let Inst{31-19} = op; -+ let Inst{18-10} = addr{8-0}; -+ let Inst{9-5} = addr{13-9}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI8_idx5 op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<5> idx; -+ -+ let Inst{31-23} = op; -+ let Inst{22-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI8_idx2 op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<2> idx; -+ -+ let Inst{31-20} = op; -+ let Inst{19-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI8_idx3 op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<3> idx; -+ -+ let Inst{31-21} = op; -+ let Inst{20-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SI8_idx4 op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<4> idx; -+ -+ let Inst{31-22} = op; -+ let Inst{21-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_3R_2GP op>: LASXInst { -+ bits<5> rk; -+ bits<5> rj; -+ bits<5> xd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_3R_1GP op>: LASXInst { -+ bits<5> rk; -+ bits<5> xj; -+ bits<5> xd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I5 op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<5> si5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = si5; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I5_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<5> ui5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = ui5; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I5_mode_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> mode; -+ bits<5> ui5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = ui5; -+ let Inst{9-5} = mode; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_2R op>: LASXInst { -+ bits<5> xj; -+ bits<5> xd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_SET op>: LASXInst { -+ bits<5> xj; -+ bits<3> cd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = xj; -+ let Inst{4-3} = 0b00; -+ let Inst{2-0} = cd; -+} -+ -+class LASX_2R_1GP op>: LASXInst { -+ bits<5> rj; -+ bits<5> xd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I3_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I4_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I6_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<6> ui6; -+ -+ let Inst{31-16} = op; -+ let Inst{15-10} = ui6; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I2_R_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I3_R_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_ELM_COPY_U3 op>: LASXInst { -+ bits<5> rd; -+ bits<5> xj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = rd; -+} -+ -+class LASX_ELM_COPY_U2 op>: LASXInst { -+ bits<5> rd; -+ bits<5> xj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = rd; -+} -+ -+class LASX_I1_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I2_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I7_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<7> ui7; -+ -+ let Inst{31-17} = op; -+ let Inst{16-10} = ui7; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_1R_I13 op>: LASXInst { -+ bits<13> i13; -+ bits<5> xd; -+ -+ let Inst{31-18} = op; -+ let Inst{17-5} = i13; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I8_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> xj; -+ bits<8> ui8; -+ -+ let Inst{31-18} = op; -+ let Inst{17-10} = ui8; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = xd; -+} -+ -+ -+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -+class LASX_I1_R_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_I4_R_U op>: LASXInst { -+ bits<5> xd; -+ bits<5> rj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_ELM_COPY_B op>: LASXInst { -+ bits<5> rd; -+ bits<5> xj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = rd; -+} -+ -+class LASX_ELM_COPY_D op>: LASXInst { -+ bits<5> rd; -+ bits<5> xj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = xj; -+ let Inst{4-0} = rd; -+} -+ -+class LASX_Addr_SI8_idx1 op>: LASXInst { -+ bits<5> xd; -+ bits<13> addr; -+ bits<1> idx; -+ -+ let Inst{31-19} = op; -+ let Inst{18-11} = addr{7-0}; -+ let Inst{10} = idx; -+ let Inst{9-5} = addr{12-8}; -+ let Inst{4-0} = xd; -+} -+ -+class LASX_1R_I13_I10 op>: LASXInst { -+ bits<10> i10; -+ bits<5> xd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-5} = i10; -+ let Inst{4-0} = xd; -+} -+ -+ -+ -+ -+ -+ -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td -new file mode 100644 -index 000000000..2677a79fa ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td -@@ -0,0 +1,5673 @@ -+//===- LoongArchLASXInstrInfo.td - loongson LASX instructions -*- tablegen ------------*-=// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+// -+// This file describes loongson ASX instructions. -+// -+//===----------------------------------------------------------------------===// -+def SDT_XVPERMI : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, -+ SDTCisSameAs<0, 1>, -+ SDTCisVT<2, i32>]>; -+def SDT_XVSHFI : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>, -+ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, -+ SDTCisVT<3, i32>]>; -+def SDT_XVBROADCAST : SDTypeProfile<1, 1, [SDTCisVec<0>]>; -+ -+def SDT_INSVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, -+ SDTCisSameAs<1, 2>, -+ SDTCisVT<3, i32>]>; -+ -+def SDT_XVPICKVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, -+ SDTCisSameAs<1, 2>, -+ SDTCisVT<3, i32>]>; -+ -+def SDT_XVSHUF4I : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisInt<0>, -+ SDTCisSameAs<0, 1>, -+ SDTCisSameAs<0, 2>, -+ SDTCisVT<3, i32>]>; -+ -+def LoongArchXVSHUFI : SDNode<"LoongArchISD::XVSHFI", SDT_XVSHFI>; -+ -+def LoongArchXVSELI : SDNode<"LoongArchISD::XVSELI", SDT_XVSHFI>; -+ -+def LoongArchXVPERMI : SDNode<"LoongArchISD::XVPERMI", SDT_XVPERMI>; -+ -+def LoongArchXVBROADCAST : SDNode<"LoongArchISD::XVBROADCAST", SDT_XVBROADCAST>; -+ -+def LoongArchINSVE : SDNode<"LoongArchISD::INSVE", SDT_INSVE>; -+ -+def LoongArchXVSHUF4I : SDNode<"LoongArchISD::XVSHUF4I", SDT_XVSHUF4I>; -+ -+def LoongArchXVPICKVE : SDNode<"LoongArchISD::XVPICKVE", SDT_INSVE>; -+ -+def xvbroadcast_v32i8 : PatFrag<(ops node:$v1), -+ (v32i8 (LoongArchXVBROADCAST node:$v1))>; -+def xvbroadcast_v16i16 : PatFrag<(ops node:$v1), -+ (v16i16 (LoongArchXVBROADCAST node:$v1))>; -+def xvbroadcast_v8i32 : PatFrag<(ops node:$v1), -+ (v8i32 (LoongArchXVBROADCAST node:$v1))>; -+def xvbroadcast_v4i64 : PatFrag<(ops node:$v1), -+ (v4i64 (LoongArchXVBROADCAST node:$v1))>; -+ -+ -+def vfseteq_v8f32 : vfsetcc_type; -+def vfseteq_v4f64 : vfsetcc_type; -+def vfsetge_v8f32 : vfsetcc_type; -+def vfsetge_v4f64 : vfsetcc_type; -+def vfsetgt_v8f32 : vfsetcc_type; -+def vfsetgt_v4f64 : vfsetcc_type; -+def vfsetle_v8f32 : vfsetcc_type; -+def vfsetle_v4f64 : vfsetcc_type; -+def vfsetlt_v8f32 : vfsetcc_type; -+def vfsetlt_v4f64 : vfsetcc_type; -+def vfsetne_v8f32 : vfsetcc_type; -+def vfsetne_v4f64 : vfsetcc_type; -+def vfsetoeq_v8f32 : vfsetcc_type; -+def vfsetoeq_v4f64 : vfsetcc_type; -+def vfsetoge_v8f32 : vfsetcc_type; -+def vfsetoge_v4f64 : vfsetcc_type; -+def vfsetogt_v8f32 : vfsetcc_type; -+def vfsetogt_v4f64 : vfsetcc_type; -+def vfsetole_v8f32 : vfsetcc_type; -+def vfsetole_v4f64 : vfsetcc_type; -+def vfsetolt_v8f32 : vfsetcc_type; -+def vfsetolt_v4f64 : vfsetcc_type; -+def vfsetone_v8f32 : vfsetcc_type; -+def vfsetone_v4f64 : vfsetcc_type; -+def vfsetord_v8f32 : vfsetcc_type; -+def vfsetord_v4f64 : vfsetcc_type; -+def vfsetun_v8f32 : vfsetcc_type; -+def vfsetun_v4f64 : vfsetcc_type; -+def vfsetueq_v8f32 : vfsetcc_type; -+def vfsetueq_v4f64 : vfsetcc_type; -+def vfsetuge_v8f32 : vfsetcc_type; -+def vfsetuge_v4f64 : vfsetcc_type; -+def vfsetugt_v8f32 : vfsetcc_type; -+def vfsetugt_v4f64 : vfsetcc_type; -+def vfsetule_v8f32 : vfsetcc_type; -+def vfsetule_v4f64 : vfsetcc_type; -+def vfsetult_v8f32 : vfsetcc_type; -+def vfsetult_v4f64 : vfsetcc_type; -+def vfsetune_v8f32 : vfsetcc_type; -+def vfsetune_v4f64 : vfsetcc_type; -+ -+def xvsplati8 : PatFrag<(ops node:$e0), -+ (v32i8 (build_vector -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0))>; -+def xvsplati16 : PatFrag<(ops node:$e0), -+ (v16i16 (build_vector -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0))>; -+def xvsplati32 : PatFrag<(ops node:$e0), -+ (v8i32 (build_vector -+ node:$e0, node:$e0, node:$e0, node:$e0, -+ node:$e0, node:$e0, node:$e0, node:$e0))>; -+def xvsplati64 : PatFrag<(ops node:$e0), -+ (v4i64 (build_vector -+ node:$e0, node:$e0, node:$e0, node:$e0))>; -+def xvsplatf32 : PatFrag<(ops node:$e0), -+ (v8f32 (build_vector node:$e0, node:$e0, -+ node:$e0, node:$e0))>; -+def xvsplatf64 : PatFrag<(ops node:$e0), -+ (v4f64 (build_vector node:$e0, node:$e0))>; -+ -+def xvsplati8_uimm3 : SplatComplexPattern; -+def xvsplati16_uimm4 : SplatComplexPattern; -+ -+def xvsplati64_uimm6 : SplatComplexPattern; -+ -+def xvsplati8_simm5 : SplatComplexPattern; -+def xvsplati16_simm5 : SplatComplexPattern; -+def xvsplati32_simm5 : SplatComplexPattern; -+def xvsplati64_simm5 : SplatComplexPattern; -+ -+def xvsplat_imm_eq_1 : PatLeaf<(build_vector), [{ -+ APInt Imm; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ return selectVSplat(N, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -+}]>; -+ -+def xvsplati64_imm_eq_1 : PatLeaf<(bitconvert (v8i32 (build_vector))), [{ -+ APInt Imm; -+ SDNode *BV = N->getOperand(0).getNode(); -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -+}]>; -+ -+def xvbitclr_b : PatFrag<(ops node:$xk, node:$xa), -+ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), -+ immAllOnesV))>; -+def xvbitclr_h : PatFrag<(ops node:$xk, node:$xa), -+ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), -+ immAllOnesV))>; -+def xvbitclr_w : PatFrag<(ops node:$xk, node:$xa), -+ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), -+ immAllOnesV))>; -+def xvbitclr_d : PatFrag<(ops node:$xk, node:$xa), -+ (and node:$xk, (xor (shl (v4i64 vsplati64_imm_eq_1), -+ node:$xa), -+ (bitconvert (v8i32 immAllOnesV))))>; -+ -+ -+ -+def xvsplati8_uimm5 : SplatComplexPattern; -+def xvsplati16_uimm5 : SplatComplexPattern; -+def xvsplati32_uimm5 : SplatComplexPattern; -+def xvsplati64_uimm5 : SplatComplexPattern; -+def xvsplati8_uimm8 : SplatComplexPattern; -+def xvsplati16_uimm8 : SplatComplexPattern; -+def xvsplati32_uimm8 : SplatComplexPattern; -+def xvsplati64_uimm8 : SplatComplexPattern; -+ -+ -+ -+def xvsplati8_uimm4 : SplatComplexPattern; -+def xvsplati16_uimm3 : SplatComplexPattern; -+def xvsplati32_uimm2 : SplatComplexPattern; -+def xvsplati64_uimm1 : SplatComplexPattern; -+ -+ -+// Patterns. -+class LASXPat pred = [HasLASX]> : -+ Pat, Requires; -+ -+class LASX_4RF { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk, ROXA:$xa); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk, $xa"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk, ROXA:$xa))]; -+} -+ -+class LASX_3RF { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; -+} -+ -+class LASX_3R_SETCC_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, ROXK:$xk, CC)))]; -+} -+ -+class LASX_LD { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); -+ list Pattern = [(set ROXD:$xd, (TyNode (OpNode Addr:$addr)))]; -+ string DecoderMethod = "DecodeLASX256Mem"; -+} -+ -+class LASX_ST { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); -+ list Pattern = [(OpNode (TyNode ROXD:$xd), Addr:$addr)]; -+ string DecoderMethod = "DecodeLASX256Mem"; -+} -+ -+class LASX_I8_U5_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm5:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt5:$idx)]; -+ string DecoderMethod = "DecodeLASX256memstl"; -+} -+ -+class LASX_I8_U2_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm2:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt2:$idx)]; -+ string DecoderMethod = "DecodeLASX256memstl"; -+} -+ -+class LASX_I8_U3_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm3:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt3:$idx)]; -+ string DecoderMethod = "DecodeLASX256memstl"; -+} -+ -+class LASX_I8_U4_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm4:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt4:$idx)]; -+ string DecoderMethod = "DecodeLASX256memstl"; -+} -+ -+class LASX_SDX_LA { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, RORK:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk"); -+ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, RORK:$rk)]; -+} -+ -+class LASX_3R_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; -+} -+ -+class LASX_LDX_LA { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins PtrRC:$rj, RORK:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk"); -+ list Pattern = [(set ROXD:$xd, (OpNode iPTR:$rj, RORK:$rk))]; -+} -+ -+class LASX_3R_4R_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, -+ ROXK:$xk))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+ -+class LASX_3R_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, GPR32Opnd:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $rk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, GPR32Opnd:$rk))]; -+} -+ -+ -+class LASX_3R_VREPLVE_DESC_BASE_N { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, GPR64Opnd:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $rk"); -+ list Pattern = []; -+} -+ -+ -+class LASX_VEC_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; -+} -+ -+ -+ -+class LASX_3RF_DESC_BASE : -+ LASX_3R_DESC_BASE; -+ -+ -+class LASX_3R_DESC_BASE1 { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xk, ROXK:$xj))]; -+} -+ -+class LASX_3RF_DESC_BASE1 : -+ LASX_3R_DESC_BASE1; -+ -+ -+ -+class LASX_3R_VSHF_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ROXK:$xk); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); -+ list Pattern = [(set ROXD:$xd, (LoongArchVSHF ROXD:$xd_in, ROXJ:$xj, -+ ROXK:$xk))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_I5_SETCC_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); -+ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, SplatImm:$si5, CC)))]; -+} -+ -+class LASX_I5_SETCC_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$si5))]; -+} -+ -+ -+class LASX_I5_U_SETCC_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, SplatImm:$ui5, CC)))]; -+} -+ -+class LASX_I5_U_SETCC_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; -+} -+ -+class LASX_VEC_PSEUDO_BASE : -+ LASXPseudo<(outs ROXD:$xd), (ins ROXJ:$xj, ROXK:$xk), -+ [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]>; -+ -+ -+class LASX_I5_U_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui5))]; -+} -+ -+ -+class LASX_I5_U_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; -+} -+ -+class LASX_U5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt5:$ui5))]; -+} -+ -+class LASX_U5N_DESC_BASE : -+ LASX_U5_DESC_BASE; -+ -+class LASX_U5_4R_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt5:$ui5))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj))]; -+} -+ -+class LASX_SET_DESC_BASE { -+ dag OutOperandList = (outs FCFROpnd:$cd); -+ dag InOperandList = (ins ROXD:$xj); -+ string AsmString = !strconcat(instr_asm, "\t$cd, $xj"); -+ list Pattern = []; -+} -+ -+class LASX_2RF_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj))]; -+} -+ -+class LASX_I5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$si5))]; -+} -+ -+class LASX_I5_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$si5))]; -+} -+ -+ -+class LASX_2R_REPL_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROS:$rj); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj"); -+ list Pattern = [(set ROXD:$xd, (VT (OpNode ROS:$rj)))]; -+} -+ -+class LASX_XVEXTEND_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); -+ list Pattern = [(set ROXD:$xd, (DTy (OpNode (STy ROXJ:$xj))))]; -+} -+ -+class LASX_RORI_U3_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; -+} -+ -+class LASX_RORI_U4_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; -+} -+ -+class LASX_RORI_U5_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; -+} -+ -+class LASX_RORI_U6_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; -+} -+ -+class LASX_BIT_3_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; -+} -+ -+class LASX_BIT_4_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; -+} -+ -+class LASX_BIT_5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; -+} -+ -+class LASX_BIT_6_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; -+} -+ -+class LASX_BIT_2_4O_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui2"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui2))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_BIT_2_4ON : -+ LASX_BIT_2_4O_DESC_BASE; -+ -+class LASX_BIT_3_4O_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui3))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_BIT_3_4ON : -+ LASX_BIT_3_4O_DESC_BASE; -+ -+class LASX_INSERT_U3_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROS:$rj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (VTy (insertelt (VTy ROXD:$xd_in), ROS:$rj, Imm:$ui3)))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_INSERT_U2_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROS:$rj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $ui2"); -+ list Pattern = [(set ROXD:$xd, (VTy (insertelt (VTy ROXD:$xd_in), ROS:$rj, Imm:$ui2)))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_COPY_U2_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $xj, $ui2"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROXJ:$xj), Imm:$ui2))]; -+} -+ -+class LASX_COPY_U3_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $xj, $ui3"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROXJ:$xj), Imm:$ui3))]; -+} -+ -+class LASX_ELM_U4_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt4:$ui4))]; -+} -+ -+class LASX_ELM_U3_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm3:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt3:$ui3))]; -+} -+ -+class LASX_ELM_U2_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm2:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui2"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt2:$ui2))]; -+} -+ -+class LASX_ELM_U1_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm1:$ui1); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui1"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt1:$ui1))]; -+} -+ -+class LASX_XVBROADCAST_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); -+ list Pattern = [(set ROXD:$xd, (OpNode (TyNode ROXJ:$xj)))]; -+} -+ -+class LASX_2R_U3_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm3:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt3:$ui3))]; -+} -+ -+class LASX_2R_U4_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt4:$ui4))]; -+} -+ -+class LASX_2R_U5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt5:$ui5))]; -+} -+ -+class LASX_2R_U6_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm6:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt6:$ui6))]; -+} -+ -+class LASX_BIT_U3_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui3))]; -+} -+ -+class LASX_BIT_U4_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui4))]; -+} -+ -+class LASX_BIT_U5_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui5))]; -+} -+ -+class LASX_BIT_U6_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui6))]; -+} -+ -+class LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; -+} -+ -+class LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; -+} -+ -+class LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; -+} -+ -+class LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; -+} -+ -+class LASX_U4_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in,ROXJ:$xj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in,ROXJ:$xj, Imm:$ui4))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_N4_U5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui5))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_U6_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui6))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_D_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm7:$ui7); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui7"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt7:$ui7))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U4_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt4:$ui4))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U5_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt5:$ui5))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U6_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm6:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt6:$ui6))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U7_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm7:$ui7); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui7"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt7:$ui7))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U8_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt8:$ui8))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_2R_3R_U8_SELECT { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, vsplat_uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, xvsplati8_uimm8:$ui8, ROXJ:$xj))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_I8_O4_SHF_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt8:$ui8))]; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class LASX_I8_SHF_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt8:$ui8))]; -+} -+ -+class LASX_2R_U8_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt8:$ui8))]; -+} -+ -+class LASX_I13_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins immOp:$i13); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $i13"); -+ list Pattern = [(set ROXD:$xd, (OpNode (Ty simm13:$i13)))]; -+ string DecoderMethod = "DecodeLASX256Mem13"; -+} -+ -+class LASX_I13_DESC_BASE_10 { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ImmOp:$i10); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $i10"); -+ bit hasSideEffects = 0; -+ string DecoderMethod = "DecodeLASX256Mem10"; -+ list Pattern = [(set ROXD:$xd, (OpNode Imm:$i10))]; -+ } -+ -+class LASX_BIT_U8_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui8))]; -+} -+ -+class LASX_2RN_3R_U8_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); -+ list Pattern = []; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+ -+//encoding -+ -+def XVFMADD_S : LASX_4R<0b000010100001>, -+ LASX_4RF<"xvfmadd.s", int_loongarch_lasx_xvfmadd_s, LASX256WOpnd>; -+ -+def XVFMADD_D : LASX_4R<0b000010100010>, -+ LASX_4RF<"xvfmadd.d", int_loongarch_lasx_xvfmadd_d, LASX256DOpnd>; -+ -+ -+def XVFMSUB_S : LASX_4R<0b000010100101>, -+ LASX_4RF<"xvfmsub.s", int_loongarch_lasx_xvfmsub_s, LASX256WOpnd>; -+ -+def XVFMSUB_D : LASX_4R<0b000010100110>, -+ LASX_4RF<"xvfmsub.d", int_loongarch_lasx_xvfmsub_d, LASX256DOpnd>; -+ -+ -+def XVFNMADD_S : LASX_4R<0b000010101001>, -+ LASX_4RF<"xvfnmadd.s", int_loongarch_lasx_xvfnmadd_s, LASX256WOpnd>; -+ -+def XVFNMADD_D : LASX_4R<0b000010101010>, -+ LASX_4RF<"xvfnmadd.d", int_loongarch_lasx_xvfnmadd_d, LASX256DOpnd>; -+ -+ -+def XVFNMSUB_S : LASX_4R<0b000010101101>, -+ LASX_4RF<"xvfnmsub.s", int_loongarch_lasx_xvfnmsub_s, LASX256WOpnd>; -+ -+def XVFNMSUB_D : LASX_4R<0b000010101110>, -+ LASX_4RF<"xvfnmsub.d", int_loongarch_lasx_xvfnmsub_d, LASX256DOpnd>; -+ -+ -+// xvfmadd: xj * xk + xa -+def : LASXPat<(fma v4f64:$xj, v4f64:$xk, v4f64:$xa), -+ (XVFMADD_D $xj, $xk, $xa)>; -+ -+def : LASXPat<(fma v8f32:$xj, v8f32:$xk, v8f32:$xa), -+ (XVFMADD_S $xj, $xk, $xa)>; -+ -+ -+// xvfmsub: xj * xk - xa -+def : LASXPat<(fma v4f64:$xj, v4f64:$xk, (fneg v4f64:$xa)), -+ (XVFMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; -+ -+def : LASXPat<(fma v8f32:$xj, v8f32:$xk, (fneg v8f32:$xa)), -+ (XVFMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; -+ -+ -+// xvfnmadd: -(xj * xk + xa) -+def : LASXPat<(fma (fneg v4f64:$xj), v4f64:$xk, (fneg v4f64:$xa)), -+ (XVFNMADD_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; -+ -+def : LASXPat<(fma (fneg v8f32:$xj), v8f32:$xk, (fneg v8f32:$xa)), -+ (XVFNMADD_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; -+ -+// xvfnmsub: -(xj * xk - xa) -+def : LASXPat<(fma (fneg v4f64:$xj), v4f64:$xk, v4f64:$xa), -+ (XVFNMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; -+ -+def : LASXPat<(fma (fneg v8f32:$xj), v8f32:$xk, v8f32:$xa), -+ (XVFNMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; -+ -+ -+def XVFCMP_CAF_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.caf.s", int_loongarch_lasx_xvfcmp_caf_s, LASX256WOpnd>{ -+ bits<5> cond=0x0; -+ } -+ -+def XVFCMP_CAF_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.caf.d", int_loongarch_lasx_xvfcmp_caf_d, LASX256DOpnd>{ -+ bits<5> cond=0x0; -+ } -+ -+def XVFCMP_COR_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cor.s", vfsetord_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x14; -+ } -+ -+def XVFCMP_COR_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cor.d", vfsetord_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x14; -+ } -+ -+def XVFCMP_CUN_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cun.s", vfsetun_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x8; -+ } -+ -+def XVFCMP_CUN_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cun.d", vfsetun_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x8; -+ } -+ -+def XVFCMP_CUNE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cune.s", vfsetune_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x18; -+ } -+ -+def XVFCMP_CUNE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cune.d", vfsetune_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x18; -+ } -+ -+def XVFCMP_CUEQ_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cueq.s", vfsetueq_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0xc; -+ } -+ -+def XVFCMP_CUEQ_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cueq.d", vfsetueq_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0xc; -+ } -+ -+def XVFCMP_CEQ_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.ceq.s", vfsetoeq_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x4; -+ } -+ -+def XVFCMP_CEQ_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.ceq.d", vfsetoeq_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x4; -+ } -+ -+def XVFCMP_CNE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cne.s", vfsetone_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x10; -+ } -+ -+def XVFCMP_CNE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cne.d", vfsetone_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x10; -+ } -+ -+def XVFCMP_CLT_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.clt.s", vfsetolt_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x2; -+ } -+ -+def XVFCMP_CLT_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.clt.d", vfsetolt_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x2; -+ } -+ -+def XVFCMP_CULT_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cult.s", vfsetult_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0xa; -+ } -+ -+def XVFCMP_CULT_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cult.d", vfsetult_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0xa; -+ } -+ -+def XVFCMP_CLE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cle.s", vfsetole_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0x6; -+ } -+ -+def XVFCMP_CLE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cle.d", vfsetole_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0x6; -+ } -+ -+def XVFCMP_CULE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.cule.s", vfsetule_v8f32, LASX256WOpnd>{ -+ bits<5> cond=0xe; -+ } -+ -+def XVFCMP_CULE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.cule.d", vfsetule_v4f64, LASX256DOpnd>{ -+ bits<5> cond=0xe; -+ } -+ -+def XVFCMP_SAF_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.saf.s", int_loongarch_lasx_xvfcmp_saf_s, LASX256WOpnd>{ -+ bits<5> cond=0x1; -+ } -+ -+def XVFCMP_SAF_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.saf.d", int_loongarch_lasx_xvfcmp_saf_d, LASX256DOpnd>{ -+ bits<5> cond=0x1; -+ } -+ -+def XVFCMP_SOR_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sor.s", int_loongarch_lasx_xvfcmp_sor_s, LASX256WOpnd>{ -+ bits<5> cond=0x15; -+ } -+ -+def XVFCMP_SOR_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sor.d", int_loongarch_lasx_xvfcmp_sor_d, LASX256DOpnd>{ -+ bits<5> cond=0x15; -+ } -+ -+def XVFCMP_SUN_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sun.s", int_loongarch_lasx_xvfcmp_sun_s, LASX256WOpnd>{ -+ bits<5> cond=0x9; -+ } -+ -+def XVFCMP_SUN_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sun.d", int_loongarch_lasx_xvfcmp_sun_d, LASX256DOpnd>{ -+ bits<5> cond=0x9; -+ } -+ -+def XVFCMP_SUNE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sune.s", int_loongarch_lasx_xvfcmp_sune_s, LASX256WOpnd>{ -+ bits<5> cond=0x19; -+ } -+ -+def XVFCMP_SUNE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sune.d", int_loongarch_lasx_xvfcmp_sune_d, LASX256DOpnd>{ -+ bits<5> cond=0x19; -+ } -+ -+def XVFCMP_SUEQ_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sueq.s", int_loongarch_lasx_xvfcmp_sueq_s, LASX256WOpnd>{ -+ bits<5> cond=0xd; -+ } -+ -+def XVFCMP_SUEQ_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sueq.d", int_loongarch_lasx_xvfcmp_sueq_d, LASX256DOpnd>{ -+ bits<5> cond=0xd; -+ } -+ -+def XVFCMP_SEQ_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.seq.s", int_loongarch_lasx_xvfcmp_seq_s, LASX256WOpnd>{ -+ bits<5> cond=0x5; -+ } -+ -+def XVFCMP_SEQ_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.seq.d", int_loongarch_lasx_xvfcmp_seq_d, LASX256DOpnd>{ -+ bits<5> cond=0x5; -+ } -+ -+def XVFCMP_SNE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sne.s", int_loongarch_lasx_xvfcmp_sne_s, LASX256WOpnd>{ -+ bits<5> cond=0x11; -+ } -+ -+def XVFCMP_SNE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sne.d", int_loongarch_lasx_xvfcmp_sne_d, LASX256DOpnd>{ -+ bits<5> cond=0x11; -+ } -+ -+def XVFCMP_SLT_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.slt.s", int_loongarch_lasx_xvfcmp_slt_s, LASX256WOpnd>{ -+ bits<5> cond=0x3; -+ } -+ -+def XVFCMP_SLT_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.slt.d", int_loongarch_lasx_xvfcmp_slt_d, LASX256DOpnd>{ -+ bits<5> cond=0x3; -+ } -+ -+def XVFCMP_SULT_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sult.s", int_loongarch_lasx_xvfcmp_sult_s, LASX256WOpnd>{ -+ bits<5> cond=0xb; -+ } -+ -+def XVFCMP_SULT_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sult.d", int_loongarch_lasx_xvfcmp_sult_d, LASX256DOpnd>{ -+ bits<5> cond=0xb; -+ } -+ -+def XVFCMP_SLE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sle.s", int_loongarch_lasx_xvfcmp_sle_s, LASX256WOpnd>{ -+ bits<5> cond=0x7; -+ } -+ -+def XVFCMP_SLE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sle.d", int_loongarch_lasx_xvfcmp_sle_d, LASX256DOpnd>{ -+ bits<5> cond=0x7; -+ } -+ -+def XVFCMP_SULE_S : LASX_XVFCMP<0b000011001001>, -+ LASX_3RF<"xvfcmp.sule.s", int_loongarch_lasx_xvfcmp_sule_s, LASX256WOpnd>{ -+ bits<5> cond=0xf; -+ } -+ -+def XVFCMP_SULE_D : LASX_XVFCMP<0b000011001010>, -+ LASX_3RF<"xvfcmp.sule.d", int_loongarch_lasx_xvfcmp_sule_d, LASX256DOpnd>{ -+ bits<5> cond=0xf; -+ } -+ -+ -+def XVBITSEL_V : LASX_4R<0b000011010010>, -+ LASX_4RF<"xvbitsel.v", int_loongarch_lasx_xvbitsel_v, LASX256BOpnd>; -+ -+class LASX_BSEL_PSEUDO_BASE : -+ LASXPseudo<(outs RO:$xd), (ins RO:$xd_in, RO:$xs, RO:$xt), -+ [(set RO:$xd, (Ty (vselect RO:$xd_in, RO:$xt, RO:$xs)))]>, -+ PseudoInstExpansion<(XVBITSEL_V LASX256BOpnd:$xd, LASX256BOpnd:$xs, -+ LASX256BOpnd:$xt, LASX256BOpnd:$xd_in)> { -+ let Constraints = "$xd_in = $xd"; -+} -+ -+def XBSEL_B_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+def XBSEL_H_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+def XBSEL_W_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+def XBSEL_D_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+def XBSEL_FW_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+def XBSEL_FD_PSEUDO : LASX_BSEL_PSEUDO_BASE; -+ -+ -+ -+def XVSHUF_B : LASX_4R<0b000011010110>, -+ LASX_4RF<"xvshuf.b", int_loongarch_lasx_xvshuf_b, LASX256BOpnd>; -+ -+ -+def XVLD : LASX_I12_S<0b0010110010>, -+ LASX_LD<"xvld", load, v32i8, LASX256BOpnd, mem>; -+ -+def XVST : LASX_I12_S<0b0010110011>, -+ LASX_ST<"xvst", store, v32i8, LASX256BOpnd, mem_simm12>; -+ -+ -+class LASX_LD_DESC_BASE { -+ dag OutOperandList = (outs ROXD:$xd); -+ dag InOperandList = (ins MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); -+ list Pattern = [(set ROXD:$xd, (OpNode (TyNode (load Addr:$addr))))]; -+ string DecoderMethod = "DecodeLASX256memlsl"; -+} -+ -+ -+def XVLDREPL_B : LASX_SI12_S<0b0011001010>, -+ LASX_LD_DESC_BASE<"xvldrepl.b", xvbroadcast_v32i8, v32i8, LASX256BOpnd>; -+ -+def XVLDREPL_H : LASX_SI11_S<0b00110010010>, -+ LASX_LD_DESC_BASE<"xvldrepl.h", xvbroadcast_v16i16, v16i16, LASX256HOpnd, mem_simm11_lsl1, addrimm11lsl1>; -+ -+def XVLDREPL_W : LASX_SI10_S<0b001100100010>, -+ LASX_LD_DESC_BASE<"xvldrepl.w", xvbroadcast_v8i32, v8i32, LASX256WOpnd, mem_simm10_lsl2, addrimm10lsl2>; -+ -+def XVLDREPL_D : LASX_SI9_S<0b0011001000010>, -+ LASX_LD_DESC_BASE<"xvldrepl.d", xvbroadcast_v4i64, v4i64, LASX256DOpnd, mem_simm9_lsl3, addrimm9lsl3>; -+ -+ -+def XVSTELM_B : LASX_SI8_idx5<0b001100111>, -+ LASX_I8_U5_DESC_BASE<"xvstelm.b", int_loongarch_lasx_xvstelm_b, simm8_32, immSExt8, LASX256BOpnd, GPR32Opnd>; -+ -+def XVSTELM_H : LASX_SI8_idx4<0b0011001101>, -+ LASX_I8_U4_DESC_BASE<"xvstelm.h", int_loongarch_lasx_xvstelm_h, immSExt8_1_O, immSExt8, LASX256HOpnd, GPR32Opnd>; -+ -+def XVSTELM_W : LASX_SI8_idx3<0b00110011001>, -+ LASX_I8_U3_DESC_BASE<"xvstelm.w", int_loongarch_lasx_xvstelm_w, immSExt8_2_O, immSExt8, LASX256WOpnd, GPR32Opnd>; -+ -+def XVSTELM_D : LASX_SI8_idx2<0b001100110001>, -+ LASX_I8_U2_DESC_BASE<"xvstelm.d", int_loongarch_lasx_xvstelm_d, immSExt8_3_O, immSExt8, LASX256DOpnd, GPR32Opnd>; -+ -+let mayLoad = 1, canFoldAsLoad = 1 in { -+ def XVLDX : LASX_3R_2GP<0b00111000010010000>, -+ LASX_LDX_LA<"xvldx", int_loongarch_lasx_xvldx, GPR64Opnd, LASX256BOpnd>; -+} -+ -+let mayStore = 1 in{ -+ def XVSTX : LASX_3R_2GP<0b00111000010011000>, -+ LASX_SDX_LA<"xvstx", int_loongarch_lasx_xvstx, GPR64Opnd, LASX256BOpnd>; -+} -+ -+ -+def XVSEQ_B : LASX_3R<0b01110100000000000>, IsCommutable, -+ LASX_3R_SETCC_DESC_BASE<"xvseq.b", SETEQ, v32i8, LASX256BOpnd>; -+ -+def XVSEQ_H : LASX_3R<0b01110100000000001>, IsCommutable, -+ LASX_3R_SETCC_DESC_BASE<"xvseq.h", SETEQ, v16i16, LASX256HOpnd>; -+ -+def XVSEQ_W : LASX_3R<0b01110100000000010>, IsCommutable, -+ LASX_3R_SETCC_DESC_BASE<"xvseq.w", SETEQ, v8i32, LASX256WOpnd> ; -+ -+def XVSEQ_D : LASX_3R<0b01110100000000011>, IsCommutable, -+ LASX_3R_SETCC_DESC_BASE<"xvseq.d", SETEQ, v4i64, LASX256DOpnd>; -+ -+ -+def XVSLE_B : LASX_3R<0b01110100000000100>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.b", SETLE, v32i8, LASX256BOpnd>; -+ -+def XVSLE_H : LASX_3R<0b01110100000000101>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.h", SETLE, v16i16, LASX256HOpnd>; -+ -+def XVSLE_W : LASX_3R<0b01110100000000110>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.w", SETLE, v8i32, LASX256WOpnd>; -+ -+def XVSLE_D : LASX_3R<0b01110100000000111>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.d", SETLE, v4i64, LASX256DOpnd>; -+ -+ -+def XVSLE_BU : LASX_3R<0b01110100000001000>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.bu", SETULE, v32i8, LASX256BOpnd>; -+ -+def XVSLE_HU : LASX_3R<0b01110100000001001>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.hu", SETULE, v16i16, LASX256HOpnd>; -+ -+def XVSLE_WU : LASX_3R<0b01110100000001010>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.wu", SETULE, v8i32, LASX256WOpnd>; -+ -+def XVSLE_DU : LASX_3R<0b01110100000001011>, -+ LASX_3R_SETCC_DESC_BASE<"xvsle.du", SETULE, v4i64, LASX256DOpnd>; -+ -+ -+def XVSLT_B : LASX_3R<0b01110100000001100>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.b", SETLT, v32i8, LASX256BOpnd>; -+ -+def XVSLT_H : LASX_3R<0b01110100000001101>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.h", SETLT, v16i16, LASX256HOpnd>; -+ -+def XVSLT_W : LASX_3R<0b01110100000001110>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.w", SETLT, v8i32, LASX256WOpnd>; -+ -+def XVSLT_D : LASX_3R<0b01110100000001111>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.d", SETLT, v4i64, LASX256DOpnd>; -+ -+ -+def XVSLT_BU : LASX_3R<0b01110100000010000>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.bu", SETULT, v32i8, LASX256BOpnd>; -+ -+def XVSLT_HU : LASX_3R<0b01110100000010001>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.hu", SETULT, v16i16, LASX256HOpnd>; -+ -+def XVSLT_WU : LASX_3R<0b01110100000010010>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.wu", SETULT, v8i32, LASX256WOpnd>; -+ -+def XVSLT_DU : LASX_3R<0b01110100000010011>, -+ LASX_3R_SETCC_DESC_BASE<"xvslt.du", SETULT, v4i64, LASX256DOpnd>; -+ -+ -+def XVADD_B : LASX_3R<0b01110100000010100>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadd.b", add, LASX256BOpnd>; -+ -+def XVADD_H : LASX_3R<0b01110100000010101>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadd.h", add, LASX256HOpnd>; -+ -+def XVADD_W : LASX_3R<0b01110100000010110>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadd.w", add, LASX256WOpnd>; -+ -+def XVADD_D : LASX_3R<0b01110100000010111>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadd.d", add, LASX256DOpnd>; -+ -+ -+def XVSUB_B : LASX_3R<0b01110100000011000>, -+ LASX_3R_DESC_BASE<"xvsub.b", sub, LASX256BOpnd>; -+ -+def XVSUB_H : LASX_3R<0b01110100000011001>, -+ LASX_3R_DESC_BASE<"xvsub.h", sub, LASX256HOpnd>; -+ -+def XVSUB_W : LASX_3R<0b01110100000011010>, -+ LASX_3R_DESC_BASE<"xvsub.w", sub, LASX256WOpnd>; -+ -+def XVSUB_D : LASX_3R<0b01110100000011011>, -+ LASX_3R_DESC_BASE<"xvsub.d", sub, LASX256DOpnd>; -+ -+ -+def XVADDWEV_H_B : LASX_3R<0b01110100000111100>, -+ LASX_3R_DESC_BASE<"xvaddwev.h.b", int_loongarch_lasx_xvaddwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWEV_W_H : LASX_3R<0b01110100000111101>, -+ LASX_3R_DESC_BASE<"xvaddwev.w.h", int_loongarch_lasx_xvaddwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWEV_D_W : LASX_3R<0b01110100000111110>, -+ LASX_3R_DESC_BASE<"xvaddwev.d.w", int_loongarch_lasx_xvaddwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWEV_Q_D : LASX_3R<0b01110100000111111>, -+ LASX_3R_DESC_BASE<"xvaddwev.q.d", int_loongarch_lasx_xvaddwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSUBWEV_H_B : LASX_3R<0b01110100001000000>, -+ LASX_3R_DESC_BASE<"xvsubwev.h.b", int_loongarch_lasx_xvsubwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSUBWEV_W_H : LASX_3R<0b01110100001000001>, -+ LASX_3R_DESC_BASE<"xvsubwev.w.h", int_loongarch_lasx_xvsubwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSUBWEV_D_W : LASX_3R<0b01110100001000010>, -+ LASX_3R_DESC_BASE<"xvsubwev.d.w", int_loongarch_lasx_xvsubwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVSUBWEV_Q_D : LASX_3R<0b01110100001000011>, -+ LASX_3R_DESC_BASE<"xvsubwev.q.d", int_loongarch_lasx_xvsubwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDWOD_H_B : LASX_3R<0b01110100001000100>, -+ LASX_3R_DESC_BASE<"xvaddwod.h.b", int_loongarch_lasx_xvaddwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWOD_W_H : LASX_3R<0b01110100001000101>, -+ LASX_3R_DESC_BASE<"xvaddwod.w.h", int_loongarch_lasx_xvaddwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWOD_D_W : LASX_3R<0b01110100001000110>, -+ LASX_3R_DESC_BASE<"xvaddwod.d.w", int_loongarch_lasx_xvaddwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWOD_Q_D : LASX_3R<0b01110100001000111>, -+ LASX_3R_DESC_BASE<"xvaddwod.q.d", int_loongarch_lasx_xvaddwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSUBWOD_H_B : LASX_3R<0b01110100001001000>, -+ LASX_3R_DESC_BASE<"xvsubwod.h.b", int_loongarch_lasx_xvsubwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSUBWOD_W_H : LASX_3R<0b01110100001001001>, -+ LASX_3R_DESC_BASE<"xvsubwod.w.h", int_loongarch_lasx_xvsubwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSUBWOD_D_W : LASX_3R<0b01110100001001010>, -+ LASX_3R_DESC_BASE<"xvsubwod.d.w", int_loongarch_lasx_xvsubwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVSUBWOD_Q_D : LASX_3R<0b01110100001001011>, -+ LASX_3R_DESC_BASE<"xvsubwod.q.d", int_loongarch_lasx_xvsubwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDWEV_H_BU : LASX_3R<0b01110100001011100>, -+ LASX_3R_DESC_BASE<"xvaddwev.h.bu", int_loongarch_lasx_xvaddwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWEV_W_HU : LASX_3R<0b01110100001011101>, -+ LASX_3R_DESC_BASE<"xvaddwev.w.hu", int_loongarch_lasx_xvaddwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWEV_D_WU : LASX_3R<0b01110100001011110>, -+ LASX_3R_DESC_BASE<"xvaddwev.d.wu", int_loongarch_lasx_xvaddwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWEV_Q_DU : LASX_3R<0b01110100001011111>, -+ LASX_3R_DESC_BASE<"xvaddwev.q.du", int_loongarch_lasx_xvaddwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSUBWEV_H_BU : LASX_3R<0b01110100001100000>, -+ LASX_3R_DESC_BASE<"xvsubwev.h.bu", int_loongarch_lasx_xvsubwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSUBWEV_W_HU : LASX_3R<0b01110100001100001>, -+ LASX_3R_DESC_BASE<"xvsubwev.w.hu", int_loongarch_lasx_xvsubwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSUBWEV_D_WU : LASX_3R<0b01110100001100010>, -+ LASX_3R_DESC_BASE<"xvsubwev.d.wu", int_loongarch_lasx_xvsubwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVSUBWEV_Q_DU : LASX_3R<0b01110100001100011>, -+ LASX_3R_DESC_BASE<"xvsubwev.q.du", int_loongarch_lasx_xvsubwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDWOD_H_BU : LASX_3R<0b01110100001100100>, -+ LASX_3R_DESC_BASE<"xvaddwod.h.bu", int_loongarch_lasx_xvaddwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWOD_W_HU : LASX_3R<0b01110100001100101>, -+ LASX_3R_DESC_BASE<"xvaddwod.w.hu", int_loongarch_lasx_xvaddwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWOD_D_WU : LASX_3R<0b01110100001100110>, -+ LASX_3R_DESC_BASE<"xvaddwod.d.wu", int_loongarch_lasx_xvaddwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWOD_Q_DU : LASX_3R<0b01110100001100111>, -+ LASX_3R_DESC_BASE<"xvaddwod.q.du", int_loongarch_lasx_xvaddwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSUBWOD_H_BU : LASX_3R<0b01110100001101000>, -+ LASX_3R_DESC_BASE<"xvsubwod.h.bu", int_loongarch_lasx_xvsubwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSUBWOD_W_HU : LASX_3R<0b01110100001101001>, -+ LASX_3R_DESC_BASE<"xvsubwod.w.hu", int_loongarch_lasx_xvsubwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSUBWOD_D_WU : LASX_3R<0b01110100001101010>, -+ LASX_3R_DESC_BASE<"xvsubwod.d.wu", int_loongarch_lasx_xvsubwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVSUBWOD_Q_DU : LASX_3R<0b01110100001101011>, -+ LASX_3R_DESC_BASE<"xvsubwod.q.du", int_loongarch_lasx_xvsubwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDWEV_H_BU_B : LASX_3R<0b01110100001111100>, -+ LASX_3R_DESC_BASE<"xvaddwev.h.bu.b", int_loongarch_lasx_xvaddwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWEV_W_HU_H : LASX_3R<0b01110100001111101>, -+ LASX_3R_DESC_BASE<"xvaddwev.w.hu.h", int_loongarch_lasx_xvaddwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWEV_D_WU_W : LASX_3R<0b01110100001111110>, -+ LASX_3R_DESC_BASE<"xvaddwev.d.wu.w", int_loongarch_lasx_xvaddwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWEV_Q_DU_D : LASX_3R<0b01110100001111111>, -+ LASX_3R_DESC_BASE<"xvaddwev.q.du.d", int_loongarch_lasx_xvaddwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDWOD_H_BU_B : LASX_3R<0b01110100010000000>, -+ LASX_3R_DESC_BASE<"xvaddwod.h.bu.b", int_loongarch_lasx_xvaddwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVADDWOD_W_HU_H : LASX_3R<0b01110100010000001>, -+ LASX_3R_DESC_BASE<"xvaddwod.w.hu.h", int_loongarch_lasx_xvaddwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVADDWOD_D_WU_W : LASX_3R<0b01110100010000010>, -+ LASX_3R_DESC_BASE<"xvaddwod.d.wu.w", int_loongarch_lasx_xvaddwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVADDWOD_Q_DU_D : LASX_3R<0b01110100010000011>, -+ LASX_3R_DESC_BASE<"xvaddwod.q.du.d", int_loongarch_lasx_xvaddwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSADD_B : LASX_3R<0b01110100010001100>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.b", saddsat, LASX256BOpnd>; -+ -+def XVSADD_H : LASX_3R<0b01110100010001101>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.h", saddsat, LASX256HOpnd>; -+ -+def XVSADD_W : LASX_3R<0b01110100010001110>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.w", saddsat, LASX256WOpnd>; -+ -+def XVSADD_D : LASX_3R<0b01110100010001111>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.d", saddsat, LASX256DOpnd>; -+ -+ -+def XVSSUB_B : LASX_3R<0b01110100010010000>, -+ LASX_3R_DESC_BASE<"xvssub.b", ssubsat, LASX256BOpnd>; -+ -+def XVSSUB_H : LASX_3R<0b01110100010010001>, -+ LASX_3R_DESC_BASE<"xvssub.h", ssubsat, LASX256HOpnd>; -+ -+def XVSSUB_W : LASX_3R<0b01110100010010010>, -+ LASX_3R_DESC_BASE<"xvssub.w", ssubsat, LASX256WOpnd>; -+ -+def XVSSUB_D : LASX_3R<0b01110100010010011>, -+ LASX_3R_DESC_BASE<"xvssub.d", ssubsat, LASX256DOpnd>; -+ -+ -+def XVSADD_BU : LASX_3R<0b01110100010010100>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.bu", uaddsat, LASX256BOpnd>; -+ -+def XVSADD_HU : LASX_3R<0b01110100010010101>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.hu", uaddsat, LASX256HOpnd>; -+ -+def XVSADD_WU : LASX_3R<0b01110100010010110>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.wu", uaddsat, LASX256WOpnd>; -+ -+def XVSADD_DU : LASX_3R<0b01110100010010111>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvsadd.du", uaddsat, LASX256DOpnd>; -+ -+ -+def XVSSUB_BU : LASX_3R<0b01110100010011000>, -+ LASX_3R_DESC_BASE<"xvssub.bu", usubsat, LASX256BOpnd>; -+ -+def XVSSUB_HU : LASX_3R<0b01110100010011001>, -+ LASX_3R_DESC_BASE<"xvssub.hu", usubsat, LASX256HOpnd>; -+ -+def XVSSUB_WU : LASX_3R<0b01110100010011010>, -+ LASX_3R_DESC_BASE<"xvssub.wu", usubsat, LASX256WOpnd>; -+ -+def XVSSUB_DU : LASX_3R<0b01110100010011011>, -+ LASX_3R_DESC_BASE<"xvssub.du", usubsat, LASX256DOpnd>; -+ -+ -+def XVHADDW_H_B : LASX_3R<0b01110100010101000>, -+ LASX_3R_DESC_BASE<"xvhaddw.h.b", int_loongarch_lasx_xvhaddw_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVHADDW_W_H : LASX_3R<0b01110100010101001>, -+ LASX_3R_DESC_BASE<"xvhaddw.w.h", int_loongarch_lasx_xvhaddw_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVHADDW_D_W : LASX_3R<0b01110100010101010>, -+ LASX_3R_DESC_BASE<"xvhaddw.d.w", int_loongarch_lasx_xvhaddw_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVHADDW_Q_D : LASX_3R<0b01110100010101011>, -+ LASX_3R_DESC_BASE<"xvhaddw.q.d", int_loongarch_lasx_xvhaddw_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+ -+def XVHSUBW_H_B : LASX_3R<0b01110100010101100>, -+ LASX_3R_DESC_BASE<"xvhsubw.h.b", int_loongarch_lasx_xvhsubw_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVHSUBW_W_H : LASX_3R<0b01110100010101101>, -+ LASX_3R_DESC_BASE<"xvhsubw.w.h", int_loongarch_lasx_xvhsubw_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVHSUBW_D_W : LASX_3R<0b01110100010101110>, -+ LASX_3R_DESC_BASE<"xvhsubw.d.w", int_loongarch_lasx_xvhsubw_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVHSUBW_Q_D : LASX_3R<0b01110100010101111>, -+ LASX_3R_DESC_BASE<"xvhsubw.q.d", int_loongarch_lasx_xvhsubw_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVHADDW_HU_BU : LASX_3R<0b01110100010110000>, -+ LASX_3R_DESC_BASE<"xvhaddw.hu.bu", int_loongarch_lasx_xvhaddw_hu_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVHADDW_WU_HU : LASX_3R<0b01110100010110001>, -+ LASX_3R_DESC_BASE<"xvhaddw.wu.hu", int_loongarch_lasx_xvhaddw_wu_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVHADDW_DU_WU : LASX_3R<0b01110100010110010>, -+ LASX_3R_DESC_BASE<"xvhaddw.du.wu", int_loongarch_lasx_xvhaddw_du_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVHADDW_QU_DU : LASX_3R<0b01110100010110011>, -+ LASX_3R_DESC_BASE<"xvhaddw.qu.du", int_loongarch_lasx_xvhaddw_qu_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+ -+def XVHSUBW_HU_BU : LASX_3R<0b01110100010110100>, -+ LASX_3R_DESC_BASE<"xvhsubw.hu.bu", int_loongarch_lasx_xvhsubw_hu_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVHSUBW_WU_HU : LASX_3R<0b01110100010110101>, -+ LASX_3R_DESC_BASE<"xvhsubw.wu.hu", int_loongarch_lasx_xvhsubw_wu_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVHSUBW_DU_WU : LASX_3R<0b01110100010110110>, -+ LASX_3R_DESC_BASE<"xvhsubw.du.wu", int_loongarch_lasx_xvhsubw_du_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVHSUBW_QU_DU : LASX_3R<0b01110100010110111>, -+ LASX_3R_DESC_BASE<"xvhsubw.qu.du", int_loongarch_lasx_xvhsubw_qu_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVADDA_B : LASX_3R<0b01110100010111000>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadda.b", int_loongarch_lasx_xvadda_b, LASX256BOpnd>; -+ -+def XVADDA_H : LASX_3R<0b01110100010111001>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadda.h", int_loongarch_lasx_xvadda_h, LASX256HOpnd>; -+ -+def XVADDA_W : LASX_3R<0b01110100010111010>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadda.w", int_loongarch_lasx_xvadda_w, LASX256WOpnd>; -+ -+def XVADDA_D : LASX_3R<0b01110100010111011>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadda.d", int_loongarch_lasx_xvadda_d, LASX256DOpnd>; -+ -+ -+def XVABSD_B : LASX_3R<0b01110100011000000>, -+ LASX_3R_DESC_BASE<"xvabsd.b", int_loongarch_lasx_xvabsd_b, LASX256BOpnd>; -+ -+def XVABSD_H : LASX_3R<0b01110100011000001>, -+ LASX_3R_DESC_BASE<"xvabsd.h", int_loongarch_lasx_xvabsd_h, LASX256HOpnd>; -+ -+def XVABSD_W : LASX_3R<0b01110100011000010>, -+ LASX_3R_DESC_BASE<"xvabsd.w", int_loongarch_lasx_xvabsd_w, LASX256WOpnd>; -+ -+def XVABSD_D : LASX_3R<0b01110100011000011>, -+ LASX_3R_DESC_BASE<"xvabsd.d", int_loongarch_lasx_xvabsd_d, LASX256DOpnd>; -+ -+ -+def XVABSD_BU : LASX_3R<0b01110100011000100>, -+ LASX_3R_DESC_BASE<"xvabsd.bu", int_loongarch_lasx_xvabsd_bu, LASX256BOpnd>; -+ -+def XVABSD_HU : LASX_3R<0b01110100011000101>, -+ LASX_3R_DESC_BASE<"xvabsd.hu", int_loongarch_lasx_xvabsd_hu, LASX256HOpnd>; -+ -+def XVABSD_WU : LASX_3R<0b01110100011000110>, -+ LASX_3R_DESC_BASE<"xvabsd.wu", int_loongarch_lasx_xvabsd_wu, LASX256WOpnd>; -+ -+def XVABSD_DU : LASX_3R<0b01110100011000111>, -+ LASX_3R_DESC_BASE<"xvabsd.du", int_loongarch_lasx_xvabsd_du, LASX256DOpnd>; -+ -+ -+def XVAVG_B : LASX_3R<0b01110100011001000>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.b", int_loongarch_lasx_xvavg_b, LASX256BOpnd>; -+ -+def XVAVG_H : LASX_3R<0b01110100011001001>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.h", int_loongarch_lasx_xvavg_h, LASX256HOpnd>; -+ -+def XVAVG_W : LASX_3R<0b01110100011001010>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.w", int_loongarch_lasx_xvavg_w, LASX256WOpnd>; -+ -+def XVAVG_D : LASX_3R<0b01110100011001011>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.d", int_loongarch_lasx_xvavg_d, LASX256DOpnd>; -+ -+ -+def XVAVG_BU : LASX_3R<0b01110100011001100>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.bu", int_loongarch_lasx_xvavg_bu, LASX256BOpnd>; -+ -+def XVAVG_HU : LASX_3R<0b01110100011001101>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.hu", int_loongarch_lasx_xvavg_hu, LASX256HOpnd>; -+ -+def XVAVG_WU : LASX_3R<0b01110100011001110>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.wu", int_loongarch_lasx_xvavg_wu, LASX256WOpnd>; -+ -+def XVAVG_DU : LASX_3R<0b01110100011001111>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavg.du", int_loongarch_lasx_xvavg_du, LASX256DOpnd>; -+ -+ -+def XVAVGR_B : LASX_3R<0b01110100011010000>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.b", int_loongarch_lasx_xvavgr_b, LASX256BOpnd>; -+ -+def XVAVGR_H : LASX_3R<0b01110100011010001>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.h", int_loongarch_lasx_xvavgr_h, LASX256HOpnd>; -+ -+def XVAVGR_W : LASX_3R<0b01110100011010010>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.w", int_loongarch_lasx_xvavgr_w, LASX256WOpnd>; -+ -+def XVAVGR_D : LASX_3R<0b01110100011010011>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.d", int_loongarch_lasx_xvavgr_d, LASX256DOpnd>; -+ -+ -+def XVAVGR_BU : LASX_3R<0b01110100011010100>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.bu", int_loongarch_lasx_xvavgr_bu, LASX256BOpnd>; -+ -+def XVAVGR_HU : LASX_3R<0b01110100011010101>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.hu", int_loongarch_lasx_xvavgr_hu, LASX256HOpnd>; -+ -+def XVAVGR_WU : LASX_3R<0b01110100011010110>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.wu", int_loongarch_lasx_xvavgr_wu, LASX256WOpnd>; -+ -+def XVAVGR_DU : LASX_3R<0b01110100011010111>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvavgr.du", int_loongarch_lasx_xvavgr_du, LASX256DOpnd>; -+ -+ -+def XVMAX_B : LASX_3R<0b01110100011100000>, -+ LASX_3R_DESC_BASE<"xvmax.b", smax, LASX256BOpnd>; -+ -+def XVMAX_H : LASX_3R<0b01110100011100001>, -+ LASX_3R_DESC_BASE<"xvmax.h", smax, LASX256HOpnd>; -+ -+def XVMAX_W : LASX_3R<0b01110100011100010>, -+ LASX_3R_DESC_BASE<"xvmax.w", smax, LASX256WOpnd>; -+ -+def XVMAX_D : LASX_3R<0b01110100011100011>, -+ LASX_3R_DESC_BASE<"xvmax.d", smax, LASX256DOpnd>; -+ -+ -+def XVMIN_B : LASX_3R<0b01110100011100100>, -+ LASX_3R_DESC_BASE<"xvmin.b", smin, LASX256BOpnd>; -+ -+def XVMIN_H : LASX_3R<0b01110100011100101>, -+ LASX_3R_DESC_BASE<"xvmin.h", smin, LASX256HOpnd>; -+ -+def XVMIN_W : LASX_3R<0b01110100011100110>, -+ LASX_3R_DESC_BASE<"xvmin.w", smin, LASX256WOpnd>; -+ -+def XVMIN_D : LASX_3R<0b01110100011100111>, -+ LASX_3R_DESC_BASE<"xvmin.d", smin, LASX256DOpnd>; -+ -+ -+def XVMAX_BU : LASX_3R<0b01110100011101000>, -+ LASX_3R_DESC_BASE<"xvmax.bu", umax, LASX256BOpnd>; -+ -+def XVMAX_HU : LASX_3R<0b01110100011101001>, -+ LASX_3R_DESC_BASE<"xvmax.hu", umax, LASX256HOpnd>; -+ -+def XVMAX_WU : LASX_3R<0b01110100011101010>, -+ LASX_3R_DESC_BASE<"xvmax.wu", umax, LASX256WOpnd>; -+ -+def XVMAX_DU : LASX_3R<0b01110100011101011>, -+ LASX_3R_DESC_BASE<"xvmax.du", umax, LASX256DOpnd>; -+ -+ -+def XVMIN_BU : LASX_3R<0b01110100011101100>, -+ LASX_3R_DESC_BASE<"xvmin.bu", umin, LASX256BOpnd>; -+ -+def XVMIN_HU : LASX_3R<0b01110100011101101>, -+ LASX_3R_DESC_BASE<"xvmin.hu", umin, LASX256HOpnd>; -+ -+def XVMIN_WU : LASX_3R<0b01110100011101110>, -+ LASX_3R_DESC_BASE<"xvmin.wu", umin, LASX256WOpnd>; -+ -+def XVMIN_DU : LASX_3R<0b01110100011101111>, -+ LASX_3R_DESC_BASE<"xvmin.du", umin, LASX256DOpnd>; -+ -+ -+def XVMUL_B : LASX_3R<0b01110100100001000>, -+ LASX_3R_DESC_BASE<"xvmul.b", mul, LASX256BOpnd>, IsCommutable; -+ -+def XVMUL_H : LASX_3R<0b01110100100001001>, -+ LASX_3R_DESC_BASE<"xvmul.h", mul, LASX256HOpnd>, IsCommutable; -+ -+def XVMUL_W : LASX_3R<0b01110100100001010>, -+ LASX_3R_DESC_BASE<"xvmul.w", mul, LASX256WOpnd>, IsCommutable; -+ -+def XVMUL_D : LASX_3R<0b01110100100001011>, -+ LASX_3R_DESC_BASE<"xvmul.d", mul, LASX256DOpnd>, IsCommutable; -+ -+ -+def XVMUH_B : LASX_3R<0b01110100100001100>, -+ LASX_3R_DESC_BASE<"xvmuh.b", int_loongarch_lasx_xvmuh_b, LASX256BOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMUH_H : LASX_3R<0b01110100100001101>, -+ LASX_3R_DESC_BASE<"xvmuh.h", int_loongarch_lasx_xvmuh_h, LASX256HOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMUH_W : LASX_3R<0b01110100100001110>, -+ LASX_3R_DESC_BASE<"xvmuh.w", int_loongarch_lasx_xvmuh_w, LASX256WOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMUH_D : LASX_3R<0b01110100100001111>, -+ LASX_3R_DESC_BASE<"xvmuh.d", int_loongarch_lasx_xvmuh_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMUH_BU : LASX_3R<0b01110100100010000>, -+ LASX_3R_DESC_BASE<"xvmuh.bu", int_loongarch_lasx_xvmuh_bu, LASX256BOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMUH_HU : LASX_3R<0b01110100100010001>, -+ LASX_3R_DESC_BASE<"xvmuh.hu", int_loongarch_lasx_xvmuh_hu, LASX256HOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMUH_WU : LASX_3R<0b01110100100010010>, -+ LASX_3R_DESC_BASE<"xvmuh.wu", int_loongarch_lasx_xvmuh_wu, LASX256WOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMUH_DU : LASX_3R<0b01110100100010011>, -+ LASX_3R_DESC_BASE<"xvmuh.du", int_loongarch_lasx_xvmuh_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWEV_H_B : LASX_3R<0b01110100100100000>, -+ LASX_3R_DESC_BASE<"xvmulwev.h.b", int_loongarch_lasx_xvmulwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWEV_W_H : LASX_3R<0b01110100100100001>, -+ LASX_3R_DESC_BASE<"xvmulwev.w.h", int_loongarch_lasx_xvmulwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWEV_D_W : LASX_3R<0b01110100100100010>, -+ LASX_3R_DESC_BASE<"xvmulwev.d.w", int_loongarch_lasx_xvmulwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWEV_Q_D : LASX_3R<0b01110100100100011>, -+ LASX_3R_DESC_BASE<"xvmulwev.q.d", int_loongarch_lasx_xvmulwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWOD_H_B : LASX_3R<0b01110100100100100>, -+ LASX_3R_DESC_BASE<"xvmulwod.h.b", int_loongarch_lasx_xvmulwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWOD_W_H : LASX_3R<0b01110100100100101>, -+ LASX_3R_DESC_BASE<"xvmulwod.w.h", int_loongarch_lasx_xvmulwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWOD_D_W : LASX_3R<0b01110100100100110>, -+ LASX_3R_DESC_BASE<"xvmulwod.d.w", int_loongarch_lasx_xvmulwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWOD_Q_D : LASX_3R<0b01110100100100111>, -+ LASX_3R_DESC_BASE<"xvmulwod.q.d", int_loongarch_lasx_xvmulwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWEV_H_BU : LASX_3R<0b01110100100110000>, -+ LASX_3R_DESC_BASE<"xvmulwev.h.bu", int_loongarch_lasx_xvmulwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWEV_W_HU : LASX_3R<0b01110100100110001>, -+ LASX_3R_DESC_BASE<"xvmulwev.w.hu", int_loongarch_lasx_xvmulwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWEV_D_WU : LASX_3R<0b01110100100110010>, -+ LASX_3R_DESC_BASE<"xvmulwev.d.wu", int_loongarch_lasx_xvmulwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWEV_Q_DU : LASX_3R<0b01110100100110011>, -+ LASX_3R_DESC_BASE<"xvmulwev.q.du", int_loongarch_lasx_xvmulwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWOD_H_BU : LASX_3R<0b01110100100110100>, -+ LASX_3R_DESC_BASE<"xvmulwod.h.bu", int_loongarch_lasx_xvmulwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWOD_W_HU : LASX_3R<0b01110100100110101>, -+ LASX_3R_DESC_BASE<"xvmulwod.w.hu", int_loongarch_lasx_xvmulwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWOD_D_WU : LASX_3R<0b01110100100110110>, -+ LASX_3R_DESC_BASE<"xvmulwod.d.wu", int_loongarch_lasx_xvmulwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWOD_Q_DU : LASX_3R<0b01110100100110111>, -+ LASX_3R_DESC_BASE<"xvmulwod.q.du", int_loongarch_lasx_xvmulwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWEV_H_BU_B : LASX_3R<0b01110100101000000>, -+ LASX_3R_DESC_BASE<"xvmulwev.h.bu.b", int_loongarch_lasx_xvmulwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWEV_W_HU_H : LASX_3R<0b01110100101000001>, -+ LASX_3R_DESC_BASE<"xvmulwev.w.hu.h", int_loongarch_lasx_xvmulwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWEV_D_WU_W : LASX_3R<0b01110100101000010>, -+ LASX_3R_DESC_BASE<"xvmulwev.d.wu.w", int_loongarch_lasx_xvmulwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWEV_Q_DU_D : LASX_3R<0b01110100101000011>, -+ LASX_3R_DESC_BASE<"xvmulwev.q.du.d", int_loongarch_lasx_xvmulwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMULWOD_H_BU_B : LASX_3R<0b01110100101000100>, -+ LASX_3R_DESC_BASE<"xvmulwod.h.bu.b", int_loongarch_lasx_xvmulwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMULWOD_W_HU_H : LASX_3R<0b01110100101000101>, -+ LASX_3R_DESC_BASE<"xvmulwod.w.hu.h", int_loongarch_lasx_xvmulwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMULWOD_D_WU_W : LASX_3R<0b01110100101000110>, -+ LASX_3R_DESC_BASE<"xvmulwod.d.wu.w", int_loongarch_lasx_xvmulwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; -+ -+def XVMULWOD_Q_DU_D : LASX_3R<0b01110100101000111>, -+ LASX_3R_DESC_BASE<"xvmulwod.q.du.d", int_loongarch_lasx_xvmulwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADD_B : LASX_3R<0b01110100101010000>, -+ LASX_3R_4R_DESC_BASE<"xvmadd.b", muladd, LASX256BOpnd>; -+ -+def XVMADD_H : LASX_3R<0b01110100101010001>, -+ LASX_3R_4R_DESC_BASE<"xvmadd.h", muladd, LASX256HOpnd>; -+ -+def XVMADD_W : LASX_3R<0b01110100101010010>, -+ LASX_3R_4R_DESC_BASE<"xvmadd.w", muladd, LASX256WOpnd>; -+ -+def XVMADD_D : LASX_3R<0b01110100101010011>, -+ LASX_3R_4R_DESC_BASE<"xvmadd.d", muladd, LASX256DOpnd>; -+ -+ -+def XVMSUB_B : LASX_3R<0b01110100101010100>, -+ LASX_3R_4R_DESC_BASE<"xvmsub.b", mulsub, LASX256BOpnd>; -+ -+def XVMSUB_H : LASX_3R<0b01110100101010101>, -+ LASX_3R_4R_DESC_BASE<"xvmsub.h", mulsub, LASX256HOpnd>; -+ -+def XVMSUB_W : LASX_3R<0b01110100101010110>, -+ LASX_3R_4R_DESC_BASE<"xvmsub.w", mulsub, LASX256WOpnd>; -+ -+def XVMSUB_D : LASX_3R<0b01110100101010111>, -+ LASX_3R_4R_DESC_BASE<"xvmsub.d", mulsub, LASX256DOpnd>; -+ -+ -+def XVMADDWEV_H_B : LASX_3R<0b01110100101011000>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.b", int_loongarch_lasx_xvmaddwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWEV_W_H : LASX_3R<0b01110100101011001>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.h", int_loongarch_lasx_xvmaddwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWEV_D_W : LASX_3R<0b01110100101011010>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.w", int_loongarch_lasx_xvmaddwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWEV_Q_D : LASX_3R<0b01110100101011011>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.d", int_loongarch_lasx_xvmaddwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADDWOD_H_B : LASX_3R<0b01110100101011100>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.b", int_loongarch_lasx_xvmaddwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWOD_W_H : LASX_3R<0b01110100101011101>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.h", int_loongarch_lasx_xvmaddwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWOD_D_W : LASX_3R<0b01110100101011110>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.w", int_loongarch_lasx_xvmaddwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWOD_Q_D : LASX_3R<0b01110100101011111>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.d", int_loongarch_lasx_xvmaddwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADDWEV_H_BU : LASX_3R<0b01110100101101000>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.bu", int_loongarch_lasx_xvmaddwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWEV_W_HU : LASX_3R<0b01110100101101001>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.hu", int_loongarch_lasx_xvmaddwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWEV_D_WU : LASX_3R<0b01110100101101010>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.wu", int_loongarch_lasx_xvmaddwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWEV_Q_DU : LASX_3R<0b01110100101101011>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.du", int_loongarch_lasx_xvmaddwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADDWOD_H_BU : LASX_3R<0b01110100101101100>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.bu", int_loongarch_lasx_xvmaddwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWOD_W_HU : LASX_3R<0b01110100101101101>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.hu", int_loongarch_lasx_xvmaddwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWOD_D_WU : LASX_3R<0b01110100101101110>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.wu", int_loongarch_lasx_xvmaddwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWOD_Q_DU : LASX_3R<0b01110100101101111>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.du", int_loongarch_lasx_xvmaddwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADDWEV_H_BU_B : LASX_3R<0b01110100101111000>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.bu.b", int_loongarch_lasx_xvmaddwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWEV_W_HU_H : LASX_3R<0b01110100101111001>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.hu.h", int_loongarch_lasx_xvmaddwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWEV_D_WU_W : LASX_3R<0b01110100101111010>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.wu.w", int_loongarch_lasx_xvmaddwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWEV_Q_DU_D : LASX_3R<0b01110100101111011>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.du.d", int_loongarch_lasx_xvmaddwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVMADDWOD_H_BU_B : LASX_3R<0b01110100101111100>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.bu.b", int_loongarch_lasx_xvmaddwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVMADDWOD_W_HU_H : LASX_3R<0b01110100101111101>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.hu.h", int_loongarch_lasx_xvmaddwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVMADDWOD_D_WU_W : LASX_3R<0b01110100101111110>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.wu.w", int_loongarch_lasx_xvmaddwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVMADDWOD_Q_DU_D : LASX_3R<0b01110100101111111>, -+ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.du.d", int_loongarch_lasx_xvmaddwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVDIV_B : LASX_3R<0b01110100111000000>, -+ LASX_3R_DESC_BASE<"xvdiv.b", sdiv, LASX256BOpnd>; -+ -+def XVDIV_H : LASX_3R<0b01110100111000001>, -+ LASX_3R_DESC_BASE<"xvdiv.h", sdiv, LASX256HOpnd>; -+ -+def XVDIV_W : LASX_3R<0b01110100111000010>, -+ LASX_3R_DESC_BASE<"xvdiv.w", sdiv, LASX256WOpnd>; -+ -+def XVDIV_D : LASX_3R<0b01110100111000011>, -+ LASX_3R_DESC_BASE<"xvdiv.d", sdiv, LASX256DOpnd>; -+ -+ -+def XVMOD_B : LASX_3R<0b01110100111000100>, -+ LASX_3R_DESC_BASE<"xvmod.b", srem, LASX256BOpnd>; -+ -+def XVMOD_H : LASX_3R<0b01110100111000101>, -+ LASX_3R_DESC_BASE<"xvmod.h", srem, LASX256HOpnd>; -+ -+def XVMOD_W : LASX_3R<0b01110100111000110>, -+ LASX_3R_DESC_BASE<"xvmod.w", srem, LASX256WOpnd>; -+ -+def XVMOD_D : LASX_3R<0b01110100111000111>, -+ LASX_3R_DESC_BASE<"xvmod.d", srem, LASX256DOpnd>; -+ -+ -+def XVDIV_BU : LASX_3R<0b01110100111001000>, -+ LASX_3R_DESC_BASE<"xvdiv.bu", udiv, LASX256BOpnd>; -+ -+def XVDIV_HU : LASX_3R<0b01110100111001001>, -+ LASX_3R_DESC_BASE<"xvdiv.hu", udiv, LASX256HOpnd>; -+ -+def XVDIV_WU : LASX_3R<0b01110100111001010>, -+ LASX_3R_DESC_BASE<"xvdiv.wu", udiv, LASX256WOpnd>; -+ -+def XVDIV_DU : LASX_3R<0b01110100111001011>, -+ LASX_3R_DESC_BASE<"xvdiv.du", udiv, LASX256DOpnd>; -+ -+ -+def XVMOD_BU : LASX_3R<0b01110100111001100>, -+ LASX_3R_DESC_BASE<"xvmod.bu", urem, LASX256BOpnd>; -+ -+def XVMOD_HU : LASX_3R<0b01110100111001101>, -+ LASX_3R_DESC_BASE<"xvmod.hu", urem, LASX256HOpnd>; -+ -+def XVMOD_WU : LASX_3R<0b01110100111001110>, -+ LASX_3R_DESC_BASE<"xvmod.wu", urem, LASX256WOpnd>; -+ -+def XVMOD_DU : LASX_3R<0b01110100111001111>, -+ LASX_3R_DESC_BASE<"xvmod.du", urem, LASX256DOpnd>; -+ -+ -+def XVSLL_B : LASX_3R<0b01110100111010000>, -+ LASX_3R_DESC_BASE<"xvsll.b", shl, LASX256BOpnd>; -+ -+def XVSLL_H : LASX_3R<0b01110100111010001>, -+ LASX_3R_DESC_BASE<"xvsll.h", shl, LASX256HOpnd>; -+ -+def XVSLL_W : LASX_3R<0b01110100111010010>, -+ LASX_3R_DESC_BASE<"xvsll.w", shl, LASX256WOpnd>; -+ -+def XVSLL_D : LASX_3R<0b01110100111010011>, -+ LASX_3R_DESC_BASE<"xvsll.d", shl, LASX256DOpnd>; -+ -+ -+def XVSRL_B : LASX_3R<0b01110100111010100>, -+ LASX_3R_DESC_BASE<"xvsrl.b", srl, LASX256BOpnd>; -+ -+def XVSRL_H : LASX_3R<0b01110100111010101>, -+ LASX_3R_DESC_BASE<"xvsrl.h", srl, LASX256HOpnd>; -+ -+def XVSRL_W : LASX_3R<0b01110100111010110>, -+ LASX_3R_DESC_BASE<"xvsrl.w", srl, LASX256WOpnd>; -+ -+def XVSRL_D : LASX_3R<0b01110100111010111>, -+ LASX_3R_DESC_BASE<"xvsrl.d", srl, LASX256DOpnd>; -+ -+ -+def XVSRA_B : LASX_3R<0b01110100111011000>, -+ LASX_3R_DESC_BASE<"xvsra.b", sra, LASX256BOpnd>; -+ -+def XVSRA_H : LASX_3R<0b01110100111011001>, -+ LASX_3R_DESC_BASE<"xvsra.h", sra, LASX256HOpnd>; -+ -+def XVSRA_W : LASX_3R<0b01110100111011010>, -+ LASX_3R_DESC_BASE<"xvsra.w", sra, LASX256WOpnd>; -+ -+def XVSRA_D : LASX_3R<0b01110100111011011>, -+ LASX_3R_DESC_BASE<"xvsra.d", sra, LASX256DOpnd>; -+ -+ -+def XVROTR_B : LASX_3R<0b01110100111011100>, -+ LASX_3R_DESC_BASE<"xvrotr.b", int_loongarch_lasx_xvrotr_b, LASX256BOpnd>; -+ -+def XVROTR_H : LASX_3R<0b01110100111011101>, -+ LASX_3R_DESC_BASE<"xvrotr.h", int_loongarch_lasx_xvrotr_h, LASX256HOpnd>; -+ -+def XVROTR_W : LASX_3R<0b01110100111011110>, -+ LASX_3R_DESC_BASE<"xvrotr.w", int_loongarch_lasx_xvrotr_w, LASX256WOpnd>; -+ -+def XVROTR_D : LASX_3R<0b01110100111011111>, -+ LASX_3R_DESC_BASE<"xvrotr.d", int_loongarch_lasx_xvrotr_d, LASX256DOpnd>; -+ -+ -+def XVSRLR_B : LASX_3R<0b01110100111100000>, -+ LASX_3R_DESC_BASE<"xvsrlr.b", int_loongarch_lasx_xvsrlr_b, LASX256BOpnd>; -+ -+def XVSRLR_H : LASX_3R<0b01110100111100001>, -+ LASX_3R_DESC_BASE<"xvsrlr.h", int_loongarch_lasx_xvsrlr_h, LASX256HOpnd>; -+ -+def XVSRLR_W : LASX_3R<0b01110100111100010>, -+ LASX_3R_DESC_BASE<"xvsrlr.w", int_loongarch_lasx_xvsrlr_w, LASX256WOpnd>; -+ -+def XVSRLR_D : LASX_3R<0b01110100111100011>, -+ LASX_3R_DESC_BASE<"xvsrlr.d", int_loongarch_lasx_xvsrlr_d, LASX256DOpnd>; -+ -+ -+def XVSRAR_B : LASX_3R<0b01110100111100100>, -+ LASX_3R_DESC_BASE<"xvsrar.b", int_loongarch_lasx_xvsrar_b, LASX256BOpnd>; -+ -+def XVSRAR_H : LASX_3R<0b01110100111100101>, -+ LASX_3R_DESC_BASE<"xvsrar.h", int_loongarch_lasx_xvsrar_h, LASX256HOpnd>; -+ -+def XVSRAR_W : LASX_3R<0b01110100111100110>, -+ LASX_3R_DESC_BASE<"xvsrar.w", int_loongarch_lasx_xvsrar_w, LASX256WOpnd>; -+ -+def XVSRAR_D : LASX_3R<0b01110100111100111>, -+ LASX_3R_DESC_BASE<"xvsrar.d", int_loongarch_lasx_xvsrar_d, LASX256DOpnd>; -+ -+ -+def XVSRLN_B_H : LASX_3R<0b01110100111101001>, -+ LASX_3R_DESC_BASE<"xvsrln.b.h", int_loongarch_lasx_xvsrln_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSRLN_H_W : LASX_3R<0b01110100111101010>, -+ LASX_3R_DESC_BASE<"xvsrln.h.w", int_loongarch_lasx_xvsrln_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSRLN_W_D : LASX_3R<0b01110100111101011>, -+ LASX_3R_DESC_BASE<"xvsrln.w.d", int_loongarch_lasx_xvsrln_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSRAN_B_H : LASX_3R<0b01110100111101101>, -+ LASX_3R_DESC_BASE<"xvsran.b.h", int_loongarch_lasx_xvsran_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSRAN_H_W : LASX_3R<0b01110100111101110>, -+ LASX_3R_DESC_BASE<"xvsran.h.w", int_loongarch_lasx_xvsran_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSRAN_W_D : LASX_3R<0b01110100111101111>, -+ LASX_3R_DESC_BASE<"xvsran.w.d", int_loongarch_lasx_xvsran_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSRLRN_B_H : LASX_3R<0b01110100111110001>, -+ LASX_3R_DESC_BASE<"xvsrlrn.b.h", int_loongarch_lasx_xvsrlrn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSRLRN_H_W : LASX_3R<0b01110100111110010>, -+ LASX_3R_DESC_BASE<"xvsrlrn.h.w", int_loongarch_lasx_xvsrlrn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSRLRN_W_D : LASX_3R<0b01110100111110011>, -+ LASX_3R_DESC_BASE<"xvsrlrn.w.d", int_loongarch_lasx_xvsrlrn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSRARN_B_H : LASX_3R<0b01110100111110101>, -+ LASX_3R_DESC_BASE<"xvsrarn.b.h", int_loongarch_lasx_xvsrarn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSRARN_H_W : LASX_3R<0b01110100111110110>, -+ LASX_3R_DESC_BASE<"xvsrarn.h.w", int_loongarch_lasx_xvsrarn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSRARN_W_D : LASX_3R<0b01110100111110111>, -+ LASX_3R_DESC_BASE<"xvsrarn.w.d", int_loongarch_lasx_xvsrarn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRLN_B_H : LASX_3R<0b01110100111111001>, -+ LASX_3R_DESC_BASE<"xvssrln.b.h", int_loongarch_lasx_xvssrln_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRLN_H_W : LASX_3R<0b01110100111111010>, -+ LASX_3R_DESC_BASE<"xvssrln.h.w", int_loongarch_lasx_xvssrln_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRLN_W_D : LASX_3R<0b01110100111111011>, -+ LASX_3R_DESC_BASE<"xvssrln.w.d", int_loongarch_lasx_xvssrln_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRAN_B_H : LASX_3R<0b01110100111111101>, -+ LASX_3R_DESC_BASE<"xvssran.b.h", int_loongarch_lasx_xvssran_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRAN_H_W : LASX_3R<0b01110100111111110>, -+ LASX_3R_DESC_BASE<"xvssran.h.w", int_loongarch_lasx_xvssran_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRAN_W_D : LASX_3R<0b01110100111111111>, -+ LASX_3R_DESC_BASE<"xvssran.w.d", int_loongarch_lasx_xvssran_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRLRN_B_H : LASX_3R<0b01110101000000001>, -+ LASX_3R_DESC_BASE<"xvssrlrn.b.h", int_loongarch_lasx_xvssrlrn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRLRN_H_W : LASX_3R<0b01110101000000010>, -+ LASX_3R_DESC_BASE<"xvssrlrn.h.w", int_loongarch_lasx_xvssrlrn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRLRN_W_D : LASX_3R<0b01110101000000011>, -+ LASX_3R_DESC_BASE<"xvssrlrn.w.d", int_loongarch_lasx_xvssrlrn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRARN_B_H : LASX_3R<0b01110101000000101>, -+ LASX_3R_DESC_BASE<"xvssrarn.b.h", int_loongarch_lasx_xvssrarn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRARN_H_W : LASX_3R<0b01110101000000110>, -+ LASX_3R_DESC_BASE<"xvssrarn.h.w", int_loongarch_lasx_xvssrarn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRARN_W_D : LASX_3R<0b01110101000000111>, -+ LASX_3R_DESC_BASE<"xvssrarn.w.d", int_loongarch_lasx_xvssrarn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRLN_BU_H : LASX_3R<0b01110101000001001>, -+ LASX_3R_DESC_BASE<"xvssrln.bu.h", int_loongarch_lasx_xvssrln_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRLN_HU_W : LASX_3R<0b01110101000001010>, -+ LASX_3R_DESC_BASE<"xvssrln.hu.w", int_loongarch_lasx_xvssrln_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRLN_WU_D : LASX_3R<0b01110101000001011>, -+ LASX_3R_DESC_BASE<"xvssrln.wu.d", int_loongarch_lasx_xvssrln_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRAN_BU_H : LASX_3R<0b01110101000001101>, -+ LASX_3R_DESC_BASE<"xvssran.bu.h", int_loongarch_lasx_xvssran_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRAN_HU_W : LASX_3R<0b01110101000001110>, -+ LASX_3R_DESC_BASE<"xvssran.hu.w", int_loongarch_lasx_xvssran_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRAN_WU_D : LASX_3R<0b01110101000001111>, -+ LASX_3R_DESC_BASE<"xvssran.wu.d", int_loongarch_lasx_xvssran_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRLRN_BU_H : LASX_3R<0b01110101000010001>, -+ LASX_3R_DESC_BASE<"xvssrlrn.bu.h", int_loongarch_lasx_xvssrlrn_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRLRN_HU_W : LASX_3R<0b01110101000010010>, -+ LASX_3R_DESC_BASE<"xvssrlrn.hu.w", int_loongarch_lasx_xvssrlrn_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRLRN_WU_D : LASX_3R<0b01110101000010011>, -+ LASX_3R_DESC_BASE<"xvssrlrn.wu.d", int_loongarch_lasx_xvssrlrn_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRARN_BU_H : LASX_3R<0b01110101000010101>, -+ LASX_3R_DESC_BASE<"xvssrarn.bu.h", int_loongarch_lasx_xvssrarn_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRARN_HU_W : LASX_3R<0b01110101000010110>, -+ LASX_3R_DESC_BASE<"xvssrarn.hu.w", int_loongarch_lasx_xvssrarn_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRARN_WU_D : LASX_3R<0b01110101000010111>, -+ LASX_3R_DESC_BASE<"xvssrarn.wu.d", int_loongarch_lasx_xvssrarn_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVBITCLR_B : LASX_3R<0b01110101000011000>, -+ LASX_3R_DESC_BASE<"xvbitclr.b", xvbitclr_b, LASX256BOpnd>; -+ -+def XVBITCLR_H : LASX_3R<0b01110101000011001>, -+ LASX_3R_DESC_BASE<"xvbitclr.h", xvbitclr_h, LASX256HOpnd>; -+ -+def XVBITCLR_W : LASX_3R<0b01110101000011010>, -+ LASX_3R_DESC_BASE<"xvbitclr.w", xvbitclr_w, LASX256WOpnd>; -+ -+def XVBITCLR_D : LASX_3R<0b01110101000011011>, -+ LASX_3R_DESC_BASE<"xvbitclr.d", xvbitclr_d, LASX256DOpnd>; -+ -+ -+def XVBITSET_B : LASX_3R<0b01110101000011100>, -+ LASX_3R_DESC_BASE<"xvbitset.b", int_loongarch_lasx_xvbitset_b, LASX256BOpnd>; -+ -+def XVBITSET_H : LASX_3R<0b01110101000011101>, -+ LASX_3R_DESC_BASE<"xvbitset.h", int_loongarch_lasx_xvbitset_h, LASX256HOpnd>; -+ -+def XVBITSET_W : LASX_3R<0b01110101000011110>, -+ LASX_3R_DESC_BASE<"xvbitset.w", int_loongarch_lasx_xvbitset_w, LASX256WOpnd>; -+ -+def XVBITSET_D : LASX_3R<0b01110101000011111>, -+ LASX_3R_DESC_BASE<"xvbitset.d", int_loongarch_lasx_xvbitset_d, LASX256DOpnd>; -+ -+ -+def XVBITREV_B : LASX_3R<0b01110101000100000>, -+ LASX_3R_DESC_BASE<"xvbitrev.b", int_loongarch_lasx_xvbitrev_b, LASX256BOpnd>; -+ -+def XVBITREV_H : LASX_3R<0b01110101000100001>, -+ LASX_3R_DESC_BASE<"xvbitrev.h", int_loongarch_lasx_xvbitrev_h, LASX256HOpnd>; -+ -+def XVBITREV_W : LASX_3R<0b01110101000100010>, -+ LASX_3R_DESC_BASE<"xvbitrev.w", int_loongarch_lasx_xvbitrev_w, LASX256WOpnd>; -+ -+def XVBITREV_D : LASX_3R<0b01110101000100011>, -+ LASX_3R_DESC_BASE<"xvbitrev.d", int_loongarch_lasx_xvbitrev_d, LASX256DOpnd>; -+ -+ -+def XVPACKEV_B : LASX_3R<0b01110101000101100>, -+ LASX_3R_DESC_BASE<"xvpackev.b", LoongArchVPACKEV, LASX256BOpnd>; -+ -+def XVPACKEV_H : LASX_3R<0b01110101000101101>, -+ LASX_3R_DESC_BASE<"xvpackev.h", LoongArchVPACKEV, LASX256HOpnd>; -+ -+def XVPACKEV_W : LASX_3R<0b01110101000101110>, -+ LASX_3R_DESC_BASE<"xvpackev.w", LoongArchVPACKEV, LASX256WOpnd>; -+ -+def XVPACKEV_D : LASX_3R<0b01110101000101111>, -+ LASX_3R_DESC_BASE<"xvpackev.d", LoongArchVPACKEV, LASX256DOpnd>; -+ -+ -+def XVPACKOD_B : LASX_3R<0b01110101000110000>, -+ LASX_3R_DESC_BASE<"xvpackod.b", LoongArchVPACKOD, LASX256BOpnd>; -+ -+def XVPACKOD_H : LASX_3R<0b01110101000110001>, -+ LASX_3R_DESC_BASE<"xvpackod.h", LoongArchVPACKOD, LASX256HOpnd>; -+ -+def XVPACKOD_W : LASX_3R<0b01110101000110010>, -+ LASX_3R_DESC_BASE<"xvpackod.w", LoongArchVPACKOD, LASX256WOpnd>; -+ -+def XVPACKOD_D : LASX_3R<0b01110101000110011>, -+ LASX_3R_DESC_BASE<"xvpackod.d", LoongArchVPACKOD, LASX256DOpnd>; -+ -+ -+def XVILVL_B : LASX_3R<0b01110101000110100>, -+ LASX_3R_DESC_BASE<"xvilvl.b", LoongArchVILVL, LASX256BOpnd>; -+ -+def XVILVL_H : LASX_3R<0b01110101000110101>, -+ LASX_3R_DESC_BASE<"xvilvl.h", LoongArchVILVL, LASX256HOpnd>; -+ -+def XVILVL_W : LASX_3R<0b01110101000110110>, -+ LASX_3R_DESC_BASE<"xvilvl.w", LoongArchVILVL, LASX256WOpnd>; -+ -+def XVILVL_D : LASX_3R<0b01110101000110111>, -+ LASX_3R_DESC_BASE<"xvilvl.d", LoongArchVILVL, LASX256DOpnd>; -+ -+ -+def XVILVH_B : LASX_3R<0b01110101000111000>, -+ LASX_3R_DESC_BASE<"xvilvh.b", LoongArchVILVH, LASX256BOpnd>; -+ -+def XVILVH_H : LASX_3R<0b01110101000111001>, -+ LASX_3R_DESC_BASE<"xvilvh.h", LoongArchVILVH, LASX256HOpnd>; -+ -+def XVILVH_W : LASX_3R<0b01110101000111010>, -+ LASX_3R_DESC_BASE<"xvilvh.w", LoongArchVILVH, LASX256WOpnd>; -+ -+def XVILVH_D : LASX_3R<0b01110101000111011>, -+ LASX_3R_DESC_BASE<"xvilvh.d", LoongArchVILVH, LASX256DOpnd>; -+ -+ -+def XVPICKEV_B : LASX_3R<0b01110101000111100>, -+ LASX_3R_DESC_BASE<"xvpickev.b", LoongArchVPICKEV, LASX256BOpnd>; -+ -+def XVPICKEV_H : LASX_3R<0b01110101000111101>, -+ LASX_3R_DESC_BASE<"xvpickev.h", LoongArchVPICKEV, LASX256HOpnd>; -+ -+def XVPICKEV_W : LASX_3R<0b01110101000111110>, -+ LASX_3R_DESC_BASE<"xvpickev.w", LoongArchVPICKEV, LASX256WOpnd>; -+ -+def XVPICKEV_D : LASX_3R<0b01110101000111111>, -+ LASX_3R_DESC_BASE<"xvpickev.d", LoongArchVPICKEV, LASX256DOpnd>; -+ -+ -+def XVPICKOD_B : LASX_3R<0b01110101001000000>, -+ LASX_3R_DESC_BASE<"xvpickod.b", LoongArchVPICKOD, LASX256BOpnd>; -+ -+def XVPICKOD_H : LASX_3R<0b01110101001000001>, -+ LASX_3R_DESC_BASE<"xvpickod.h", LoongArchVPICKOD, LASX256HOpnd>; -+ -+def XVPICKOD_W : LASX_3R<0b01110101001000010>, -+ LASX_3R_DESC_BASE<"xvpickod.w", LoongArchVPICKOD, LASX256WOpnd>; -+ -+def XVPICKOD_D : LASX_3R<0b01110101001000011>, -+ LASX_3R_DESC_BASE<"xvpickod.d", LoongArchVPICKOD, LASX256DOpnd>; -+ -+ -+def XVREPLVE_B : LASX_3R_1GP<0b01110101001000100>, -+ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.b", int_loongarch_lasx_xvreplve_b, LASX256BOpnd>; -+ -+def XVREPLVE_H : LASX_3R_1GP<0b01110101001000101>, -+ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.h", int_loongarch_lasx_xvreplve_h, LASX256HOpnd>; -+ -+def XVREPLVE_W : LASX_3R_1GP<0b01110101001000110>, -+ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.w", int_loongarch_lasx_xvreplve_w, LASX256WOpnd>; -+ -+def XVREPLVE_D : LASX_3R_1GP<0b01110101001000111>, -+ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.d", int_loongarch_lasx_xvreplve_d, LASX256DOpnd>; -+ -+ -+def XVAND_V : LASX_3R<0b01110101001001100>, -+ LASX_VEC_DESC_BASE<"xvand.v", and, LASX256BOpnd>; -+class XAND_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XAND_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XAND_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+ -+def XAND_V_H_PSEUDO : XAND_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XAND_V_W_PSEUDO : XAND_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XAND_V_D_PSEUDO : XAND_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+ -+def XVOR_V : LASX_3R<0b01110101001001101>, -+ LASX_VEC_DESC_BASE<"xvor.v", or, LASX256BOpnd>; -+class X_OR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class X_OR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class X_OR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+ -+def X_OR_V_H_PSEUDO : X_OR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def X_OR_V_W_PSEUDO : X_OR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def X_OR_V_D_PSEUDO : X_OR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+ -+def XVXOR_V : LASX_3R<0b01110101001001110>, -+ LASX_VEC_DESC_BASE<"xvxor.v", xor, LASX256BOpnd>; -+class XXOR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XXOR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XXOR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+ -+def XXOR_V_H_PSEUDO : XXOR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XXOR_V_W_PSEUDO : XXOR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XXOR_V_D_PSEUDO : XXOR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+ -+def XVNOR_V : LASX_3R<0b01110101001001111>, -+ LASX_VEC_DESC_BASE<"xvnor.v", LoongArchVNOR, LASX256BOpnd>; -+ -+class XNOR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XNOR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+class XNOR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; -+ -+def XNOR_V_H_PSEUDO : XNOR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XNOR_V_W_PSEUDO : XNOR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+def XNOR_V_D_PSEUDO : XNOR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+ -+def XVANDN_V : LASX_3R<0b01110101001010000>, -+ LASX_3R_DESC_BASE<"xvandn.v", int_loongarch_lasx_xvandn_v, LASX256BOpnd>; -+ -+ -+class LASX_ANDN_PSEUDO_BASE : -+ LASXPseudo<(outs RO:$xd), (ins RO:$xj, RO:$xk), -+ []>, -+ PseudoInstExpansion<(XVANDN_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+def XVANDN_H_PSEUDO : LASX_ANDN_PSEUDO_BASE; -+def XVANDN_W_PSEUDO : LASX_ANDN_PSEUDO_BASE; -+def XVANDN_D_PSEUDO : LASX_ANDN_PSEUDO_BASE; -+ -+ -+def XVORN_V : LASX_3R<0b01110101001010001>, -+ LASX_3R_DESC_BASE<"xvorn.v", int_loongarch_lasx_xvorn_v, LASX256BOpnd>; -+ -+ -+class LASX_ORN_PSEUDO_BASE : -+ LASXPseudo<(outs RO:$xd), (ins RO:$xj, RO:$xk), -+ []>, -+ PseudoInstExpansion<(XVORN_V LASX256BOpnd:$xd, -+ LASX256BOpnd:$xj, -+ LASX256BOpnd:$xk)>; -+ -+def XVORN_H_PSEUDO : LASX_ORN_PSEUDO_BASE; -+def XVORN_W_PSEUDO : LASX_ORN_PSEUDO_BASE; -+def XVORN_D_PSEUDO : LASX_ORN_PSEUDO_BASE; -+ -+ -+def XVFRSTP_B : LASX_3R<0b01110101001010110>, -+ LASX_3R_4R_DESC_BASE<"xvfrstp.b", int_loongarch_lasx_xvfrstp_b, LASX256BOpnd>; -+ -+def XVFRSTP_H : LASX_3R<0b01110101001010111>, -+ LASX_3R_4R_DESC_BASE<"xvfrstp.h", int_loongarch_lasx_xvfrstp_h, LASX256HOpnd>; -+ -+ -+def XVADD_Q : LASX_3R<0b01110101001011010>, IsCommutable, -+ LASX_3R_DESC_BASE<"xvadd.q", int_loongarch_lasx_xvadd_q, LASX256DOpnd>; -+ -+def XVSUB_Q : LASX_3R<0b01110101001011011>, -+ LASX_3R_DESC_BASE<"xvsub.q", int_loongarch_lasx_xvsub_q, LASX256DOpnd>; -+ -+ -+def XVSIGNCOV_B : LASX_3R<0b01110101001011100>, -+ LASX_3R_DESC_BASE<"xvsigncov.b", int_loongarch_lasx_xvsigncov_b, LASX256BOpnd>; -+ -+def XVSIGNCOV_H : LASX_3R<0b01110101001011101>, -+ LASX_3R_DESC_BASE<"xvsigncov.h", int_loongarch_lasx_xvsigncov_h, LASX256HOpnd>; -+ -+def XVSIGNCOV_W : LASX_3R<0b01110101001011110>, -+ LASX_3R_DESC_BASE<"xvsigncov.w", int_loongarch_lasx_xvsigncov_w, LASX256WOpnd>; -+ -+def XVSIGNCOV_D : LASX_3R<0b01110101001011111>, -+ LASX_3R_DESC_BASE<"xvsigncov.d", int_loongarch_lasx_xvsigncov_d, LASX256DOpnd>; -+ -+ -+def XVFADD_S : LASX_3R<0b01110101001100001>, IsCommutable, -+ LASX_3RF_DESC_BASE<"xvfadd.s", fadd, LASX256WOpnd>; -+ -+def XVFADD_D : LASX_3R<0b01110101001100010>, IsCommutable, -+ LASX_3RF_DESC_BASE<"xvfadd.d", fadd, LASX256DOpnd>; -+ -+ -+def XVFSUB_S : LASX_3R<0b01110101001100101>, -+ LASX_3RF_DESC_BASE<"xvfsub.s", fsub, LASX256WOpnd>; -+ -+def XVFSUB_D : LASX_3R<0b01110101001100110>, -+ LASX_3RF_DESC_BASE<"xvfsub.d", fsub, LASX256DOpnd>; -+ -+ -+def XVFMUL_S : LASX_3R<0b01110101001110001>, -+ LASX_3RF_DESC_BASE<"xvfmul.s", fmul, LASX256WOpnd>; -+ -+def XVFMUL_D : LASX_3R<0b01110101001110010>, -+ LASX_3RF_DESC_BASE<"xvfmul.d", fmul, LASX256DOpnd>; -+ -+ -+def XVFDIV_S : LASX_3R<0b01110101001110101>, -+ LASX_3RF_DESC_BASE<"xvfdiv.s", fdiv, LASX256WOpnd>; -+ -+def XVFDIV_D : LASX_3R<0b01110101001110110>, -+ LASX_3RF_DESC_BASE<"xvfdiv.d", fdiv, LASX256DOpnd>; -+ -+ -+def XVFMAX_S : LASX_3R<0b01110101001111001>, -+ LASX_3RF_DESC_BASE<"xvfmax.s", int_loongarch_lasx_xvfmax_s, LASX256WOpnd>; -+ -+def XVFMAX_D : LASX_3R<0b01110101001111010>, -+ LASX_3RF_DESC_BASE<"xvfmax.d", int_loongarch_lasx_xvfmax_d, LASX256DOpnd>; -+ -+ -+def XVFMIN_S : LASX_3R<0b01110101001111101>, -+ LASX_3RF_DESC_BASE<"xvfmin.s", int_loongarch_lasx_xvfmin_s, LASX256WOpnd>; -+ -+def XVFMIN_D : LASX_3R<0b01110101001111110>, -+ LASX_3RF_DESC_BASE<"xvfmin.d", int_loongarch_lasx_xvfmin_d, LASX256DOpnd>; -+ -+ -+def XVFMAXA_S : LASX_3R<0b01110101010000001>, -+ LASX_3RF_DESC_BASE<"xvfmaxa.s", int_loongarch_lasx_xvfmaxa_s, LASX256WOpnd>; -+ -+def XVFMAXA_D : LASX_3R<0b01110101010000010>, -+ LASX_3RF_DESC_BASE<"xvfmaxa.d", int_loongarch_lasx_xvfmaxa_d, LASX256DOpnd>; -+ -+ -+def XVFMINA_S : LASX_3R<0b01110101010000101>, -+ LASX_3RF_DESC_BASE<"xvfmina.s", int_loongarch_lasx_xvfmina_s, LASX256WOpnd>; -+ -+def XVFMINA_D : LASX_3R<0b01110101010000110>, -+ LASX_3RF_DESC_BASE<"xvfmina.d", int_loongarch_lasx_xvfmina_d, LASX256DOpnd>; -+ -+ -+def XVFCVT_H_S : LASX_3R<0b01110101010001100>, -+ LASX_3RF_DESC_BASE<"xvfcvt.h.s", int_loongarch_lasx_xvfcvt_h_s, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVFCVT_S_D : LASX_3R<0b01110101010001101>, -+ LASX_3RF_DESC_BASE1<"xvfcvt.s.d", int_loongarch_lasx_xvfcvt_s_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVFFINT_S_L : LASX_3R<0b01110101010010000>, -+ LASX_3RF_DESC_BASE<"xvffint.s.l", int_loongarch_lasx_xvffint_s_l, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+def XVFTINT_W_D : LASX_3R<0b01110101010010011>, -+ LASX_3RF_DESC_BASE<"xvftint.w.d", int_loongarch_lasx_xvftint_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVFTINTRM_W_D : LASX_3R<0b01110101010010100>, -+ LASX_3RF_DESC_BASE<"xvftintrm.w.d", int_loongarch_lasx_xvftintrm_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+def XVFTINTRP_W_D : LASX_3R<0b01110101010010101>, -+ LASX_3RF_DESC_BASE<"xvftintrp.w.d", int_loongarch_lasx_xvftintrp_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+def XVFTINTRZ_W_D : LASX_3R<0b01110101010010110>, -+ LASX_3RF_DESC_BASE<"xvftintrz.w.d", int_loongarch_lasx_xvftintrz_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+def XVFTINTRNE_W_D : LASX_3R<0b01110101010010111>, -+ LASX_3RF_DESC_BASE<"xvftintrne.w.d", int_loongarch_lasx_xvftintrne_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSHUF_H : LASX_3R<0b01110101011110101>, -+ LASX_3R_VSHF_DESC_BASE<"xvshuf.h", LASX256HOpnd>; -+ -+def XVSHUF_W : LASX_3R<0b01110101011110110>, -+ LASX_3R_VSHF_DESC_BASE<"xvshuf.w", LASX256WOpnd>; -+ -+def XVSHUF_D : LASX_3R<0b01110101011110111>, -+ LASX_3R_VSHF_DESC_BASE<"xvshuf.d", LASX256DOpnd>; -+ -+ -+def XVPERM_W : LASX_3R<0b01110101011111010>, -+ LASX_3R_DESC_BASE<"xvperm.w", int_loongarch_lasx_xvperm_w, LASX256WOpnd>; -+ -+ -+def XVSEQI_B : LASX_I5<0b01110110100000000>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.b", int_loongarch_lasx_xvseqi_b, simm5_32, immSExt5, LASX256BOpnd>; -+ -+def XVSEQI_H : LASX_I5<0b01110110100000001>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.h", int_loongarch_lasx_xvseqi_h, simm5_32, immSExt5, LASX256HOpnd>; -+ -+def XVSEQI_W : LASX_I5<0b01110110100000010>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.w", int_loongarch_lasx_xvseqi_w, simm5_32, immSExt5, LASX256WOpnd>; -+ -+def XVSEQI_D : LASX_I5<0b01110110100000011>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.d", int_loongarch_lasx_xvseqi_d, simm5_32, immSExt5, LASX256DOpnd>; -+ -+ -+def XVSLEI_B : LASX_I5<0b01110110100000100>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.b", int_loongarch_lasx_xvslei_b, simm5_32, immSExt5, LASX256BOpnd>; -+ -+def XVSLEI_H : LASX_I5<0b01110110100000101>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.h", int_loongarch_lasx_xvslei_h, simm5_32, immSExt5, LASX256HOpnd>; -+ -+def XVSLEI_W : LASX_I5<0b01110110100000110>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.w", int_loongarch_lasx_xvslei_w, simm5_32, immSExt5, LASX256WOpnd>; -+ -+def XVSLEI_D : LASX_I5<0b01110110100000111>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.d", int_loongarch_lasx_xvslei_d, simm5_32, immSExt5, LASX256DOpnd>; -+ -+ -+def XVSLEI_BU : LASX_I5_U<0b01110110100001000>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.bu", int_loongarch_lasx_xvslei_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVSLEI_HU : LASX_I5_U<0b01110110100001001>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.hu", int_loongarch_lasx_xvslei_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSLEI_WU : LASX_I5_U<0b01110110100001010>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.wu", int_loongarch_lasx_xvslei_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSLEI_DU : LASX_I5_U<0b01110110100001011>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.du", int_loongarch_lasx_xvslei_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVSLTI_B : LASX_I5<0b01110110100001100>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.b", int_loongarch_lasx_xvslti_b, simm5_32, immSExt5, LASX256BOpnd>; -+ -+def XVSLTI_H : LASX_I5<0b01110110100001101>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.h", int_loongarch_lasx_xvslti_h, simm5_32, immSExt5, LASX256HOpnd>; -+ -+def XVSLTI_W : LASX_I5<0b01110110100001110>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.w", int_loongarch_lasx_xvslti_w, simm5_32, immSExt5, LASX256WOpnd>; -+ -+def XVSLTI_D : LASX_I5<0b01110110100001111>, -+ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.d", int_loongarch_lasx_xvslti_d, simm5_32, immSExt5, LASX256DOpnd>; -+ -+ -+def XVSLTI_BU : LASX_I5_U<0b01110110100010000>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.bu", int_loongarch_lasx_xvslti_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVSLTI_HU : LASX_I5_U<0b01110110100010001>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.hu", int_loongarch_lasx_xvslti_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSLTI_WU : LASX_I5_U<0b01110110100010010>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.wu", int_loongarch_lasx_xvslti_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSLTI_DU : LASX_I5_U<0b01110110100010011>, -+ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.du", int_loongarch_lasx_xvslti_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVADDI_BU : LASX_I5_U<0b01110110100010100>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.bu", int_loongarch_lasx_xvaddi_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVADDI_HU : LASX_I5_U<0b01110110100010101>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.hu", int_loongarch_lasx_xvaddi_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVADDI_WU : LASX_I5_U<0b01110110100010110>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.wu", int_loongarch_lasx_xvaddi_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVADDI_DU : LASX_I5_U<0b01110110100010111>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.du", int_loongarch_lasx_xvaddi_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVSUBI_BU : LASX_I5_U<0b01110110100011000>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.bu", int_loongarch_lasx_xvsubi_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVSUBI_HU : LASX_I5_U<0b01110110100011001>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.hu", int_loongarch_lasx_xvsubi_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSUBI_WU : LASX_I5_U<0b01110110100011010>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.wu", int_loongarch_lasx_xvsubi_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSUBI_DU : LASX_I5_U<0b01110110100011011>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.du", int_loongarch_lasx_xvsubi_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVBSLL_V : LASX_I5_U<0b01110110100011100>, -+ LASX_U5_DESC_BASE<"xvbsll.v", int_loongarch_lasx_xvbsll_v, LASX256BOpnd>; -+ -+def XVBSRL_V : LASX_I5_U<0b01110110100011101>, -+ LASX_U5_DESC_BASE<"xvbsrl.v", int_loongarch_lasx_xvbsrl_v, LASX256BOpnd>; -+ -+ -+def XVMAXI_B : LASX_I5<0b01110110100100000>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.b", int_loongarch_lasx_xvmaxi_b, simm5_32, immSExt5, LASX256BOpnd>; -+ -+def XVMAXI_H : LASX_I5<0b01110110100100001>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.h", int_loongarch_lasx_xvmaxi_h, simm5_32, immSExt5, LASX256HOpnd>; -+ -+def XVMAXI_W : LASX_I5<0b01110110100100010>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.w", int_loongarch_lasx_xvmaxi_w, simm5_32, immSExt5, LASX256WOpnd>; -+ -+def XVMAXI_D : LASX_I5<0b01110110100100011>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.d", int_loongarch_lasx_xvmaxi_d, simm5_32, immSExt5, LASX256DOpnd>; -+ -+ -+def XVMINI_B : LASX_I5<0b01110110100100100>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmini.b", int_loongarch_lasx_xvmini_b, simm5_32, immSExt5, LASX256BOpnd>; -+ -+def XVMINI_H : LASX_I5<0b01110110100100101>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmini.h", int_loongarch_lasx_xvmini_h, simm5_32, immSExt5, LASX256HOpnd>; -+ -+def XVMINI_W : LASX_I5<0b01110110100100110>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmini.w", int_loongarch_lasx_xvmini_w, simm5_32, immSExt5, LASX256WOpnd>; -+ -+def XVMINI_D : LASX_I5<0b01110110100100111>, -+ LASX_I5_DESC_BASE_Intrinsic<"xvmini.d", int_loongarch_lasx_xvmini_d, simm5_32, immSExt5, LASX256DOpnd>; -+ -+ -+def XVMAXI_BU : LASX_I5_U<0b01110110100101000>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.bu", int_loongarch_lasx_xvmaxi_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVMAXI_HU : LASX_I5_U<0b01110110100101001>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.hu", int_loongarch_lasx_xvmaxi_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVMAXI_WU : LASX_I5_U<0b01110110100101010>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.wu", int_loongarch_lasx_xvmaxi_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVMAXI_DU : LASX_I5_U<0b01110110100101011>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.du", int_loongarch_lasx_xvmaxi_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVMINI_BU : LASX_I5_U<0b01110110100101100>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.bu", int_loongarch_lasx_xvmini_bu, uimm5, immZExt5, LASX256BOpnd>; -+ -+def XVMINI_HU : LASX_I5_U<0b01110110100101101>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.hu", int_loongarch_lasx_xvmini_hu, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVMINI_WU : LASX_I5_U<0b01110110100101110>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.wu", int_loongarch_lasx_xvmini_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVMINI_DU : LASX_I5_U<0b01110110100101111>, -+ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.du", int_loongarch_lasx_xvmini_du, uimm5, immZExt5, LASX256DOpnd>; -+ -+ -+def XVFRSTPI_B : LASX_I5_U<0b01110110100110100>, -+ LASX_U5_4R_DESC_BASE<"xvfrstpi.b", int_loongarch_lasx_xvfrstpi_b, LASX256BOpnd>; -+ -+def XVFRSTPI_H : LASX_I5_U<0b01110110100110101>, -+ LASX_U5_4R_DESC_BASE<"xvfrstpi.h", int_loongarch_lasx_xvfrstpi_h, LASX256HOpnd>; -+ -+ -+def XVCLO_B : LASX_2R<0b0111011010011100000000>, -+ LASX_2R_DESC_BASE<"xvclo.b", int_loongarch_lasx_xvclo_b, LASX256BOpnd>; -+ -+def XVCLO_H : LASX_2R<0b0111011010011100000001>, -+ LASX_2R_DESC_BASE<"xvclo.h", int_loongarch_lasx_xvclo_h, LASX256HOpnd>; -+ -+def XVCLO_W : LASX_2R<0b0111011010011100000010>, -+ LASX_2R_DESC_BASE<"xvclo.w", int_loongarch_lasx_xvclo_w, LASX256WOpnd>; -+ -+def XVCLO_D : LASX_2R<0b0111011010011100000011>, -+ LASX_2R_DESC_BASE<"xvclo.d", int_loongarch_lasx_xvclo_d, LASX256DOpnd>; -+ -+ -+def XVCLZ_B : LASX_2R<0b0111011010011100000100>, -+ LASX_2R_DESC_BASE<"xvclz.b", ctlz, LASX256BOpnd>; -+ -+def XVCLZ_H : LASX_2R<0b0111011010011100000101>, -+ LASX_2R_DESC_BASE<"xvclz.h", ctlz, LASX256HOpnd>; -+ -+def XVCLZ_W : LASX_2R<0b0111011010011100000110>, -+ LASX_2R_DESC_BASE<"xvclz.w", ctlz, LASX256WOpnd>; -+ -+def XVCLZ_D : LASX_2R<0b0111011010011100000111>, -+ LASX_2R_DESC_BASE<"xvclz.d", ctlz, LASX256DOpnd>; -+ -+ -+def XVPCNT_B : LASX_2R<0b0111011010011100001000>, -+ LASX_2R_DESC_BASE<"xvpcnt.b", ctpop, LASX256BOpnd>; -+ -+def XVPCNT_H : LASX_2R<0b0111011010011100001001>, -+ LASX_2R_DESC_BASE<"xvpcnt.h", ctpop, LASX256HOpnd>; -+ -+def XVPCNT_W : LASX_2R<0b0111011010011100001010>, -+ LASX_2R_DESC_BASE<"xvpcnt.w", ctpop, LASX256WOpnd>; -+ -+def XVPCNT_D : LASX_2R<0b0111011010011100001011>, -+ LASX_2R_DESC_BASE<"xvpcnt.d", ctpop, LASX256DOpnd>; -+ -+ -+def XVNEG_B : LASX_2R<0b0111011010011100001100>, -+ LASX_2R_DESC_BASE<"xvneg.b", int_loongarch_lasx_xvneg_b, LASX256BOpnd>; -+ -+def XVNEG_H : LASX_2R<0b0111011010011100001101>, -+ LASX_2R_DESC_BASE<"xvneg.h", int_loongarch_lasx_xvneg_h, LASX256HOpnd>; -+ -+def XVNEG_W : LASX_2R<0b0111011010011100001110>, -+ LASX_2R_DESC_BASE<"xvneg.w", int_loongarch_lasx_xvneg_w, LASX256WOpnd>; -+ -+def XVNEG_D : LASX_2R<0b0111011010011100001111>, -+ LASX_2R_DESC_BASE<"xvneg.d", int_loongarch_lasx_xvneg_d, LASX256DOpnd>; -+ -+ -+def XVMSKLTZ_B : LASX_2R<0b0111011010011100010000>, -+ LASX_2R_DESC_BASE<"xvmskltz.b", int_loongarch_lasx_xvmskltz_b, LASX256BOpnd>; -+ -+def XVMSKLTZ_H : LASX_2R<0b0111011010011100010001>, -+ LASX_2R_DESC_BASE<"xvmskltz.h", int_loongarch_lasx_xvmskltz_h, LASX256HOpnd>; -+ -+def XVMSKLTZ_W : LASX_2R<0b0111011010011100010010>, -+ LASX_2R_DESC_BASE<"xvmskltz.w", int_loongarch_lasx_xvmskltz_w, LASX256WOpnd>; -+ -+def XVMSKLTZ_D : LASX_2R<0b0111011010011100010011>, -+ LASX_2R_DESC_BASE<"xvmskltz.d", int_loongarch_lasx_xvmskltz_d, LASX256DOpnd>; -+ -+ -+def XVMSKGEZ_B : LASX_2R<0b0111011010011100010100>, -+ LASX_2R_DESC_BASE<"xvmskgez.b", int_loongarch_lasx_xvmskgez_b, LASX256BOpnd>; -+ -+def XVMSKNZ_B : LASX_2R<0b0111011010011100011000>, -+ LASX_2R_DESC_BASE<"xvmsknz.b", int_loongarch_lasx_xvmsknz_b, LASX256BOpnd>; -+ -+ -+def XVSETEQZ_V : LASX_SET<0b0111011010011100100110>, -+ LASX_SET_DESC_BASE<"xvseteqz.v", LASX256BOpnd>; -+ -+def XVSETNEZ_V : LASX_SET<0b0111011010011100100111>, -+ LASX_SET_DESC_BASE<"xvsetnez.v", LASX256BOpnd>; -+ -+ -+def XVSETANYEQZ_B : LASX_SET<0b0111011010011100101000>, -+ LASX_SET_DESC_BASE<"xvsetanyeqz.b", LASX256BOpnd>; -+ -+def XVSETANYEQZ_H : LASX_SET<0b0111011010011100101001>, -+ LASX_SET_DESC_BASE<"xvsetanyeqz.h", LASX256HOpnd>; -+ -+def XVSETANYEQZ_W : LASX_SET<0b0111011010011100101010>, -+ LASX_SET_DESC_BASE<"xvsetanyeqz.w", LASX256WOpnd>; -+ -+def XVSETANYEQZ_D : LASX_SET<0b0111011010011100101011>, -+ LASX_SET_DESC_BASE<"xvsetanyeqz.d", LASX256DOpnd>; -+ -+ -+def XVSETALLNEZ_B : LASX_SET<0b0111011010011100101100>, -+ LASX_SET_DESC_BASE<"xvsetallnez.b", LASX256BOpnd>; -+ -+def XVSETALLNEZ_H : LASX_SET<0b0111011010011100101101>, -+ LASX_SET_DESC_BASE<"xvsetallnez.h", LASX256HOpnd>; -+ -+def XVSETALLNEZ_W : LASX_SET<0b0111011010011100101110>, -+ LASX_SET_DESC_BASE<"xvsetallnez.w", LASX256WOpnd>; -+ -+def XVSETALLNEZ_D : LASX_SET<0b0111011010011100101111>, -+ LASX_SET_DESC_BASE<"xvsetallnez.d", LASX256DOpnd>; -+ -+class LASX_CBRANCH_PSEUDO_DESC_BASE : -+ LoongArchPseudo<(outs GPR32:$dst), -+ (ins RCWS:$xj), -+ [(set GPR32:$dst, (OpNode (TyNode RCWS:$xj)))]> { -+ bit usesCustomInserter = 1; -+} -+ -+def XSNZ_B_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSNZ_H_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSNZ_W_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSNZ_D_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSNZ_V_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+ -+def XSZ_B_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSZ_H_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSZ_W_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSZ_D_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+def XSZ_V_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; -+ -+ -+def XVFLOGB_S : LASX_2R<0b0111011010011100110001>, -+ LASX_2RF_DESC_BASE<"xvflogb.s", int_loongarch_lasx_xvflogb_s, LASX256WOpnd>; -+ -+def XVFLOGB_D : LASX_2R<0b0111011010011100110010>, -+ LASX_2RF_DESC_BASE<"xvflogb.d", int_loongarch_lasx_xvflogb_d, LASX256DOpnd>; -+ -+ -+def XVFCLASS_S : LASX_2R<0b0111011010011100110101>, -+ LASX_2RF_DESC_BASE<"xvfclass.s", int_loongarch_lasx_xvfclass_s, LASX256WOpnd>; -+ -+def XVFCLASS_D : LASX_2R<0b0111011010011100110110>, -+ LASX_2RF_DESC_BASE<"xvfclass.d", int_loongarch_lasx_xvfclass_d, LASX256DOpnd>; -+ -+ -+def XVFSQRT_S : LASX_2R<0b0111011010011100111001>, -+ LASX_2RF_DESC_BASE<"xvfsqrt.s", fsqrt, LASX256WOpnd>; -+ -+def XVFSQRT_D : LASX_2R<0b0111011010011100111010>, -+ LASX_2RF_DESC_BASE<"xvfsqrt.d", fsqrt, LASX256DOpnd>; -+ -+ -+def XVFRECIP_S : LASX_2R<0b0111011010011100111101>, -+ LASX_2RF_DESC_BASE<"xvfrecip.s", int_loongarch_lasx_xvfrecip_s, LASX256WOpnd>; -+ -+def XVFRECIP_D : LASX_2R<0b0111011010011100111110>, -+ LASX_2RF_DESC_BASE<"xvfrecip.d", int_loongarch_lasx_xvfrecip_d, LASX256DOpnd>; -+ -+ -+def XVFRSQRT_S : LASX_2R<0b0111011010011101000001>, -+ LASX_2RF_DESC_BASE<"xvfrsqrt.s", int_loongarch_lasx_xvfrsqrt_s, LASX256WOpnd>; -+ -+def XVFRSQRT_D : LASX_2R<0b0111011010011101000010>, -+ LASX_2RF_DESC_BASE<"xvfrsqrt.d", int_loongarch_lasx_xvfrsqrt_d, LASX256DOpnd>; -+ -+ -+def XVFRINT_S : LASX_2R<0b0111011010011101001101>, -+ LASX_2RF_DESC_BASE<"xvfrint.s", frint, LASX256WOpnd>; -+ -+def XVFRINT_D : LASX_2R<0b0111011010011101001110>, -+ LASX_2RF_DESC_BASE<"xvfrint.d", frint, LASX256DOpnd>; -+ -+ -+def XVFRINTRM_S : LASX_2R<0b0111011010011101010001>, -+ LASX_2RF_DESC_BASE<"xvfrintrm.s", int_loongarch_lasx_xvfrintrm_s, LASX256WOpnd>; -+ -+def XVFRINTRM_D : LASX_2R<0b0111011010011101010010>, -+ LASX_2RF_DESC_BASE<"xvfrintrm.d", int_loongarch_lasx_xvfrintrm_d, LASX256DOpnd>; -+ -+ -+def XVFRINTRP_S : LASX_2R<0b0111011010011101010101>, -+ LASX_2RF_DESC_BASE<"xvfrintrp.s", int_loongarch_lasx_xvfrintrp_s, LASX256WOpnd>; -+ -+def XVFRINTRP_D : LASX_2R<0b0111011010011101010110>, -+ LASX_2RF_DESC_BASE<"xvfrintrp.d", int_loongarch_lasx_xvfrintrp_d, LASX256DOpnd>; -+ -+ -+def XVFRINTRZ_S : LASX_2R<0b0111011010011101011001>, -+ LASX_2RF_DESC_BASE<"xvfrintrz.s", int_loongarch_lasx_xvfrintrz_s, LASX256WOpnd>; -+ -+def XVFRINTRZ_D : LASX_2R<0b0111011010011101011010>, -+ LASX_2RF_DESC_BASE<"xvfrintrz.d", int_loongarch_lasx_xvfrintrz_d, LASX256DOpnd>; -+ -+ -+def XVFRINTRNE_S : LASX_2R<0b0111011010011101011101>, -+ LASX_2RF_DESC_BASE<"xvfrintrne.s", int_loongarch_lasx_xvfrintrne_s, LASX256WOpnd>; -+ -+def XVFRINTRNE_D : LASX_2R<0b0111011010011101011110>, -+ LASX_2RF_DESC_BASE<"xvfrintrne.d", int_loongarch_lasx_xvfrintrne_d, LASX256DOpnd>; -+ -+ -+def XVFCVTL_S_H : LASX_2R<0b0111011010011101111010>, -+ LASX_2RF_DESC_BASE<"xvfcvtl.s.h", int_loongarch_lasx_xvfcvtl_s_h, LASX256WOpnd, LASX256HOpnd>; -+ -+def XVFCVTH_S_H : LASX_2R<0b0111011010011101111011>, -+ LASX_2RF_DESC_BASE<"xvfcvth.s.h", int_loongarch_lasx_xvfcvth_s_h, LASX256WOpnd, LASX256HOpnd>; -+ -+ -+def XVFCVTL_D_S : LASX_2R<0b0111011010011101111100>, -+ LASX_2RF_DESC_BASE<"xvfcvtl.d.s", int_loongarch_lasx_xvfcvtl_d_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFCVTH_D_S : LASX_2R<0b0111011010011101111101>, -+ LASX_2RF_DESC_BASE<"xvfcvth.d.s", int_loongarch_lasx_xvfcvth_d_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFFINT_S_W : LASX_2R<0b0111011010011110000000>, -+ LASX_2RF_DESC_BASE<"xvffint.s.w", sint_to_fp, LASX256WOpnd>; -+ -+def XVFFINT_S_WU : LASX_2R<0b0111011010011110000001>, -+ LASX_2RF_DESC_BASE<"xvffint.s.wu", uint_to_fp, LASX256WOpnd>; -+ -+ -+def XVFFINT_D_L : LASX_2R<0b0111011010011110000010>, -+ LASX_2RF_DESC_BASE<"xvffint.d.l", sint_to_fp, LASX256DOpnd>; -+ -+def XVFFINT_D_LU : LASX_2R<0b0111011010011110000011>, -+ LASX_2RF_DESC_BASE<"xvffint.d.lu", uint_to_fp, LASX256DOpnd>; -+ -+ -+def XVFFINTL_D_W : LASX_2R<0b0111011010011110000100>, -+ LASX_2RF_DESC_BASE<"xvffintl.d.w", int_loongarch_lasx_xvffintl_d_w, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFFINTH_D_W : LASX_2R<0b0111011010011110000101>, -+ LASX_2RF_DESC_BASE<"xvffinth.d.w", int_loongarch_lasx_xvffinth_d_w, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFTINT_W_S : LASX_2R<0b0111011010011110001100>, -+ LASX_2RF_DESC_BASE<"xvftint.w.s", int_loongarch_lasx_xvftint_w_s, LASX256WOpnd>; -+ -+def XVFTINT_L_D : LASX_2R<0b0111011010011110001101>, -+ LASX_2RF_DESC_BASE<"xvftint.l.d", int_loongarch_lasx_xvftint_l_d, LASX256DOpnd>; -+ -+ -+def XVFTINTRM_W_S : LASX_2R<0b0111011010011110001110>, -+ LASX_2RF_DESC_BASE<"xvftintrm.w.s", int_loongarch_lasx_xvftintrm_w_s, LASX256WOpnd>; -+ -+def XVFTINTRM_L_D : LASX_2R<0b0111011010011110001111>, -+ LASX_2RF_DESC_BASE<"xvftintrm.l.d", int_loongarch_lasx_xvftintrm_l_d, LASX256DOpnd>; -+ -+ -+def XVFTINTRP_W_S : LASX_2R<0b0111011010011110010000>, -+ LASX_2RF_DESC_BASE<"xvftintrp.w.s", int_loongarch_lasx_xvftintrp_w_s, LASX256WOpnd>; -+ -+def XVFTINTRP_L_D : LASX_2R<0b0111011010011110010001>, -+ LASX_2RF_DESC_BASE<"xvftintrp.l.d", int_loongarch_lasx_xvftintrp_l_d, LASX256DOpnd>; -+ -+ -+def XVFTINTRZ_W_S : LASX_2R<0b0111011010011110010010>, -+ LASX_2RF_DESC_BASE<"xvftintrz.w.s", fp_to_sint, LASX256WOpnd>; -+ -+def XVFTINTRZ_L_D : LASX_2R<0b0111011010011110010011>, -+ LASX_2RF_DESC_BASE<"xvftintrz.l.d", fp_to_sint, LASX256DOpnd>; -+ -+ -+def XVFTINTRNE_W_S : LASX_2R<0b0111011010011110010100>, -+ LASX_2RF_DESC_BASE<"xvftintrne.w.s", int_loongarch_lasx_xvftintrne_w_s, LASX256WOpnd>; -+ -+def XVFTINTRNE_L_D : LASX_2R<0b0111011010011110010101>, -+ LASX_2RF_DESC_BASE<"xvftintrne.l.d", int_loongarch_lasx_xvftintrne_l_d, LASX256DOpnd>; -+ -+ -+def XVFTINT_WU_S : LASX_2R<0b0111011010011110010110>, -+ LASX_2RF_DESC_BASE<"xvftint.wu.s", int_loongarch_lasx_xvftint_wu_s, LASX256WOpnd>; -+ -+def XVFTINT_LU_D : LASX_2R<0b0111011010011110010111>, -+ LASX_2RF_DESC_BASE<"xvftint.lu.d", int_loongarch_lasx_xvftint_lu_d, LASX256DOpnd>; -+ -+ -+def XVFTINTRZ_WU_S : LASX_2R<0b0111011010011110011100>, -+ LASX_2RF_DESC_BASE<"xvftintrz.wu.s", fp_to_uint, LASX256WOpnd>; -+ -+def XVFTINTRZ_LU_D : LASX_2R<0b0111011010011110011101>, -+ LASX_2RF_DESC_BASE<"xvftintrz.lu.d", fp_to_uint, LASX256DOpnd>; -+ -+ -+def XVFTINTL_L_S : LASX_2R<0b0111011010011110100000>, -+ LASX_2RF_DESC_BASE<"xvftintl.l.s", int_loongarch_lasx_xvftintl_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFTINTH_L_S : LASX_2R<0b0111011010011110100001>, -+ LASX_2RF_DESC_BASE<"xvftinth.l.s", int_loongarch_lasx_xvftinth_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFTINTRML_L_S : LASX_2R<0b0111011010011110100010>, -+ LASX_2RF_DESC_BASE<"xvftintrml.l.s", int_loongarch_lasx_xvftintrml_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFTINTRMH_L_S : LASX_2R<0b0111011010011110100011>, -+ LASX_2RF_DESC_BASE<"xvftintrmh.l.s", int_loongarch_lasx_xvftintrmh_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFTINTRPL_L_S : LASX_2R<0b0111011010011110100100>, -+ LASX_2RF_DESC_BASE<"xvftintrpl.l.s", int_loongarch_lasx_xvftintrpl_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFTINTRPH_L_S : LASX_2R<0b0111011010011110100101>, -+ LASX_2RF_DESC_BASE<"xvftintrph.l.s", int_loongarch_lasx_xvftintrph_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFTINTRZL_L_S : LASX_2R<0b0111011010011110100110>, -+ LASX_2RF_DESC_BASE<"xvftintrzl.l.s", int_loongarch_lasx_xvftintrzl_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFTINTRZH_L_S : LASX_2R<0b0111011010011110100111>, -+ LASX_2RF_DESC_BASE<"xvftintrzh.l.s", int_loongarch_lasx_xvftintrzh_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVFTINTRNEL_L_S : LASX_2R<0b0111011010011110101000>, -+ LASX_2RF_DESC_BASE<"xvftintrnel.l.s", int_loongarch_lasx_xvftintrnel_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+def XVFTINTRNEH_L_S : LASX_2R<0b0111011010011110101001>, -+ LASX_2RF_DESC_BASE<"xvftintrneh.l.s", int_loongarch_lasx_xvftintrneh_l_s, LASX256DOpnd, LASX256WOpnd>; -+ -+ -+def XVEXTH_H_B : LASX_2R<0b0111011010011110111000>, -+ LASX_2R_DESC_BASE<"xvexth.h.b", int_loongarch_lasx_xvexth_h_b, LASX256HOpnd, LASX256BOpnd>; -+ -+def XVEXTH_W_H : LASX_2R<0b0111011010011110111001>, -+ LASX_2R_DESC_BASE<"xvexth.w.h", int_loongarch_lasx_xvexth_w_h, LASX256WOpnd, LASX256HOpnd>; -+ -+def XVEXTH_D_W : LASX_2R<0b0111011010011110111010>, -+ LASX_2R_DESC_BASE<"xvexth.d.w", int_loongarch_lasx_xvexth_d_w, LASX256DOpnd, LASX256WOpnd> ; -+ -+def XVEXTH_Q_D : LASX_2R<0b0111011010011110111011>, -+ LASX_2R_DESC_BASE<"xvexth.q.d", int_loongarch_lasx_xvexth_q_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVEXTH_HU_BU : LASX_2R<0b0111011010011110111100>, -+ LASX_2R_DESC_BASE<"xvexth.hu.bu", int_loongarch_lasx_xvexth_hu_bu, LASX256HOpnd, LASX256BOpnd>; -+ -+def XVEXTH_WU_HU : LASX_2R<0b0111011010011110111101>, -+ LASX_2R_DESC_BASE<"xvexth.wu.hu", int_loongarch_lasx_xvexth_wu_hu, LASX256WOpnd, LASX256HOpnd>; -+ -+def XVEXTH_DU_WU : LASX_2R<0b0111011010011110111110>, -+ LASX_2R_DESC_BASE<"xvexth.du.wu", int_loongarch_lasx_xvexth_du_wu, LASX256DOpnd, LASX256WOpnd> ; -+ -+def XVEXTH_QU_DU : LASX_2R<0b0111011010011110111111>, -+ LASX_2R_DESC_BASE<"xvexth.qu.du", int_loongarch_lasx_xvexth_qu_du, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVREPLGR2VR_B : LASX_2R_1GP<0b0111011010011111000000>, -+ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.b", v32i8, xvsplati8, LASX256BOpnd, GPR32Opnd>; -+ -+def XVREPLGR2VR_H : LASX_2R_1GP<0b0111011010011111000001>, -+ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.h", v16i16, xvsplati16, LASX256HOpnd, GPR32Opnd>; -+ -+def XVREPLGR2VR_W : LASX_2R_1GP<0b0111011010011111000010>, -+ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.w", v8i32, xvsplati32, LASX256WOpnd, GPR32Opnd>; -+ -+def XVREPLGR2VR_D : LASX_2R_1GP<0b0111011010011111000011>, -+ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.d", v4i64, xvsplati64, LASX256DOpnd, GPR64Opnd>; -+ -+ -+def VEXT2XV_H_B : LASX_2R<0b0111011010011111000100>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.h.b", int_loongarch_lasx_vext2xv_h_b, v32i8, v16i16, LASX256BOpnd, LASX256HOpnd>; -+ -+def VEXT2XV_W_B : LASX_2R<0b0111011010011111000101>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.w.b", int_loongarch_lasx_vext2xv_w_b, v32i8, v8i32, LASX256BOpnd, LASX256WOpnd>; -+ -+def VEXT2XV_D_B : LASX_2R<0b0111011010011111000110>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.b", int_loongarch_lasx_vext2xv_d_b, v32i8, v4i64, LASX256BOpnd, LASX256DOpnd> ; -+ -+def VEXT2XV_W_H : LASX_2R<0b0111011010011111000111>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.w.h", int_loongarch_lasx_vext2xv_w_h, v16i16, v8i32, LASX256HOpnd, LASX256WOpnd>; -+ -+def VEXT2XV_D_H : LASX_2R<0b0111011010011111001000>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.h", int_loongarch_lasx_vext2xv_d_h, v16i16, v4i64, LASX256HOpnd, LASX256DOpnd> ; -+ -+def VEXT2XV_D_W : LASX_2R<0b0111011010011111001001>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.w", int_loongarch_lasx_vext2xv_d_w, v8i32, v4i64, LASX256WOpnd, LASX256DOpnd>; -+ -+ -+def VEXT2XV_HU_BU : LASX_2R<0b0111011010011111001010>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.hu.bu", int_loongarch_lasx_vext2xv_hu_bu, v32i8, v16i16, LASX256BOpnd, LASX256HOpnd>; -+ -+def VEXT2XV_WU_BU : LASX_2R<0b0111011010011111001011>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.wu.bu", int_loongarch_lasx_vext2xv_wu_bu, v32i8, v8i32, LASX256BOpnd, LASX256WOpnd>; -+ -+def VEXT2XV_DU_BU : LASX_2R<0b0111011010011111001100>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.bu", int_loongarch_lasx_vext2xv_du_bu, v32i8, v4i64, LASX256BOpnd, LASX256DOpnd> ; -+ -+def VEXT2XV_WU_HU : LASX_2R<0b0111011010011111001101>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.wu.hu", int_loongarch_lasx_vext2xv_wu_hu, v16i16, v8i32, LASX256HOpnd, LASX256WOpnd>; -+ -+def VEXT2XV_DU_HU : LASX_2R<0b0111011010011111001110>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.hu", int_loongarch_lasx_vext2xv_du_hu, v16i16, v4i64, LASX256HOpnd, LASX256DOpnd> ; -+ -+def VEXT2XV_DU_WU : LASX_2R<0b0111011010011111001111>, -+ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.wu", int_loongarch_lasx_vext2xv_du_wu, v8i32, v4i64, LASX256WOpnd, LASX256DOpnd>; -+ -+ -+def XVHSELI_D : LASX_I5_U<0b01110110100111111>, -+ LASX_U5N_DESC_BASE<"xvhseli.d", LASX256DOpnd>; -+ -+ -+def XVROTRI_B : LASX_I3_U<0b0111011010100000001>, -+ LASX_RORI_U3_DESC_BASE_Intrinsic<"xvrotri.b", int_loongarch_lasx_xvrotri_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVROTRI_H : LASX_I4_U<0b011101101010000001>, -+ LASX_RORI_U4_DESC_BASE_Intrinsic<"xvrotri.h", int_loongarch_lasx_xvrotri_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVROTRI_W : LASX_I5_U<0b01110110101000001>, -+ LASX_RORI_U5_DESC_BASE_Intrinsic<"xvrotri.w", int_loongarch_lasx_xvrotri_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVROTRI_D : LASX_I6_U<0b0111011010100001>, -+ LASX_RORI_U6_DESC_BASE_Intrinsic<"xvrotri.d", int_loongarch_lasx_xvrotri_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSRLRI_B : LASX_I3_U<0b0111011010100100001>, -+ LASX_BIT_3_DESC_BASE<"xvsrlri.b", int_loongarch_lasx_xvsrlri_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSRLRI_H : LASX_I4_U<0b011101101010010001>, -+ LASX_BIT_4_DESC_BASE<"xvsrlri.h", int_loongarch_lasx_xvsrlri_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSRLRI_W : LASX_I5_U<0b01110110101001001>, -+ LASX_BIT_5_DESC_BASE<"xvsrlri.w", int_loongarch_lasx_xvsrlri_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSRLRI_D : LASX_I6_U<0b0111011010100101>, -+ LASX_BIT_6_DESC_BASE<"xvsrlri.d", int_loongarch_lasx_xvsrlri_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSRARI_B : LASX_I3_U<0b0111011010101000001>, -+ LASX_BIT_3_DESC_BASE<"xvsrari.b", int_loongarch_lasx_xvsrari_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSRARI_H : LASX_I4_U<0b011101101010100001>, -+ LASX_BIT_4_DESC_BASE<"xvsrari.h", int_loongarch_lasx_xvsrari_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSRARI_W : LASX_I5_U<0b01110110101010001>, -+ LASX_BIT_5_DESC_BASE<"xvsrari.w", int_loongarch_lasx_xvsrari_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSRARI_D : LASX_I6_U<0b0111011010101001>, -+ LASX_BIT_6_DESC_BASE<"xvsrari.d", int_loongarch_lasx_xvsrari_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVINSGR2VR_W : LASX_I3_R_U<0b0111011011101011110>, -+ LASX_INSERT_U3_DESC_BASE<"xvinsgr2vr.w", v8i32, uimm3_ptr, immZExt3Ptr, LASX256WOpnd, GPR32Opnd>; -+ -+def XVINSGR2VR_D : LASX_I2_R_U<0b01110110111010111110>, -+ LASX_INSERT_U2_DESC_BASE<"xvinsgr2vr.d", v4i64, uimm2_ptr, immZExt2Ptr, LASX256DOpnd, GPR64Opnd>; -+ -+ -+def XVPICKVE2GR_W : LASX_ELM_COPY_U3<0b0111011011101111110>, -+ LASX_COPY_U3_DESC_BASE<"xvpickve2gr.w", vextract_sext_i32, v8i32, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LASX256WOpnd>; -+ -+def XVPICKVE2GR_D : LASX_ELM_COPY_U2<0b01110110111011111110>, -+ LASX_COPY_U2_DESC_BASE<"xvpickve2gr.d", vextract_sext_i64, v4i64, uimm2_ptr, immZExt2Ptr, GPR64Opnd, LASX256DOpnd>; -+ -+ -+def XVPICKVE2GR_WU : LASX_ELM_COPY_U3<0b0111011011110011110>, -+ LASX_COPY_U3_DESC_BASE<"xvpickve2gr.wu", vextract_zext_i32, v8i32, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LASX256WOpnd>; -+ -+def XVPICKVE2GR_DU : LASX_ELM_COPY_U2<0b01110110111100111110>, -+ LASX_COPY_U2_DESC_BASE<"xvpickve2gr.du", vextract_zext_i64, v4i64, uimm2_ptr, immZExt2Ptr, GPR64Opnd, LASX256DOpnd>; -+ -+ -+def XVREPL128VEI_B : LASX_I4_U<0b011101101111011110>, -+ LASX_ELM_U4_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.b", int_loongarch_lasx_xvrepl128vei_b, LASX256BOpnd>; -+ -+def XVREPL128VEI_H : LASX_I3_U<0b0111011011110111110>, -+ LASX_ELM_U3_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.h", int_loongarch_lasx_xvrepl128vei_h, LASX256HOpnd>; -+ -+def XVREPL128VEI_W : LASX_I2_U<0b01110110111101111110>, -+ LASX_ELM_U2_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.w", int_loongarch_lasx_xvrepl128vei_w, LASX256WOpnd>; -+ -+def XVREPL128VEI_D : LASX_I1_U<0b011101101111011111110>, -+ LASX_ELM_U1_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.d", int_loongarch_lasx_xvrepl128vei_d, LASX256DOpnd>; -+ -+ -+def XVINSVE0_W : LASX_I3_U<0b0111011011111111110>, -+ LASX_BIT_3_4O_DESC_BASE<"xvinsve0.w", int_loongarch_lasx_xvinsve0_w, uimm3, immZExt3, LASX256WOpnd>; -+ -+def XVINSVE0_D : LASX_I2_U<0b01110110111111111110>, -+ LASX_BIT_2_4O_DESC_BASE<"xvinsve0.d", int_loongarch_lasx_xvinsve0_d, uimm2, immZExt2, LASX256DOpnd>; -+ -+ -+def XVPICKVE_W : LASX_I3_U<0b0111011100000011110>, -+ LASX_BIT_3_4ON<"xvpickve.w", uimm3, immZExt3, LASX256WOpnd>; -+ -+def XVPICKVE_D : LASX_I2_U<0b01110111000000111110>, -+ LASX_BIT_2_4ON<"xvpickve.d", uimm2, immZExt2, LASX256DOpnd>; -+ -+ -+def XVREPLVE0_B : LASX_2R<0b0111011100000111000000>, -+ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.b", int_loongarch_lasx_xvreplve0_b, v32i8, LASX256BOpnd>; -+ -+def XVREPLVE0_H : LASX_2R<0b0111011100000111100000>, -+ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.h", int_loongarch_lasx_xvreplve0_h, v16i16, LASX256HOpnd>; -+ -+def XVREPLVE0_W : LASX_2R<0b0111011100000111110000>, -+ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.w", int_loongarch_lasx_xvreplve0_w, v8i32, LASX256WOpnd> ; -+ -+def XVREPLVE0_D : LASX_2R<0b0111011100000111111000>, -+ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.d", xvbroadcast_v4i64, v4i64, LASX256DOpnd>; -+ -+def XVREPLVE0_Q : LASX_2R<0b0111011100000111111100>, -+ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.q", int_loongarch_lasx_xvreplve0_q, v32i8, LASX256BOpnd>; -+ -+ -+def XVSLLWIL_H_B : LASX_I3_U<0b0111011100001000001>, -+ LASX_2R_U3_DESC_BASE<"xvsllwil.h.b", int_loongarch_lasx_xvsllwil_h_b, LASX256HOpnd, LASX256BOpnd>; -+ -+def XVSLLWIL_W_H : LASX_I4_U<0b011101110000100001>, -+ LASX_2R_U4_DESC_BASE<"xvsllwil.w.h", int_loongarch_lasx_xvsllwil_w_h, LASX256WOpnd, LASX256HOpnd>; -+ -+def XVSLLWIL_D_W : LASX_I5_U<0b01110111000010001>, -+ LASX_2R_U5_DESC_BASE<"xvsllwil.d.w", int_loongarch_lasx_xvsllwil_d_w, LASX256DOpnd, LASX256WOpnd> ; -+ -+ -+def XVEXTL_Q_D : LASX_2R<0b0111011100001001000000>, -+ LASX_2R_DESC_BASE<"xvextl.q.d", int_loongarch_lasx_xvextl_q_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSLLWIL_HU_BU : LASX_I3_U<0b0111011100001100001>, -+ LASX_2R_U3_DESC_BASE<"xvsllwil.hu.bu", int_loongarch_lasx_xvsllwil_hu_bu, LASX256HOpnd, LASX256BOpnd>; -+ -+def XVSLLWIL_WU_HU : LASX_I4_U<0b011101110000110001>, -+ LASX_2R_U4_DESC_BASE<"xvsllwil.wu.hu", int_loongarch_lasx_xvsllwil_wu_hu, LASX256WOpnd, LASX256HOpnd>; -+ -+def XVSLLWIL_DU_WU : LASX_I5_U<0b01110111000011001>, -+ LASX_2R_U5_DESC_BASE<"xvsllwil.du.wu", int_loongarch_lasx_xvsllwil_du_wu, LASX256DOpnd, LASX256WOpnd> ; -+ -+ -+def XVEXTL_QU_DU : LASX_2R<0b0111011100001101000000>, -+ LASX_2R_DESC_BASE<"xvextl.qu.du", int_loongarch_lasx_xvextl_qu_du, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVBITCLRI_B : LASX_I3_U<0b0111011100010000001>, -+ LASX_2R_U3_DESC_BASE<"xvbitclri.b", int_loongarch_lasx_xvbitclri_b, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVBITCLRI_H : LASX_I4_U<0b011101110001000001>, -+ LASX_2R_U4_DESC_BASE<"xvbitclri.h", int_loongarch_lasx_xvbitclri_h, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVBITCLRI_W : LASX_I5_U<0b01110111000100001>, -+ LASX_2R_U5_DESC_BASE<"xvbitclri.w", int_loongarch_lasx_xvbitclri_w, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVBITCLRI_D : LASX_I6_U<0b0111011100010001>, -+ LASX_2R_U6_DESC_BASE<"xvbitclri.d", int_loongarch_lasx_xvbitclri_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVBITSETI_B : LASX_I3_U<0b0111011100010100001>, -+ LASX_2R_U3_DESC_BASE<"xvbitseti.b", int_loongarch_lasx_xvbitseti_b, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVBITSETI_H : LASX_I4_U<0b011101110001010001>, -+ LASX_2R_U4_DESC_BASE<"xvbitseti.h", int_loongarch_lasx_xvbitseti_h, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVBITSETI_W : LASX_I5_U<0b01110111000101001>, -+ LASX_2R_U5_DESC_BASE<"xvbitseti.w", int_loongarch_lasx_xvbitseti_w, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVBITSETI_D : LASX_I6_U<0b0111011100010101>, -+ LASX_2R_U6_DESC_BASE<"xvbitseti.d", int_loongarch_lasx_xvbitseti_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVBITREVI_B : LASX_I3_U<0b0111011100011000001>, -+ LASX_2R_U3_DESC_BASE<"xvbitrevi.b", int_loongarch_lasx_xvbitrevi_b, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVBITREVI_H : LASX_I4_U<0b011101110001100001>, -+ LASX_2R_U4_DESC_BASE<"xvbitrevi.h", int_loongarch_lasx_xvbitrevi_h, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVBITREVI_W : LASX_I5_U<0b01110111000110001>, -+ LASX_2R_U5_DESC_BASE<"xvbitrevi.w", int_loongarch_lasx_xvbitrevi_w, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVBITREVI_D : LASX_I6_U<0b0111011100011001>, -+ LASX_2R_U6_DESC_BASE<"xvbitrevi.d", int_loongarch_lasx_xvbitrevi_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSAT_B : LASX_I3_U<0b0111011100100100001>, -+ LASX_BIT_3_DESC_BASE<"xvsat.b", int_loongarch_lasx_xvsat_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSAT_H : LASX_I4_U<0b011101110010010001>, -+ LASX_BIT_4_DESC_BASE<"xvsat.h", int_loongarch_lasx_xvsat_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSAT_W : LASX_I5_U<0b01110111001001001>, -+ LASX_BIT_5_DESC_BASE<"xvsat.w", int_loongarch_lasx_xvsat_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSAT_D : LASX_I6_U<0b0111011100100101>, -+ LASX_BIT_6_DESC_BASE<"xvsat.d", int_loongarch_lasx_xvsat_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSAT_BU : LASX_I3_U<0b0111011100101000001>, -+ LASX_BIT_3_DESC_BASE<"xvsat.bu", int_loongarch_lasx_xvsat_bu, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSAT_HU : LASX_I4_U<0b011101110010100001>, -+ LASX_BIT_4_DESC_BASE<"xvsat.hu", int_loongarch_lasx_xvsat_hu, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSAT_WU : LASX_I5_U<0b01110111001010001>, -+ LASX_BIT_5_DESC_BASE<"xvsat.wu", int_loongarch_lasx_xvsat_wu, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSAT_DU : LASX_I6_U<0b0111011100101001>, -+ LASX_BIT_6_DESC_BASE<"xvsat.du", int_loongarch_lasx_xvsat_du, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSLLI_B : LASX_I3_U<0b0111011100101100001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvslli.b", int_loongarch_lasx_xvslli_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSLLI_H : LASX_I4_U<0b011101110010110001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvslli.h", int_loongarch_lasx_xvslli_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSLLI_W : LASX_I5_U<0b01110111001011001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvslli.w", int_loongarch_lasx_xvslli_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSLLI_D : LASX_I6_U<0b0111011100101101>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvslli.d", int_loongarch_lasx_xvslli_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSRLI_B : LASX_I3_U<0b0111011100110000001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.b", int_loongarch_lasx_xvsrli_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSRLI_H : LASX_I4_U<0b011101110011000001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.h", int_loongarch_lasx_xvsrli_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSRLI_W : LASX_I5_U<0b01110111001100001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.w", int_loongarch_lasx_xvsrli_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSRLI_D : LASX_I6_U<0b0111011100110001>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.d", int_loongarch_lasx_xvsrli_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSRAI_B : LASX_I3_U<0b0111011100110100001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.b", int_loongarch_lasx_xvsrai_b, uimm3, immZExt3, LASX256BOpnd>; -+ -+def XVSRAI_H : LASX_I4_U<0b011101110011010001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.h", int_loongarch_lasx_xvsrai_h, uimm4, immZExt4, LASX256HOpnd>; -+ -+def XVSRAI_W : LASX_I5_U<0b01110111001101001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.w", int_loongarch_lasx_xvsrai_w, uimm5, immZExt5, LASX256WOpnd>; -+ -+def XVSRAI_D : LASX_I6_U<0b0111011100110101>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.d", int_loongarch_lasx_xvsrai_d, uimm6, immZExt6, LASX256DOpnd>; -+ -+ -+def XVSRLNI_B_H : LASX_I4_U<0b011101110100000001>, -+ LASX_U4_DESC_BASE<"xvsrlni.b.h", int_loongarch_lasx_xvsrlni_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSRLNI_H_W : LASX_I5_U<0b01110111010000001>, -+ LASX_N4_U5_DESC_BASE<"xvsrlni.h.w", int_loongarch_lasx_xvsrlni_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSRLNI_W_D : LASX_I6_U<0b0111011101000001>, -+ LASX_U6_DESC_BASE<"xvsrlni.w.d", int_loongarch_lasx_xvsrlni_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSRLNI_D_Q : LASX_I7_U<0b011101110100001>, -+ LASX_D_DESC_BASE<"xvsrlni.d.q", int_loongarch_lasx_xvsrlni_d_q, LASX256DOpnd>; -+ -+ -+def XVSRLRNI_B_H : LASX_I4_U<0b011101110100010001>, -+ LASX_U4_DESC_BASE<"xvsrlrni.b.h", int_loongarch_lasx_xvsrlrni_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSRLRNI_H_W : LASX_I5_U<0b01110111010001001>, -+ LASX_N4_U5_DESC_BASE<"xvsrlrni.h.w", int_loongarch_lasx_xvsrlrni_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSRLRNI_W_D : LASX_I6_U<0b0111011101000101>, -+ LASX_U6_DESC_BASE<"xvsrlrni.w.d", int_loongarch_lasx_xvsrlrni_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSRLRNI_D_Q : LASX_I7_U<0b011101110100011>, -+ LASX_D_DESC_BASE<"xvsrlrni.d.q", int_loongarch_lasx_xvsrlrni_d_q, LASX256DOpnd>; -+ -+ -+def XVSSRLNI_B_H : LASX_I4_U<0b011101110100100001>, -+ LASX_U4_DESC_BASE<"xvssrlni.b.h", int_loongarch_lasx_xvssrlni_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRLNI_H_W : LASX_I5_U<0b01110111010010001>, -+ LASX_N4_U5_DESC_BASE<"xvssrlni.h.w", int_loongarch_lasx_xvssrlni_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRLNI_W_D : LASX_I6_U<0b0111011101001001>, -+ LASX_U6_DESC_BASE<"xvssrlni.w.d", int_loongarch_lasx_xvssrlni_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRLNI_D_Q : LASX_I7_U<0b011101110100101>, -+ LASX_D_DESC_BASE<"xvssrlni.d.q", int_loongarch_lasx_xvssrlni_d_q, LASX256DOpnd>; -+ -+ -+def XVSSRLNI_BU_H : LASX_I4_U<0b011101110100110001>, -+ LASX_U4_DESC_BASE<"xvssrlni.bu.h", int_loongarch_lasx_xvssrlni_bu_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRLNI_HU_W : LASX_I5_U<0b01110111010011001>, -+ LASX_N4_U5_DESC_BASE<"xvssrlni.hu.w", int_loongarch_lasx_xvssrlni_hu_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRLNI_WU_D : LASX_I6_U<0b0111011101001101>, -+ LASX_U6_DESC_BASE<"xvssrlni.wu.d", int_loongarch_lasx_xvssrlni_wu_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRLNI_DU_Q : LASX_I7_U<0b011101110100111>, -+ LASX_D_DESC_BASE<"xvssrlni.du.q", int_loongarch_lasx_xvssrlni_du_q, LASX256DOpnd>; -+ -+ -+def XVSSRLRNI_B_H : LASX_I4_U<0b011101110101000001>, -+ LASX_2R_3R_U4_DESC_BASE<"xvssrlrni.b.h", int_loongarch_lasx_xvssrlrni_b_h, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSSRLRNI_H_W : LASX_I5_U<0b01110111010100001>, -+ LASX_2R_3R_U5_DESC_BASE<"xvssrlrni.h.w", int_loongarch_lasx_xvssrlrni_h_w, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSSRLRNI_W_D : LASX_I6_U<0b0111011101010001>, -+ LASX_2R_3R_U6_DESC_BASE<"xvssrlrni.w.d", int_loongarch_lasx_xvssrlrni_w_d, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSSRLRNI_D_Q : LASX_I7_U<0b011101110101001>, -+ LASX_2R_3R_U7_DESC_BASE<"xvssrlrni.d.q", int_loongarch_lasx_xvssrlrni_d_q, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSSRLRNI_BU_H : LASX_I4_U<0b011101110101010001>, -+ LASX_U4_DESC_BASE<"xvssrlrni.bu.h", int_loongarch_lasx_xvssrlrni_bu_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRLRNI_HU_W : LASX_I5_U<0b01110111010101001>, -+ LASX_N4_U5_DESC_BASE<"xvssrlrni.hu.w", int_loongarch_lasx_xvssrlrni_hu_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRLRNI_WU_D : LASX_I6_U<0b0111011101010101>, -+ LASX_U6_DESC_BASE<"xvssrlrni.wu.d", int_loongarch_lasx_xvssrlrni_wu_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRLRNI_DU_Q : LASX_I7_U<0b011101110101011>, -+ LASX_D_DESC_BASE<"xvssrlrni.du.q", int_loongarch_lasx_xvssrlrni_du_q, LASX256DOpnd>; -+ -+ -+def XVSRANI_B_H : LASX_I4_U<0b011101110101100001>, -+ LASX_2R_3R_U4_DESC_BASE<"xvsrani.b.h", int_loongarch_lasx_xvsrani_b_h, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVSRANI_H_W : LASX_I5_U<0b01110111010110001>, -+ LASX_2R_3R_U5_DESC_BASE<"xvsrani.h.w", int_loongarch_lasx_xvsrani_h_w, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVSRANI_W_D : LASX_I6_U<0b0111011101011001>, -+ LASX_2R_3R_U6_DESC_BASE<"xvsrani.w.d", int_loongarch_lasx_xvsrani_w_d, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVSRANI_D_Q : LASX_I7_U<0b011101110101101>, -+ LASX_2R_3R_U7_DESC_BASE<"xvsrani.d.q", int_loongarch_lasx_xvsrani_d_q, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSRARNI_B_H : LASX_I4_U<0b011101110101110001>, -+ LASX_U4_DESC_BASE<"xvsrarni.b.h", int_loongarch_lasx_xvsrarni_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSRARNI_H_W : LASX_I5_U<0b01110111010111001>, -+ LASX_N4_U5_DESC_BASE<"xvsrarni.h.w", int_loongarch_lasx_xvsrarni_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSRARNI_W_D : LASX_I6_U<0b0111011101011101>, -+ LASX_U6_DESC_BASE<"xvsrarni.w.d", int_loongarch_lasx_xvsrarni_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSRARNI_D_Q : LASX_I7_U<0b011101110101111>, -+ LASX_D_DESC_BASE<"xvsrarni.d.q", int_loongarch_lasx_xvsrarni_d_q, LASX256DOpnd>; -+ -+ -+def XVSSRANI_B_H : LASX_I4_U<0b011101110110000001>, -+ LASX_U4_DESC_BASE<"xvssrani.b.h", int_loongarch_lasx_xvssrani_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRANI_H_W : LASX_I5_U<0b01110111011000001>, -+ LASX_N4_U5_DESC_BASE<"xvssrani.h.w", int_loongarch_lasx_xvssrani_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRANI_W_D : LASX_I6_U<0b0111011101100001>, -+ LASX_U6_DESC_BASE<"xvssrani.w.d", int_loongarch_lasx_xvssrani_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRANI_D_Q : LASX_I7_U<0b011101110110001>, -+ LASX_D_DESC_BASE<"xvssrani.d.q", int_loongarch_lasx_xvssrani_d_q, LASX256DOpnd>; -+ -+ -+def XVSSRANI_BU_H : LASX_I4_U<0b011101110110010001>, -+ LASX_U4_DESC_BASE<"xvssrani.bu.h", int_loongarch_lasx_xvssrani_bu_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRANI_HU_W : LASX_I5_U<0b01110111011001001>, -+ LASX_N4_U5_DESC_BASE<"xvssrani.hu.w", int_loongarch_lasx_xvssrani_hu_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRANI_WU_D : LASX_I6_U<0b0111011101100101>, -+ LASX_U6_DESC_BASE<"xvssrani.wu.d", int_loongarch_lasx_xvssrani_wu_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRANI_DU_Q : LASX_I7_U<0b011101110110011>, -+ LASX_D_DESC_BASE<"xvssrani.du.q", int_loongarch_lasx_xvssrani_du_q, LASX256DOpnd>; -+ -+ -+def XVSSRARNI_B_H : LASX_I4_U<0b011101110110100001>, -+ LASX_U4_DESC_BASE<"xvssrarni.b.h", int_loongarch_lasx_xvssrarni_b_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRARNI_H_W : LASX_I5_U<0b01110111011010001>, -+ LASX_N4_U5_DESC_BASE<"xvssrarni.h.w", int_loongarch_lasx_xvssrarni_h_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRARNI_W_D : LASX_I6_U<0b0111011101101001>, -+ LASX_U6_DESC_BASE<"xvssrarni.w.d", int_loongarch_lasx_xvssrarni_w_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRARNI_D_Q : LASX_I7_U<0b011101110110101>, -+ LASX_D_DESC_BASE<"xvssrarni.d.q", int_loongarch_lasx_xvssrarni_d_q, LASX256DOpnd>; -+ -+ -+def XVSSRARNI_BU_H : LASX_I4_U<0b011101110110110001>, -+ LASX_U4_DESC_BASE<"xvssrarni.bu.h", int_loongarch_lasx_xvssrarni_bu_h, uimm4, immZExt4, LASX256BOpnd>; -+ -+def XVSSRARNI_HU_W : LASX_I5_U<0b01110111011011001>, -+ LASX_N4_U5_DESC_BASE<"xvssrarni.hu.w", int_loongarch_lasx_xvssrarni_hu_w, uimm5, immZExt5, LASX256HOpnd>; -+ -+def XVSSRARNI_WU_D : LASX_I6_U<0b0111011101101101>, -+ LASX_U6_DESC_BASE<"xvssrarni.wu.d", int_loongarch_lasx_xvssrarni_wu_d, uimm6, immZExt6, LASX256WOpnd>; -+ -+def XVSSRARNI_DU_Q : LASX_I7_U<0b011101110110111>, -+ LASX_D_DESC_BASE<"xvssrarni.du.q", int_loongarch_lasx_xvssrarni_du_q, LASX256DOpnd>; -+ -+ -+def XVEXTRINS_B : LASX_I8_U<0b01110111100011>, -+ LASX_2R_3R_U8_DESC_BASE<"xvextrins.b", int_loongarch_lasx_xvextrins_b, LASX256BOpnd, LASX256BOpnd>; -+ -+def XVEXTRINS_H : LASX_I8_U<0b01110111100010>, -+ LASX_2R_3R_U8_DESC_BASE<"xvextrins.h", int_loongarch_lasx_xvextrins_h, LASX256HOpnd, LASX256HOpnd>; -+ -+def XVEXTRINS_W : LASX_I8_U<0b01110111100001>, -+ LASX_2R_3R_U8_DESC_BASE<"xvextrins.w", int_loongarch_lasx_xvextrins_w, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVEXTRINS_D : LASX_I8_U<0b01110111100000>, -+ LASX_2R_3R_U8_DESC_BASE<"xvextrins.d", int_loongarch_lasx_xvextrins_d, LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVSHUF4I_B : LASX_I8_U<0b01110111100100>, -+ LASX_I8_SHF_DESC_BASE<"xvshuf4i.b", int_loongarch_lasx_xvshuf4i_b, LASX256BOpnd>; -+ -+def XVSHUF4I_H : LASX_I8_U<0b01110111100101>, -+ LASX_I8_SHF_DESC_BASE<"xvshuf4i.h", int_loongarch_lasx_xvshuf4i_h, LASX256HOpnd>; -+ -+def XVSHUF4I_W : LASX_I8_U<0b01110111100110>, -+ LASX_I8_SHF_DESC_BASE<"xvshuf4i.w", int_loongarch_lasx_xvshuf4i_w, LASX256WOpnd>; -+ -+def XVSHUF4I_D : LASX_I8_U<0b01110111100111>, -+ LASX_I8_O4_SHF_DESC_BASE<"xvshuf4i.d", int_loongarch_lasx_xvshuf4i_d, LASX256DOpnd>; -+ -+ -+def XVBITSELI_B : LASX_I8_U<0b01110111110001>, -+ LASX_2R_3R_U8_DESC_BASE<"xvbitseli.b", int_loongarch_lasx_xvbitseli_b, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+def XVANDI_B : LASX_I8_U<0b01110111110100>, -+ LASX_2R_U8_DESC_BASE<"xvandi.b", int_loongarch_lasx_xvandi_b, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+def XVORI_B : LASX_I8_U<0b01110111110101>, -+ LASX_2R_U8_DESC_BASE<"xvori.b", int_loongarch_lasx_xvori_b, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+def XVXORI_B : LASX_I8_U<0b01110111110110>, -+ LASX_2R_U8_DESC_BASE<"xvxori.b", int_loongarch_lasx_xvxori_b, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+def XVNORI_B : LASX_I8_U<0b01110111110111>, -+ LASX_2R_U8_DESC_BASE<"xvnori.b", int_loongarch_lasx_xvnori_b, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+def XVLDI : LASX_1R_I13<0b01110111111000>, -+ LASX_I13_DESC_BASE<"xvldi", int_loongarch_lasx_xvldi, i32, simm13Op, LASX256DOpnd>; -+ -+ -+def XVLDI_B : LASX_1R_I13_I10<0b01110111111000000>, -+ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_b, simm10, immZExt10, LASX256BOpnd>; -+ -+def XVLDI_H : LASX_1R_I13_I10<0b01110111111000001>, -+ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_h, simm10, immZExt10, LASX256HOpnd>; -+ -+def XVLDI_W : LASX_1R_I13_I10<0b01110111111000010>, -+ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_w, simm10, immZExt10, LASX256WOpnd>; -+ -+def XVLDI_D : LASX_1R_I13_I10<0b01110111111000011>, -+ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_d, simm10, immZExt10, LASX256DOpnd>; -+ -+ -+def XVPERMI_W : LASX_I8_U<0b01110111111001>, -+ LASX_2R_3R_U8_DESC_BASE<"xvpermi.w", int_loongarch_lasx_xvpermi_w, LASX256WOpnd, LASX256WOpnd>; -+ -+def XVPERMI_D : LASX_I8_U<0b01110111111010>, -+ LASX_2R_U8_DESC_BASE<"xvpermi.d", int_loongarch_lasx_xvpermi_d, LASX256DOpnd, LASX256DOpnd>; -+ -+def XVPERMI_Q : LASX_I8_U<0b01110111111011>, -+ LASX_2R_3R_U8_DESC_BASE<"xvpermi.q", int_loongarch_lasx_xvpermi_q, LASX256BOpnd, LASX256BOpnd>; -+ -+ -+//Pat -+ -+class LASXBitconvertPat preds = [HasLASX]> : -+ LASXPat<(DstVT (bitconvert SrcVT:$src)), -+ (COPY_TO_REGCLASS SrcVT:$src, DstRC), preds>; -+ -+// These are endian-independent because the element size doesnt change -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+def : LASXBitconvertPat; -+ -+class LASX_XINSERT_PSEUDO_BASE : -+ LASXPseudo<(outs ROXD:$xd), (ins ROXD:$xd_in, ImmOp:$n, ROFS:$fs), -+ [(set ROXD:$xd, (OpNode (Ty ROXD:$xd_in), ROFS:$fs, Imm:$n))]> { -+ bit usesCustomInserter = 1; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+class XINSERT_H_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; -+ -+class XINSERT_H64_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; -+ -+def XINSERT_H_PSEUDO : XINSERT_H_PSEUDO_DESC; -+def XINSERT_H64_PSEUDO : XINSERT_H64_PSEUDO_DESC; -+ -+class XINSERT_B_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; -+def XINSERT_B_PSEUDO : XINSERT_B_PSEUDO_DESC; -+ -+ -+class LASX_COPY_PSEUDO_BASE : -+ LASXPseudo<(outs RCD:$xd), (ins RCWS:$xj, ImmOp:$n), -+ [(set RCD:$xd, (OpNode (VecTy RCWS:$xj), Imm:$n))]> { -+ bit usesCustomInserter = 1; -+} -+ -+class XCOPY_FW_PSEUDO_DESC : LASX_COPY_PSEUDO_BASE; -+class XCOPY_FD_PSEUDO_DESC : LASX_COPY_PSEUDO_BASE; -+def XCOPY_FW_PSEUDO : XCOPY_FW_PSEUDO_DESC; -+def XCOPY_FD_PSEUDO : XCOPY_FD_PSEUDO_DESC; -+ -+ -+ -+class LASX_XINSERT_VIDX_PSEUDO_BASE : -+ LASXPseudo<(outs ROXD:$xd), (ins ROXD:$xd_in, ROIdx:$n, ROFS:$fs), -+ [(set ROXD:$xd, (OpNode (Ty ROXD:$xd_in), ROFS:$fs, ROIdx:$n))]> { -+ bit usesCustomInserter = 1; -+ string Constraints = "$xd = $xd_in"; -+} -+ -+ -+class XINSERT_FW_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; -+def XINSERT_FW_PSEUDO : XINSERT_FW_PSEUDO_DESC; -+ -+class XINSERT_FW_VIDX_PSEUDO_DESC : -+ LASX_XINSERT_VIDX_PSEUDO_BASE; -+class XINSERT_FW_VIDX64_PSEUDO_DESC : -+ LASX_XINSERT_VIDX_PSEUDO_BASE; -+ -+def XINSERT_FW_VIDX_PSEUDO : XINSERT_FW_VIDX_PSEUDO_DESC; -+def XINSERT_FW_VIDX64_PSEUDO : XINSERT_FW_VIDX64_PSEUDO_DESC; -+ -+class XINSERT_B_VIDX64_PSEUDO_DESC : -+ LASX_XINSERT_VIDX_PSEUDO_BASE; -+ -+def XINSERT_B_VIDX64_PSEUDO : XINSERT_B_VIDX64_PSEUDO_DESC; -+ -+ -+class XINSERT_B_VIDX_PSEUDO_DESC : -+ LASX_XINSERT_VIDX_PSEUDO_BASE; -+ -+def XINSERT_B_VIDX_PSEUDO : XINSERT_B_VIDX_PSEUDO_DESC; -+ -+ -+class XINSERTPostRA : -+ LoongArchPseudo<(outs RC:$xd), (ins RC:$xd_in, RD:$n, RE:$fs), []> { -+ let mayLoad = 1; -+ let mayStore = 1; -+} -+ -+def XINSERT_B_VIDX_PSEUDO_POSTRA : XINSERTPostRA; -+def XINSERT_B_VIDX64_PSEUDO_POSTRA : XINSERTPostRA; -+def XINSERT_FW_VIDX_PSEUDO_POSTRA : XINSERTPostRA; -+def XINSERT_FW_VIDX64_PSEUDO_POSTRA : XINSERTPostRA; -+ -+class XINSERT_FD_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; -+ -+def XINSERT_FD_PSEUDO : XINSERT_FD_PSEUDO_DESC; -+ -+class LASX_2R_FILL_PSEUDO_BASE : -+ LASXPseudo<(outs RCWD:$xd), (ins RCWS:$fs), -+ [(set RCWD:$xd, (OpNode RCWS:$fs))]> { -+ let usesCustomInserter = 1; -+} -+ -+class XFILL_FW_PSEUDO_DESC : LASX_2R_FILL_PSEUDO_BASE; -+class XFILL_FD_PSEUDO_DESC : LASX_2R_FILL_PSEUDO_BASE; -+def XFILL_FW_PSEUDO : XFILL_FW_PSEUDO_DESC; -+def XFILL_FD_PSEUDO : XFILL_FD_PSEUDO_DESC; -+ -+class LASX_CONCAT_VECTORS_PSEUDO_BASE : -+ LASXPseudo<(outs ROXD:$xd), (ins ROXJ:$xs, ROXK:$xt), -+ [(set ROXD:$xd, (Ty (concat_vectors (SubTy ROXJ:$xs), (SubTy ROXK:$xt))))]> { -+ bit usesCustomInserter = 1; -+} -+ -+class CONCAT_VECTORS_B_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+class CONCAT_VECTORS_H_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+class CONCAT_VECTORS_W_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+class CONCAT_VECTORS_D_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+ -+class CONCAT_VECTORS_FW_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+class CONCAT_VECTORS_FD_PSEUDO_DESC : -+ LASX_CONCAT_VECTORS_PSEUDO_BASE; -+ -+def CONCAT_VECTORS_B_PSEUDO : CONCAT_VECTORS_B_PSEUDO_DESC; -+def CONCAT_VECTORS_H_PSEUDO : CONCAT_VECTORS_H_PSEUDO_DESC; -+def CONCAT_VECTORS_W_PSEUDO : CONCAT_VECTORS_W_PSEUDO_DESC; -+def CONCAT_VECTORS_D_PSEUDO : CONCAT_VECTORS_D_PSEUDO_DESC; -+def CONCAT_VECTORS_FW_PSEUDO : CONCAT_VECTORS_FW_PSEUDO_DESC; -+def CONCAT_VECTORS_FD_PSEUDO : CONCAT_VECTORS_FD_PSEUDO_DESC; -+ -+ -+class LASX_COPY_GPR_PSEUDO_BASE : -+ LASXPseudo<(outs ROXD:$xd), (ins ROFS:$xj, ROIdx:$n), -+ [(set ROXD:$xd, (OpNode (VecTy ROFS:$xj), ROIdx:$n))]> { -+ bit usesCustomInserter = 1; -+} -+ -+class XCOPY_FW_GPR_PSEUDO_DESC : LASX_COPY_GPR_PSEUDO_BASE; -+def XCOPY_FW_GPR_PSEUDO : XCOPY_FW_GPR_PSEUDO_DESC; -+ -+ -+let isCodeGenOnly = 1 in { -+ -+def XVLD_H : LASX_I12_S<0b0010110010>, -+ LASX_LD<"xvld", load, v16i16, LASX256HOpnd, mem>; -+ -+def XVLD_W : LASX_I12_S<0b0010110010>, -+ LASX_LD<"xvld", load, v8i32, LASX256WOpnd, mem>; -+ -+def XVLD_D : LASX_I12_S<0b0010110010>, -+ LASX_LD<"xvld", load, v4i64, LASX256DOpnd, mem>; -+ -+ -+def XVST_H : LASX_I12_S<0b0010110011>, -+ LASX_ST<"xvst", store, v16i16, LASX256HOpnd, mem_simm12>; -+ -+def XVST_W : LASX_I12_S<0b0010110011>, -+ LASX_ST<"xvst", store, v8i32, LASX256WOpnd, mem_simm12>; -+ -+def XVST_D : LASX_I12_S<0b0010110011>, -+ LASX_ST<"xvst", store, v4i64, LASX256DOpnd, mem_simm12>; -+ -+ -+def XVREPLVE_W_N : LASX_3R_1GP<0b01110101001000110>, -+ LASX_3R_VREPLVE_DESC_BASE_N<"xvreplve.w", LASX256WOpnd>; -+ -+ -+def XVANDI_B_N : LASX_I8_U<0b01110111110100>, -+ LASX_BIT_U8_DESC_BASE<"xvandi.b", and, xvsplati8_uimm8, LASX256BOpnd>; -+ -+ -+def XVXORI_B_N : LASX_I8_U<0b01110111110110>, -+ LASX_BIT_U8_DESC_BASE<"xvxori.b", xor, xvsplati8_uimm8, LASX256BOpnd>; -+ -+ -+def XVSRAI_B_N : LASX_I3_U<0b0111011100110100001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvsrai.b", sra, xvsplati8_uimm3, LASX256BOpnd>; -+ -+def XVSRAI_H_N : LASX_I4_U<0b011101110011010001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvsrai.h", sra, xvsplati16_uimm4, LASX256HOpnd>; -+ -+def XVSRAI_W_N : LASX_I5_U<0b01110111001101001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvsrai.w", sra, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSRAI_D_N : LASX_I6_U<0b0111011100110101>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvsrai.d", sra, xvsplati64_uimm6, LASX256DOpnd>; -+ -+ -+def XVSLLI_B_N : LASX_I3_U<0b0111011100101100001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvslli.b", shl, xvsplati8_uimm3, LASX256BOpnd>; -+ -+def XVSLLI_H_N : LASX_I4_U<0b011101110010110001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvslli.h", shl, xvsplati16_uimm4, LASX256HOpnd>; -+ -+def XVSLLI_W_N : LASX_I5_U<0b01110111001011001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvslli.w", shl, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSLLI_D_N : LASX_I6_U<0b0111011100101101>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvslli.d", shl, xvsplati64_uimm6, LASX256DOpnd>; -+ -+ -+def XVSRLI_B_N : LASX_I3_U<0b0111011100110000001>, -+ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvsrli.b", srl, xvsplati8_uimm3, LASX256BOpnd>; -+ -+def XVSRLI_H_N : LASX_I4_U<0b011101110011000001>, -+ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvsrli.h", srl, xvsplati16_uimm4, LASX256HOpnd>; -+ -+def XVSRLI_W_N : LASX_I5_U<0b01110111001100001>, -+ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvsrli.w", srl, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSRLI_D_N : LASX_I6_U<0b0111011100110001>, -+ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvsrli.d", srl, xvsplati64_uimm6, LASX256DOpnd>; -+ -+ -+def XVMAXI_B_N : LASX_I5<0b01110110100100000>, -+ LASX_I5_DESC_BASE<"xvmaxi.b", smax, xvsplati8_simm5, LASX256BOpnd>; -+ -+def XVMAXI_H_N : LASX_I5<0b01110110100100001>, -+ LASX_I5_DESC_BASE<"xvmaxi.h", smax, xvsplati16_simm5, LASX256HOpnd>; -+ -+def XVMAXI_W_N : LASX_I5<0b01110110100100010>, -+ LASX_I5_DESC_BASE<"xvmaxi.w", smax, xvsplati32_simm5, LASX256WOpnd>; -+ -+def XVMAXI_D_N : LASX_I5<0b01110110100100011>, -+ LASX_I5_DESC_BASE<"xvmaxi.d", smax, xvsplati64_simm5, LASX256DOpnd>; -+ -+ -+def XVMINI_B_N : LASX_I5<0b01110110100100100>, -+ LASX_I5_DESC_BASE<"xvmini.b", smin, xvsplati8_simm5, LASX256BOpnd>; -+ -+def XVMINI_H_N : LASX_I5<0b01110110100100101>, -+ LASX_I5_DESC_BASE<"xvmini.h", smin, xvsplati16_simm5, LASX256HOpnd>; -+ -+def XVMINI_W_N : LASX_I5<0b01110110100100110>, -+ LASX_I5_DESC_BASE<"xvmini.w", smin, xvsplati32_simm5, LASX256WOpnd>; -+ -+def XVMINI_D_N : LASX_I5<0b01110110100100111>, -+ LASX_I5_DESC_BASE<"xvmini.d", smin, xvsplati64_simm5, LASX256DOpnd>; -+ -+ -+def XVMAXI_BU_N : LASX_I5_U<0b01110110100101000>, -+ LASX_I5_U_DESC_BASE<"xvmaxi.bu", umax, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVMAXI_HU_N : LASX_I5_U<0b01110110100101001>, -+ LASX_I5_U_DESC_BASE<"xvmaxi.hu", umax, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVMAXI_WU_N : LASX_I5_U<0b01110110100101010>, -+ LASX_I5_U_DESC_BASE<"xvmaxi.wu", umax, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVMAXI_DU_N : LASX_I5_U<0b01110110100101011>, -+ LASX_I5_U_DESC_BASE<"xvmaxi.du", umax, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVMINI_BU_N : LASX_I5_U<0b01110110100101100>, -+ LASX_I5_U_DESC_BASE<"xvmini.bu", umin, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVMINI_HU_N : LASX_I5_U<0b01110110100101101>, -+ LASX_I5_U_DESC_BASE<"xvmini.hu", umin, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVMINI_WU_N : LASX_I5_U<0b01110110100101110>, -+ LASX_I5_U_DESC_BASE<"xvmini.wu", umin, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVMINI_DU_N : LASX_I5_U<0b01110110100101111>, -+ LASX_I5_U_DESC_BASE<"xvmini.du", umin, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVSEQI_B_N : LASX_I5<0b01110110100000000>, -+ LASX_I5_SETCC_DESC_BASE<"xvseqi.b", SETEQ, v32i8, xvsplati8_simm5, LASX256BOpnd>; -+ -+def XVSEQI_H_N : LASX_I5<0b01110110100000001>, -+ LASX_I5_SETCC_DESC_BASE<"xvseqi.h", SETEQ, v16i16, xvsplati16_simm5, LASX256HOpnd>; -+ -+def XVSEQI_W_N : LASX_I5<0b01110110100000010>, -+ LASX_I5_SETCC_DESC_BASE<"xvseqi.w", SETEQ, v8i32, xvsplati32_simm5, LASX256WOpnd>; -+ -+def XVSEQI_D_N : LASX_I5<0b01110110100000011>, -+ LASX_I5_SETCC_DESC_BASE<"xvseqi.d", SETEQ, v4i64, xvsplati64_simm5, LASX256DOpnd>; -+ -+ -+def XVSLEI_B_N : LASX_I5<0b01110110100000100>, -+ LASX_I5_SETCC_DESC_BASE<"xvslei.b", SETLE, v32i8, xvsplati8_simm5, LASX256BOpnd>; -+ -+def XVSLEI_H_N : LASX_I5<0b01110110100000101>, -+ LASX_I5_SETCC_DESC_BASE<"xvslei.h", SETLE, v16i16, xvsplati16_simm5, LASX256HOpnd>; -+ -+def XVSLEI_W_N : LASX_I5<0b01110110100000110>, -+ LASX_I5_SETCC_DESC_BASE<"xvslei.w", SETLE, v8i32, xvsplati32_simm5, LASX256WOpnd>; -+ -+def XVSLEI_D_N : LASX_I5<0b01110110100000111>, -+ LASX_I5_SETCC_DESC_BASE<"xvslei.d", SETLE, v4i64, xvsplati64_simm5, LASX256DOpnd>; -+ -+ -+def XVSLEI_BU_N : LASX_I5_U<0b01110110100001000>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslei.bu", SETULE, v32i8, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVSLEI_HU_N : LASX_I5_U<0b01110110100001001>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslei.hu", SETULE, v16i16, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVSLEI_WU_N : LASX_I5_U<0b01110110100001010>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslei.wu", SETULE, v8i32, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSLEI_DU_N : LASX_I5_U<0b01110110100001011>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslei.du", SETULE, v4i64, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVSLTI_B_N : LASX_I5<0b01110110100001100>, -+ LASX_I5_SETCC_DESC_BASE<"xvslti.b", SETLT, v32i8, xvsplati8_simm5, LASX256BOpnd>; -+ -+def XVSLTI_H_N : LASX_I5<0b01110110100001101>, -+ LASX_I5_SETCC_DESC_BASE<"xvslti.h", SETLT, v16i16, xvsplati16_simm5, LASX256HOpnd>; -+ -+def XVSLTI_W_N : LASX_I5<0b01110110100001110>, -+ LASX_I5_SETCC_DESC_BASE<"xvslti.w", SETLT, v8i32, xvsplati32_simm5, LASX256WOpnd>; -+ -+def XVSLTI_D_N : LASX_I5<0b01110110100001111>, -+ LASX_I5_SETCC_DESC_BASE<"xvslti.d", SETLT, v4i64, xvsplati64_simm5, LASX256DOpnd>; -+ -+ -+def XVSLTI_BU_N : LASX_I5_U<0b01110110100010000>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslti.bu", SETULT, v32i8, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVSLTI_HU_N : LASX_I5_U<0b01110110100010001>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslti.hu", SETULT, v16i16, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVSLTI_WU_N : LASX_I5_U<0b01110110100010010>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslti.wu", SETULT, v8i32, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSLTI_DU_N : LASX_I5_U<0b01110110100010011>, -+ LASX_I5_U_SETCC_DESC_BASE<"xvslti.du", SETULT, v4i64, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVADDI_BU_N : LASX_I5_U<0b01110110100010100>, -+ LASX_I5_U_DESC_BASE<"xvaddi.bu", add, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVADDI_HU_N : LASX_I5_U<0b01110110100010101>, -+ LASX_I5_U_DESC_BASE<"xvaddi.hu", add, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVADDI_WU_N : LASX_I5_U<0b01110110100010110>, -+ LASX_I5_U_DESC_BASE<"xvaddi.wu", add, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVADDI_DU_N : LASX_I5_U<0b01110110100010111>, -+ LASX_I5_U_DESC_BASE<"xvaddi.du", add, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVSUBI_BU_N : LASX_I5_U<0b01110110100011000>, -+ LASX_I5_U_DESC_BASE<"xvsubi.bu", sub, xvsplati8_uimm5, LASX256BOpnd>; -+ -+def XVSUBI_HU_N : LASX_I5_U<0b01110110100011001>, -+ LASX_I5_U_DESC_BASE<"xvsubi.hu", sub, xvsplati16_uimm5, LASX256HOpnd>; -+ -+def XVSUBI_WU_N : LASX_I5_U<0b01110110100011010>, -+ LASX_I5_U_DESC_BASE<"xvsubi.wu", sub, xvsplati32_uimm5, LASX256WOpnd>; -+ -+def XVSUBI_DU_N : LASX_I5_U<0b01110110100011011>, -+ LASX_I5_U_DESC_BASE<"xvsubi.du", sub, xvsplati64_uimm5, LASX256DOpnd>; -+ -+ -+def XVPERMI_QH : LASX_I8_U<0b01110111111011>, -+ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256HOpnd, LASX256HOpnd>; -+ -+def XVPERMI_QW : LASX_I8_U<0b01110111111011>, -+ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256WOpnd, LASX256WOpnd>; -+ -+def XVPERMI_QD : LASX_I8_U<0b01110111111011>, -+ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256DOpnd, LASX256DOpnd>; -+ -+ -+def XVBITSELI_B_N : LASX_I8_U<0b01110111110001>, -+ LASX_2R_3R_U8_SELECT<"xvbitseli.b", vselect, LASX256BOpnd, LASX256BOpnd>; -+ -+} -+ -+ -+def : LASXPat<(v8f32 (load addrimm12:$addr)), (XVLD_W addrimm12:$addr)>; -+def : LASXPat<(v4f64 (load addrimm12:$addr)), (XVLD_D addrimm12:$addr)>; -+ -+def XVST_FW : LASXPat<(store (v8f32 LASX256W:$xj), addrimm12:$addr), -+ (XVST_W LASX256W:$xj, addrimm12:$addr)>; -+def XVST_FD : LASXPat<(store (v4f64 LASX256D:$xj), addrimm12:$addr), -+ (XVST_D LASX256D:$xj, addrimm12:$addr)>; -+ -+def XVNEG_FW : LASXPat<(fneg (v8f32 LASX256W:$xj)), -+ (XVBITREVI_W LASX256W:$xj, 31)>; -+def XVNEG_FD : LASXPat<(fneg (v4f64 LASX256D:$xj)), -+ (XVBITREVI_D LASX256D:$xj, 63)>; -+ -+ -+def : LASXPat<(v4i64 (LoongArchVABSD v4i64:$xj, v4i64:$xk, (i32 0))), -+ (v4i64 (XVABSD_D $xj, $xk))>; -+ -+def : LASXPat<(v8i32 (LoongArchVABSD v8i32:$xj, v8i32:$xk, (i32 0))), -+ (v8i32 (XVABSD_W $xj, $xk))>; -+ -+def : LASXPat<(v16i16 (LoongArchVABSD v16i16:$xj, v16i16:$xk, (i32 0))), -+ (v16i16 (XVABSD_H $xj, $xk))>; -+ -+def : LASXPat<(v32i8 (LoongArchVABSD v32i8:$xj, v32i8:$xk, (i32 0))), -+ (v32i8 (XVABSD_B $xj, $xk))>; -+ -+def : LASXPat<(v4i64 (LoongArchUVABSD v4i64:$xj, v4i64:$xk, (i32 0))), -+ (v4i64 (XVABSD_DU $xj, $xk))>; -+ -+def : LASXPat<(v8i32 (LoongArchUVABSD v8i32:$xj, v8i32:$xk, (i32 0))), -+ (v8i32 (XVABSD_WU $xj, $xk))>; -+ -+def : LASXPat<(v16i16 (LoongArchUVABSD v16i16:$xj, v16i16:$xk, (i32 0))), -+ (v16i16 (XVABSD_HU $xj, $xk))>; -+ -+def : LASXPat<(v32i8 (LoongArchUVABSD v32i8:$xj, v32i8:$xk, (i32 0))), -+ (v32i8 (XVABSD_BU $xj, $xk))>; -+ -+ -+def : LASXPat<(or v32i8:$vj, (shl vsplat_imm_eq_1, v32i8:$vk)), -+ (XVBITSET_B v32i8:$vj, v32i8:$vk)>; -+def : LASXPat<(or v16i16:$vj, (shl vsplat_imm_eq_1, v16i16:$vk)), -+ (XVBITSET_H v16i16:$vj, v16i16:$vk)>; -+def : LASXPat<(or v8i32:$vj, (shl vsplat_imm_eq_1, v8i32:$vk)), -+ (XVBITSET_W v8i32:$vj, v8i32:$vk)>; -+def : LASXPat<(or v4i64:$vj, (shl vsplat_imm_eq_1, v4i64:$vk)), -+ (XVBITSET_D v4i64:$vj, v4i64:$vk)>; -+ -+def : LASXPat<(xor v32i8:$vj, (shl xvsplat_imm_eq_1, v32i8:$vk)), -+ (XVBITREV_B v32i8:$vj, v32i8:$vk)>; -+def : LASXPat<(xor v16i16:$vj, (shl xvsplat_imm_eq_1, v16i16:$vk)), -+ (XVBITREV_H v16i16:$vj, v16i16:$vk)>; -+def : LASXPat<(xor v8i32:$vj, (shl xvsplat_imm_eq_1, v8i32:$vk)), -+ (XVBITREV_W v8i32:$vj, v8i32:$vk)>; -+def : LASXPat<(xor v4i64:$vj, (shl (v4i64 xvsplati64_imm_eq_1), v4i64:$vk)), -+ (XVBITREV_D v4i64:$vj, v4i64:$vk)>; -+ -+def : LASXPat<(and v32i8:$vj, (xor (shl vsplat_imm_eq_1, v32i8:$vk), immAllOnesV)), -+ (XVBITCLR_B v32i8:$vj, v32i8:$vk)>; -+def : LASXPat<(and v16i16:$vj, (xor (shl vsplat_imm_eq_1, v16i16:$vk), immAllOnesV)), -+ (XVBITCLR_H v16i16:$vj, v16i16:$vk)>; -+def : LASXPat<(and v8i32:$vj, (xor (shl vsplat_imm_eq_1, v8i32:$vk), immAllOnesV)), -+ (XVBITCLR_W v8i32:$vj, v8i32:$vk)>; -+def : LASXPat<(and v4i64:$vj, (xor (shl (v4i64 vsplati64_imm_eq_1), v4i64:$vk), (bitconvert (v8i32 immAllOnesV)))), -+ (XVBITCLR_D v4i64:$vj, v4i64:$vk)>; -+ -+def xvsplati64_imm_eq_63 : PatLeaf<(bitconvert (v8i32 (build_vector))), [{ -+ APInt Imm; -+ SDNode *BV = N->getOperand(0).getNode(); -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63; -+}]>; -+ -+def xvsplati8imm7 : PatFrag<(ops node:$wt), -+ (and node:$wt, (xvsplati8 immi32Cst7))>; -+def xvsplati16imm15 : PatFrag<(ops node:$wt), -+ (and node:$wt, (xvsplati16 immi32Cst15))>; -+def xvsplati32imm31 : PatFrag<(ops node:$wt), -+ (and node:$wt, (xvsplati32 immi32Cst31))>; -+def xvsplati64imm63 : PatFrag<(ops node:$wt), -+ (and node:$wt, xvsplati64_imm_eq_63)>; -+ -+ -+class LASXShiftPat : -+ LASXPat<(VT (Node VT:$vs, (VT (and VT:$vt, Vec)))), -+ (VT (Insn VT:$vs, VT:$vt))>; -+ -+class LASXBitPat : -+ LASXPat<(VT (Node VT:$vs, (shl vsplat_imm_eq_1, (Frag VT:$vt)))), -+ (VT (Insn VT:$vs, VT:$vt))>; -+ -+multiclass LASXShiftPats { -+ def : LASXShiftPat(Insn#_B), -+ (xvsplati8 immi32Cst7)>; -+ def : LASXShiftPat(Insn#_H), -+ (xvsplati16 immi32Cst15)>; -+ def : LASXShiftPat(Insn#_W), -+ (xvsplati32 immi32Cst31)>; -+ def : LASXPat<(v4i64 (Node v4i64:$vs, (v4i64 (and v4i64:$vt, -+ xvsplati64_imm_eq_63)))), -+ (v4i64 (!cast(Insn#_D) v4i64:$vs, v4i64:$vt))>; -+} -+ -+multiclass LASXBitPats { -+ def : LASXBitPat(Insn#_B), xvsplati8imm7>; -+ def : LASXBitPat(Insn#_H), xvsplati16imm15>; -+ def : LASXBitPat(Insn#_W), xvsplati32imm31>; -+ def : LASXPat<(Node v4i64:$vs, (shl (v4i64 xvsplati64_imm_eq_1), -+ (xvsplati64imm63 v4i64:$vt))), -+ (v4i64 (!cast(Insn#_D) v4i64:$vs, v4i64:$vt))>; -+} -+ -+defm : LASXShiftPats; -+defm : LASXShiftPats; -+defm : LASXShiftPats; -+defm : LASXBitPats; -+defm : LASXBitPats; -+ -+def : LASXPat<(and v32i8:$vs, (xor (shl xvsplat_imm_eq_1, -+ (xvsplati8imm7 v32i8:$vt)), -+ immAllOnesV)), -+ (v32i8 (XVBITCLR_B v32i8:$vs, v32i8:$vt))>; -+def : LASXPat<(and v16i16:$vs, (xor (shl xvsplat_imm_eq_1, -+ (xvsplati16imm15 v16i16:$vt)), -+ immAllOnesV)), -+ (v16i16 (XVBITCLR_H v16i16:$vs, v16i16:$vt))>; -+def : LASXPat<(and v8i32:$vs, (xor (shl xvsplat_imm_eq_1, -+ (xvsplati32imm31 v8i32:$vt)), -+ immAllOnesV)), -+ (v8i32 (XVBITCLR_W v8i32:$vs, v8i32:$vt))>; -+def : LASXPat<(and v4i64:$vs, (xor (shl (v4i64 xvsplati64_imm_eq_1), -+ (xvsplati64imm63 v4i64:$vt)), -+ (bitconvert (v8i32 immAllOnesV)))), -+ (v4i64 (XVBITCLR_D v4i64:$vs, v4i64:$vt))>; -+ -+ -+def : LASXPat<(fdiv (v8f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), -+ (f32 fpimm1),(f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), v8f32:$v), -+ (XVFRECIP_S v8f32:$v)>; -+ -+def : LASXPat<(fdiv (v4f64 (build_vector (f64 fpimm1), (f64 fpimm1), (f64 fpimm1), (f64 fpimm1))), v4f64:$v), -+ (XVFRECIP_D v4f64:$v)>; -+ -+def : LASXPat<(fdiv (v8f32 fpimm1), v8f32:$v), -+ (XVFRECIP_S v8f32:$v)>; -+ -+def : LASXPat<(fdiv (v4f64 fpimm1), v4f64:$v), -+ (XVFRECIP_D v4f64:$v)>; -+ -+ -+def : LASXPat<(fdiv (v8f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), -+ (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), (fsqrt v8f32:$v)), -+ (XVFRSQRT_S v8f32:$v)>; -+ -+def : LASXPat<(fdiv (v4f64 (build_vector (f64 fpimm1), (f64 fpimm1), (f64 fpimm1), (f64 fpimm1))), (fsqrt v4f64:$v)), -+ (XVFRSQRT_D v4f64:$v)>; -+ -+def : LASXPat<(fdiv (v8f32 fpimm1), (fsqrt v8f32:$v)), -+ (XVFRSQRT_S v8f32:$v)>; -+ -+def : LASXPat<(fdiv (v4f64 fpimm1), (fsqrt v4f64:$v)), -+ (XVFRSQRT_D v4f64:$v)>; -+ -+ -+def : LASXPat <(extract_subvector v4f64:$vec, (i32 0)), -+ (v2f64 (EXTRACT_SUBREG v4f64:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v8f32:$vec, (i32 0)), -+ (v4f32 (EXTRACT_SUBREG v8f32:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v4i64:$vec, (i32 0)), -+ (v2i64 (EXTRACT_SUBREG v4i64:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v8i32:$vec, (i32 0)), -+ (v4i32 (EXTRACT_SUBREG v8i32:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v16i16:$vec, (i32 0)), -+ (v8i16 (EXTRACT_SUBREG v16i16:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v32i8:$vec, (i32 0)), -+ (v16i8 (EXTRACT_SUBREG v32i8:$vec, sub_128))>; -+ -+ -+ -+def : LASXPat <(extract_subvector v4f64:$vec, (i64 0)), -+ (v2f64 (EXTRACT_SUBREG v4f64:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v8f32:$vec, (i64 0)), -+ (v4f32 (EXTRACT_SUBREG v8f32:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v4i64:$vec, (i64 0)), -+ (v2i64 (EXTRACT_SUBREG v4i64:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v8i32:$vec, (i64 0)), -+ (v4i32 (EXTRACT_SUBREG v8i32:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v16i16:$vec, (i64 0)), -+ (v8i16 (EXTRACT_SUBREG v16i16:$vec, sub_128))>; -+ -+def : LASXPat <(extract_subvector v32i8:$vec, (i64 0)), -+ (v16i8 (EXTRACT_SUBREG v32i8:$vec, sub_128))>; -+ -+ -+def : LASXPat <(extract_subvector v4i64:$vec, (i32 2)), -+ (v2i64 (EXTRACT_SUBREG (v4i64 (XVPERMI_QD v4i64:$vec, v4i64:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v8i32:$vec, (i32 4)), -+ (v4i32 (EXTRACT_SUBREG (v8i32 (XVPERMI_QW v8i32:$vec, v8i32:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v16i16:$vec, (i32 8)), -+ (v8i16 (EXTRACT_SUBREG (v16i16 (XVPERMI_QH v16i16:$vec, v16i16:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v32i8:$vec, (i32 16)), -+ (v16i8 (EXTRACT_SUBREG (v32i8 (XVPERMI_Q v32i8:$vec, v32i8:$vec, (i32 1))), sub_128))>; -+ -+ -+def : LASXPat <(extract_subvector v4i64:$vec, (i64 2)), -+ (v2i64 (EXTRACT_SUBREG (v4i64 (XVPERMI_QD v4i64:$vec, v4i64:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v8i32:$vec, (i64 4)), -+ (v4i32 (EXTRACT_SUBREG (v8i32 (XVPERMI_QW v8i32:$vec, v8i32:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v16i16:$vec, (i64 8)), -+ (v8i16 (EXTRACT_SUBREG (v16i16 (XVPERMI_QH v16i16:$vec, v16i16:$vec, (i32 1))), sub_128))>; -+ -+def : LASXPat <(extract_subvector v32i8:$vec, (i64 16)), -+ (v16i8 (EXTRACT_SUBREG (v32i8 (XVPERMI_Q v32i8:$vec, v32i8:$vec, (i32 1))), sub_128))>; -+ -+ -+def : LASXPat<(abs v4i64:$v), -+ (XVMAX_D v4i64:$v, (XVNEG_D v4i64:$v))>; -+ -+def : LASXPat<(abs v8i32:$v), -+ (XVMAX_W v8i32:$v, (XVNEG_W v8i32:$v))>; -+ -+def : LASXPat<(abs v16i16:$v), -+ (XVMAX_H v16i16:$v, (XVNEG_H v16i16:$v))>; -+ -+def : LASXPat<(abs v32i8:$v), -+ (XVMAX_B v32i8:$v, (XVNEG_B v32i8:$v))>; -+ -+ -+def : LASXPat<(sub (v32i8 immAllZerosV), v32i8:$v), -+ (XVNEG_B v32i8:$v)>; -+ -+def : LASXPat<(sub (v16i16 immAllZerosV), v16i16:$v), -+ (XVNEG_H v16i16:$v)>; -+ -+def : LASXPat<(sub (v8i32 immAllZerosV), v8i32:$v), -+ (XVNEG_W v8i32:$v)>; -+ -+def : LASXPat<(sub (v4i64 immAllZerosV), v4i64:$v), -+ (XVNEG_D v4i64:$v)>; -+ -+ -+ -+def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i32 0)), -+ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i32 0)), -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i32 0)), -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i32 0)), -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; -+ -+ -+def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i64 0)), -+ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i64 0)), -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i64 0)), -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i64 0)), -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; -+ -+ -+def : LASXPat<(insert_subvector -+ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i32 0)), -+ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i32 0)), -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i32 0)), -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i32 0)), -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i64 0)), -+ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i64 0)), -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i64 0)), -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; -+ -+def : LASXPat<(insert_subvector -+ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i64 0)), -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; -+ -+ -+def : LASXPat<(insert_subvector -+ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i32 2)), -+ (XVPERMI_QD (v4i64 (XVREPLGR2VR_D ZERO_64)), -+ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), -+ LSX128D:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector (v8i32 immAllZerosV), -+ (v4i32 LSX128W:$src), (i32 4)), -+ (XVPERMI_QW (v8i32 (XVREPLGR2VR_W ZERO)), -+ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), -+ LSX128W:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector -+ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i32 8)), -+ (XVPERMI_QH (v16i16 (XVREPLGR2VR_H ZERO)), -+ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), -+ LSX128H:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector -+ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i32 16)), -+ (XVPERMI_Q (v32i8 (XVREPLGR2VR_B ZERO)), -+ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), -+ LSX128B:$src, sub_128)), (i32 32))>; -+ -+ -+def : LASXPat<(insert_subvector -+ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i64 2)), -+ (XVPERMI_QD (v4i64 (XVREPLGR2VR_D ZERO_64)), -+ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), -+ LSX128D:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector -+ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i64 4)), -+ (XVPERMI_QW (v8i32 (XVREPLGR2VR_W ZERO)), -+ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), -+ LSX128W:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector -+ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i64 8)), -+ (XVPERMI_QH (v16i16 (XVREPLGR2VR_H ZERO)), -+ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), -+ LSX128H:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector -+ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i64 16)), -+ (XVPERMI_Q (v32i8 (XVREPLGR2VR_B ZERO)), -+ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), -+ LSX128B:$src, sub_128)), (i32 32))>; -+ -+ -+def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i32 2)), -+ (XVPERMI_QD (v4i64 (IMPLICIT_DEF)), -+ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), -+ LSX128D:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i32 4)), -+ (XVPERMI_QW (v8i32 (IMPLICIT_DEF)), -+ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), -+ LSX128W:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i32 8)), -+ (XVPERMI_QH (v16i16 (IMPLICIT_DEF)), -+ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), -+ LSX128H:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i32 16)), -+ (XVPERMI_Q (v32i8 (IMPLICIT_DEF)), -+ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), -+ LSX128B:$src, sub_128)), (i32 32))>; -+ -+ -+def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i64 2)), -+ (XVPERMI_QD (v4i64 (IMPLICIT_DEF)), -+ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), -+ LSX128D:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i64 4)), -+ (XVPERMI_QW (v8i32 (IMPLICIT_DEF)), -+ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), -+ LSX128W:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i64 8)), -+ (XVPERMI_QH (v16i16 (IMPLICIT_DEF)), -+ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), -+ LSX128H:$src, sub_128)), (i32 32))>; -+ -+def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i64 16)), -+ (XVPERMI_Q (v32i8 (IMPLICIT_DEF)), -+ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), -+ LSX128B:$src, sub_128)), (i32 32))>; -+ -+ -+def : LASXPat<(sra -+ (v32i8 (add -+ (v32i8 (add LASX256B:$a, LASX256B:$b)), -+ (v32i8 (srl -+ (v32i8 (add LASX256B:$a, LASX256B:$b)), -+ (v32i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (XVAVG_B (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; -+ -+def : LASXPat<(sra -+ (v16i16 (add -+ (v16i16 (add LASX256H:$a, LASX256H:$b)), -+ (v16i16 (srl -+ (v16i16 (add LASX256H:$a, LASX256H:$b)), -+ (v16i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (XVAVG_H (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; -+ -+def : LASXPat<(sra -+ (v8i32 (add -+ (v8i32 (add LASX256W:$a, LASX256W:$b)), -+ (v8i32 (srl -+ (v8i32 (add LASX256W:$a, LASX256W:$b)), -+ (v8i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31), -+ (i32 31),(i32 31),(i32 31),(i32 31)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (XVAVG_W (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; -+ -+def : LASXPat<(sra -+ (v4i64 (add -+ (v4i64 (add LASX256D:$a, LASX256D:$b)), -+ (v4i64 (srl -+ (v4i64 (add LASX256D:$a, LASX256D:$b)), -+ (v4i64 (build_vector (i64 63),(i64 63),(i64 63),(i64 63))) -+ ) -+ ) -+ ) -+ ), -+ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))), -+ (XVAVG_D (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; -+ -+ -+ -+def : LASXPat<(srl -+ (v32i8 (add LASX256B:$a, LASX256B:$b)), -+ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVG_BU (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; -+ -+def : LASXPat<(srl -+ (v16i16 (add LASX256H:$a, LASX256H:$b)), -+ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVG_HU (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; -+ -+def : LASXPat<(srl -+ (v8i32 (add LASX256W:$a, LASX256W:$b)), -+ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVG_WU (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; -+ -+def : LASXPat<(srl -+ (v4i64 (add LASX256D:$a, LASX256D:$b)), -+ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)) -+ ) -+ ), -+ (XVAVG_DU (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; -+ -+ -+ -+def : LASXPat<(sra -+ (v32i8 (add -+ (v32i8 (add (v32i8 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v32i8 (add LASX256B:$a, LASX256B:$b)) -+ )), -+ (v32i8 (srl -+ (v32i8 ( add (v32i8( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v32i8 (add LASX256B:$a, LASX256B:$b)) -+ )), -+ (v32i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (XVAVGR_B (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; -+ -+ -+def : LASXPat<(sra -+ (v16i16 (add -+ (v16i16 (add (v16i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i16 (add LASX256H:$a, LASX256H:$b)) -+ )), -+ (v16i16 (srl -+ (v16i16 (add (v16i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i16 (add LASX256H:$a, LASX256H:$b)) -+ )), -+ (v16i16 (build_vector -+ (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (XVAVGR_H (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; -+ -+ -+def : LASXPat<(sra -+ (v8i32 (add -+ (v8i32 (add (v8i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i32 (add LASX256W:$a, LASX256W:$b)) -+ )), -+ (v8i32 (srl -+ (v8i32 (add (v8i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i32 (add LASX256W:$a, LASX256W:$b)) -+ )), -+ (v8i32 (build_vector -+ (i32 31),(i32 31),(i32 31),(i32 31), -+ (i32 31),(i32 31),(i32 31),(i32 31) -+ ) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)))), -+ (XVAVGR_W (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; -+ -+def : LASXPat<(sra -+ (v4i64 (add -+ (v4i64 (add (v4i64 ( -+ build_vector (i64 1),(i64 1),(i64 1),(i64 1) -+ )), -+ (v4i64 (add LASX256D:$a, LASX256D:$b)) -+ )), -+ (v4i64 (srl -+ (v4i64 (add (v4i64 ( -+ build_vector (i64 1),(i64 1),(i64 1),(i64 1) -+ )), -+ (v4i64 (add LASX256D:$a, LASX256D:$b)) -+ )), -+ (v4i64 (build_vector -+ (i64 63),(i64 63),(i64 63),(i64 63))) -+ ) -+ ) -+ ) -+ ), -+ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))), -+ (XVAVGR_D (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; -+ -+ -+ -+def : LASXPat<(srl -+ (v32i8 (add (v32i8 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v32i8 (add LASX256B:$a, LASX256B:$b)) -+ )), -+ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVGR_BU (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; -+ -+def : LASXPat<(srl -+ (v16i16 (add (v16i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i16 (add LASX256H:$a, LASX256H:$b)) -+ )), -+ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVGR_HU (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; -+ -+def : LASXPat<(srl -+ (v8i32 (add (v8i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i32 (add LASX256W:$a, LASX256W:$b)) -+ )), -+ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (XVAVGR_WU (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; -+ -+def : LASXPat<(srl -+ (v4i64 (add (v4i64 ( -+ build_vector (i64 1),(i64 1),(i64 1),(i64 1) -+ )), -+ (v4i64 (add LASX256D:$a, LASX256D:$b)) -+ )), -+ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)) -+ ) -+ ), -+ (XVAVGR_DU (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; -+ -+ -+def : LASXPat<(mulhs LASX256D:$a, LASX256D:$b), -+ (XVMUH_D LASX256D:$a, LASX256D:$b)>; -+ -+def : LASXPat<(mulhs LASX256W:$a, LASX256W:$b), -+ (XVMUH_W LASX256W:$a, LASX256W:$b)>; -+ -+def : LASXPat<(mulhs LASX256H:$a, LASX256H:$b), -+ (XVMUH_H LASX256H:$a, LASX256H:$b)>; -+ -+def : LASXPat<(mulhs LASX256B:$a, LASX256B:$b), -+ (XVMUH_B LASX256B:$a, LASX256B:$b)>; -+ -+ -+def : LASXPat<(mulhu LASX256D:$a, LASX256D:$b), -+ (XVMUH_DU LASX256D:$a, LASX256D:$b)>; -+ -+def : LASXPat<(mulhu LASX256W:$a, LASX256W:$b), -+ (XVMUH_WU LASX256W:$a, LASX256W:$b)>; -+ -+def : LASXPat<(mulhu LASX256H:$a, LASX256H:$b), -+ (XVMUH_HU LASX256H:$a, LASX256H:$b)>; -+ -+def : LASXPat<(mulhu LASX256B:$a, LASX256B:$b), -+ (XVMUH_BU LASX256B:$a, LASX256B:$b)>; -+ -+ -+def : LASXPat<(LoongArchINSVE (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3), -+ (XVINSVE0_W LASX256W:$a, LASX256W:$b, uimm3:$ui3)>; -+ -+def : LASXPat<(LoongArchINSVE (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2), -+ (XVINSVE0_D LASX256D:$a, LASX256D:$b, uimm2:$ui2)>; -+ -+ -+def : LASXPat<(LoongArchXVPICKVE (v8i32 (bitconvert (v32i8 (build_vector -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0) -+ )))), (v8i32 LASX256W:$b), uimm3:$ui3), -+ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>; -+ -+def : LASXPat<(LoongArchXVPICKVE (v4i64 (bitconvert (v32i8 (build_vector -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0) -+ )))), (v4i64 LASX256D:$b), uimm2:$ui2), -+ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>; -+ -+ -+def : LASXPat<(LoongArchXVPICKVE (v8i32 (build_vector -+ (i32 0),(i32 0),(i32 0),(i32 0), -+ (i32 0),(i32 0),(i32 0),(i32 0) -+ )), (v8i32 LASX256W:$b), uimm3:$ui3), -+ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>; -+ -+def : LASXPat<(LoongArchXVPICKVE (v4i64 (build_vector -+ (i64 0),(i64 0),(i64 0),(i64 0) -+ )), (v4i64 LASX256D:$b), uimm2:$ui2), -+ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>; -+ -+ -+def : LASXPat<(LoongArchXVPICKVE (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3), -+ (XVPICKVE_W LASX256W:$a, LASX256W:$b, uimm3:$ui3)>; -+ -+def : LASXPat<(LoongArchXVPICKVE (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2), -+ (XVPICKVE_D LASX256D:$a, LASX256D:$b, uimm2:$ui2)>; -+ -+ -+def : LASXPat<(LoongArchXVSHUF4I (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm8_32:$ui8), -+ (XVSHUF4I_D LASX256D:$a, LASX256D:$b, uimm8_32:$ui8)>; -+ -+def : LASXPat<(LoongArchXVPERMI (v4i64 LASX256D:$a), uimm8_32:$ui8), -+ (XVPERMI_D LASX256D:$a, uimm8_32:$ui8)>; -+ -+ -+ -+ -+//===----------------------------------------------------------------------===// -+// Intrinsics -+//===----------------------------------------------------------------------===// -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cor_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_COR_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cor_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_COR_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cun_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CUN_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cun_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CUN_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cune_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CUNE_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cune_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CUNE_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cueq_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CUEQ_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cueq_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CUEQ_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_ceq_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CEQ_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_ceq_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CEQ_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cne_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CNE_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cne_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CNE_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_clt_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CLT_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_clt_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CLT_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cult_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CULT_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cult_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CULT_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cle_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CLE_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cle_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CLE_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cule_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFCMP_CULE_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfcmp_cule_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFCMP_CULE_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvseq_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSEQ_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvseq_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSEQ_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvseq_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSEQ_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvseq_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSEQ_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsle_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSLE_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSLE_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSLE_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSLE_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsle_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSLE_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSLE_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSLE_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsle_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSLE_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvslt_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSLT_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSLT_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSLT_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSLT_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvslt_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSLT_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSLT_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSLT_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvslt_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSLT_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvadd_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVADD_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvadd_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVADD_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvadd_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVADD_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvadd_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVADD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsub_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSUB_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsub_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSUB_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsub_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSUB_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsub_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSUB_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmax_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMAX_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMAX_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMAX_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMAX_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmin_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMIN_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMIN_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMIN_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMIN_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmin_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMIN_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMIN_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMIN_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmin_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMIN_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmul_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMUL_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmul_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMUL_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmul_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMUL_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmul_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMUL_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvdiv_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVDIV_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVDIV_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVDIV_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVDIV_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsll_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSLL_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsll_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSLL_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsll_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSLL_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsll_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSLL_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsrl_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSRL_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsrl_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSRL_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsrl_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSRL_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsrl_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSRL_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsra_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSRA_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsra_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSRA_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsra_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSRA_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsra_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSRA_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfadd_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFADD_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfadd_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFADD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfsub_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFSUB_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfsub_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFSUB_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfmul_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFMUL_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfmul_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFMUL_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfdiv_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), -+ (XVFDIV_S LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvfdiv_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), -+ (XVFDIV_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfsqrt_s (v8f32 LASX256W:$xj)), -+ (XVFSQRT_S LASX256W:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvfsqrt_d (v4f64 LASX256D:$xj)), -+ (XVFSQRT_D LASX256D:$xj)>; -+ -+def : LASXPat<(v8f32 (int_loongarch_lasx_xvffint_s_w (v8i32 LASX256W:$xj))), -+ (XVFFINT_S_W (v8i32 LASX256W:$xj))>; -+def : LASXPat<(v8f32 (int_loongarch_lasx_xvffint_s_wu (v8i32 LASX256W:$xj))), -+ (XVFFINT_S_WU (v8i32 LASX256W:$xj))>; -+ -+def : LASXPat<(v4f64 (int_loongarch_lasx_xvffint_d_l (v4i64 LASX256D:$xj))), -+ (XVFFINT_D_L (v4i64 LASX256D:$xj))>; -+def : LASXPat<(v4f64 (int_loongarch_lasx_xvffint_d_lu (v4i64 LASX256D:$xj))), -+ (XVFFINT_D_LU (v4i64 LASX256D:$xj))>; -+ -+def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_b GPR32Opnd:$rj), -+ (XVREPLGR2VR_B GPR32Opnd:$rj)>; -+def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_h GPR32Opnd:$rj), -+ (XVREPLGR2VR_H GPR32Opnd:$rj)>; -+def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_w GPR32Opnd:$rj), -+ (XVREPLGR2VR_W GPR32Opnd:$rj)>; -+def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_d GPR64Opnd:$rj), -+ (XVREPLGR2VR_D GPR64Opnd:$rj)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickve2gr_w (v8i32 LASX256W:$xj), (immZExt3:$ui3)), -+ (XVPICKVE2GR_W LASX256W:$xj, uimm3:$ui3)>; -+def : LASXPat<(int_loongarch_lasx_xvpickve2gr_d (v4i64 LASX256D:$xj), (immZExt2:$ui2)), -+ (XVPICKVE2GR_D LASX256D:$xj, uimm2:$ui2)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickve2gr_wu (v8i32 LASX256W:$xj), (immZExt3:$ui3)), -+ (XVPICKVE2GR_WU LASX256W:$xj, uimm3:$ui3)>; -+def : LASXPat<(int_loongarch_lasx_xvpickve2gr_du (v4i64 LASX256D:$xj), (immZExt2:$ui2)), -+ (XVPICKVE2GR_DU LASX256D:$xj, uimm2:$ui2)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvreplve0_d (v4i64 LASX256D:$xj)), -+ (XVREPLVE0_D (v4i64 LASX256D:$xj))>; -+ -+def : LASXPat<(int_loongarch_lasx_xvinsgr2vr_w (v8i32 LASX256W:$xj), GPR32Opnd:$rj, (immZExt3:$ui3)), -+ (XVINSGR2VR_W LASX256W:$xj, GPR32Opnd:$rj, uimm3:$ui3)>; -+def : LASXPat<(int_loongarch_lasx_xvinsgr2vr_d (v4i64 LASX256D:$xj), GPR64Opnd:$rj, (immZExt2:$ui2)), -+ (XVINSGR2VR_D LASX256D:$xj, GPR64Opnd:$rj, uimm2:$ui2)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickve_w (v8i32 LASX256W:$xj), (immZExt3:$ui3)), -+ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$xj, uimm3:$ui3)>; -+def : LASXPat<(int_loongarch_lasx_xvpickve_d (v4i64 LASX256D:$xj), (immZExt2:$ui2)), -+ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$xj, uimm2:$ui2)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickve_w_f (v8f32 LASX256W:$xj), (immZExt3:$ui3)), -+ (XVPICKVE_W (v8f32 (IMPLICIT_DEF)), LASX256W:$xj, uimm3:$ui3)>; -+def : LASXPat<(int_loongarch_lasx_xvpickve_d_f (v4f64 LASX256D:$xj), (immZExt2:$ui2)), -+ (XVPICKVE_D (v4f64 (IMPLICIT_DEF)), LASX256D:$xj, uimm2:$ui2)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvdiv_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVDIV_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVDIV_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVDIV_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvdiv_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVDIV_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmod_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMOD_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMOD_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMOD_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMOD_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMOD_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMOD_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMOD_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMOD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmax_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMAX_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMAX_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMAX_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmax_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMAX_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvfrint_s (v8f32 LASX256W:$xj)), -+ (XVFRINT_S LASX256W:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvfrint_d (v4f64 LASX256D:$xj)), -+ (XVFRINT_D LASX256D:$xj)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpackod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVPACKOD_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVPACKOD_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVPACKOD_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVPACKOD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpackev_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVPACKEV_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackev_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVPACKEV_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackev_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVPACKEV_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpackev_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVPACKEV_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvilvh_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVILVH_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvh_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVILVH_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvh_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVILVH_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvh_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVILVH_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvilvl_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVILVL_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvl_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVILVL_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvl_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVILVL_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvilvl_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVILVL_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickev_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVPICKEV_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickev_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVPICKEV_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickev_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVPICKEV_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickev_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVPICKEV_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpickod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVPICKOD_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVPICKOD_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVPICKOD_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvpickod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVPICKOD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsadd_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSADD_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSADD_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSADD_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSADD_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvssub_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSSUB_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSSUB_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSSUB_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSSUB_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvsadd_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSADD_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSADD_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSADD_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvsadd_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSADD_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvssub_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVSSUB_BU LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVSSUB_HU LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVSSUB_WU LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvssub_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVSSUB_DU LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmadd_b (v32i8 LASX256B:$xd_in), (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMADD_B LASX256B:$xd_in, LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmadd_h (v16i16 LASX256H:$xd_in), (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMADD_H LASX256H:$xd_in, LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmadd_w (v8i32 LASX256W:$xd_in), (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMADD_W LASX256W:$xd_in, LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmadd_d (v4i64 LASX256D:$xd_in), (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMADD_D LASX256D:$xd_in, LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvmsub_b (v32i8 LASX256B:$xd_in), (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVMSUB_B LASX256B:$xd_in, LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmsub_h (v16i16 LASX256H:$xd_in), (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVMSUB_H LASX256H:$xd_in, LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmsub_w (v8i32 LASX256W:$xd_in), (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVMSUB_W LASX256W:$xd_in, LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvmsub_d (v4i64 LASX256D:$xd_in), (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVMSUB_D LASX256D:$xd_in, LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(v8i32 (int_loongarch_lasx_xvftintrz_wu_s (v8f32 LASX256W:$xj))), -+ (XVFTINTRZ_WU_S (v8f32 LASX256W:$xj))>; -+def : LASXPat<(v4i64 (int_loongarch_lasx_xvftintrz_lu_d (v4f64 LASX256D:$xj))), -+ (XVFTINTRZ_LU_D (v4f64 LASX256D:$xj))>; -+ -+def : LASXPat<(v8i32 (int_loongarch_lasx_xvftintrz_w_s (v8f32 LASX256W:$xj))), -+ (XVFTINTRZ_W_S (v8f32 LASX256W:$xj))>; -+def : LASXPat<(v4i64 (int_loongarch_lasx_xvftintrz_l_d (v4f64 LASX256D:$xj))), -+ (XVFTINTRZ_L_D (v4f64 LASX256D:$xj))>; -+ -+def : LASXPat<(int_loongarch_lasx_xvbitclr_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), -+ (XVBITCLR_B LASX256B:$xj, LASX256B:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvbitclr_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), -+ (XVBITCLR_H LASX256H:$xj, LASX256H:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvbitclr_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), -+ (XVBITCLR_W LASX256W:$xj, LASX256W:$xk)>; -+def : LASXPat<(int_loongarch_lasx_xvbitclr_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), -+ (XVBITCLR_D LASX256D:$xj, LASX256D:$xk)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvclz_b (v32i8 LASX256B:$xj)), -+ (XVCLZ_B LASX256B:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvclz_h (v16i16 LASX256H:$xj)), -+ (XVCLZ_H LASX256H:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvclz_w (v8i32 LASX256W:$xj)), -+ (XVCLZ_W LASX256W:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvclz_d (v4i64 LASX256D:$xj)), -+ (XVCLZ_D LASX256D:$xj)>; -+ -+def : LASXPat<(int_loongarch_lasx_xvpcnt_b (v32i8 LASX256B:$xj)), -+ (XVPCNT_B LASX256B:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvpcnt_h (v16i16 LASX256H:$xj)), -+ (XVPCNT_H LASX256H:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvpcnt_w (v8i32 LASX256W:$xj)), -+ (XVPCNT_W LASX256W:$xj)>; -+def : LASXPat<(int_loongarch_lasx_xvpcnt_d (v4i64 LASX256D:$xj)), -+ (XVPCNT_D LASX256D:$xj)>; -+ -+ -+def : LASXPat<(v32i8 (load (add iPTR:$xj, iPTR:$xk))), -+ (XVLDX PtrRC:$xj, PtrRC:$xk)>; -+ -+def : LASXPat<(store (v32i8 LASX256B:$xd), (add iPTR:$xj, iPTR:$xk)), -+ (XVSTX LASX256B:$xd, PtrRC:$xj, PtrRC:$xk)>; -+ -+ -+def : LASXPat<(v4i64 (sext_invec (v8i32 LASX256W:$xj))), -+ (VEXT2XV_D_W LASX256W:$xj)>; -+def : LASXPat<(v8i32 (sext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_W_H LASX256H:$xj)>; -+def : LASXPat<(v16i16 (sext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_H_B LASX256B:$xj)>; -+ -+ -+def : LASXPat<(v4i64 (zext_invec (v8i32 LASX256W:$xj))), -+ (VEXT2XV_DU_WU LASX256W:$xj)>; -+def : LASXPat<(v8i32 (zext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_WU_HU LASX256H:$xj)>; -+def : LASXPat<(v16i16 (zext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_HU_BU LASX256B:$xj)>; -+ -+ -+def : LASXPat<(v4i64 (sext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_D_H LASX256H:$xj)>; -+def : LASXPat<(v4i64 (sext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_D_B LASX256B:$xj)>; -+def : LASXPat<(v8i32 (sext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_W_B LASX256B:$xj)>; -+ -+ -+def : LASXPat<(v4i64 (zext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_DU_HU LASX256H:$xj)>; -+def : LASXPat<(v4i64 (zext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_DU_BU LASX256B:$xj)>; -+def : LASXPat<(v8i32 (zext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_WU_BU LASX256B:$xj)>; -+ -+ -+def : LASXPat<(v4i64 (sext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_D_H LASX256H:$xj)>; -+def : LASXPat<(v4i64 (sext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_D_B LASX256B:$xj)>; -+def : LASXPat<(v8i32 (sext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_W_B LASX256B:$xj)>; -+ -+def : LASXPat<(v4i64 (zext_invec (v16i16 LASX256H:$xj))), -+ (VEXT2XV_DU_HU LASX256H:$xj)>; -+def : LASXPat<(v4i64 (zext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_DU_BU LASX256B:$xj)>; -+def : LASXPat<(v8i32 (zext_invec (v32i8 LASX256B:$xj))), -+ (VEXT2XV_WU_BU LASX256B:$xj)>; -+ -+ -+def : LASXPat<(v16i16 (sext (v16i8 LSX128B:$vj))), -+ (VEXT2XV_H_B -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$vj, sub_128))>; -+ -+def : LASXPat<(v8i32 (sext (v8i16 LSX128H:$vj))), -+ (VEXT2XV_W_H -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$vj, sub_128))>; -+ -+def : LASXPat<(v4i64 (sext (v4i32 LSX128W:$vj))), -+ (VEXT2XV_D_W -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$vj, sub_128))>; -+ -+def : LASXPat<(v16i16 (zext (v16i8 LSX128B:$vj))), -+ (VEXT2XV_HU_BU -+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$vj, sub_128))>; -+ -+def : LASXPat<(v8i32 (zext (v8i16 LSX128H:$vj))), -+ (VEXT2XV_WU_HU -+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$vj, sub_128))>; -+ -+def : LASXPat<(v4i64 (zext (v4i32 LSX128W:$vj))), -+ (VEXT2XV_DU_WU -+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$vj, sub_128))>; -+ -+ -+def : LASXPat<(xor -+ (v16i16 LASX256H:$xj), (xvsplati16 imm_mask) -+ ), -+ (XNOR_V_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xj))>; -+ -+def : LASXPat<(xor -+ (v8i32 LASX256W:$xj), (xvsplati32 imm_mask) -+ ), -+ (XNOR_V_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xj))>; -+ -+def : LASXPat<(xor -+ (v4i64 LASX256D:$xj), (xvsplati64 imm_mask_64) -+ ), -+ (XNOR_V_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xj))>; -+ -+ -+def : LASXPat<(and -+ (v32i8 (xor (v32i8 LASX256B:$xj), (xvsplati8 imm_mask))), -+ (v32i8 LASX256B:$xk) -+ ), -+ (XVANDN_V (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk))>; -+ -+def : LASXPat<(and -+ (v16i16 (xor (v16i16 LASX256H:$xj), (xvsplati16 imm_mask))), -+ (v16i16 LASX256H:$xk) -+ ), -+ (XVANDN_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk))>; -+ -+def : LASXPat<(and -+ (v8i32 (xor (v8i32 LASX256W:$xj), (xvsplati32 imm_mask))), -+ (v8i32 LASX256W:$xk) -+ ), -+ (XVANDN_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk))>; -+ -+def : LASXPat<(and -+ (v4i64 (xor (v4i64 LASX256D:$xj), (xvsplati64 imm_mask_64))), -+ (v4i64 LASX256D:$xk) -+ ), -+ (XVANDN_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk))>; -+ -+ -+def : LASXPat<(or -+ (v32i8 LASX256B:$xj), -+ (v32i8 (xor (v32i8 LASX256B:$xk), (xvsplati8 imm_mask))) -+ ), -+ (XVORN_V (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk))>; -+ -+def : LASXPat<(or -+ (v16i16 LASX256H:$xj), -+ (v16i16 (xor (v16i16 LASX256H:$xk), (xvsplati16 imm_mask))) -+ ), -+ (XVORN_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk))>; -+ -+def : LASXPat<(or -+ (v8i32 LASX256W:$xj), -+ (v8i32 (xor (v8i32 LASX256W:$xk), (xvsplati32 imm_mask))) -+ ), -+ (XVORN_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk))>; -+ -+def : LASXPat<(or -+ (v4i64 LASX256D:$xj), -+ (v4i64 (xor (v4i64 LASX256D:$xk), (xvsplati64 imm_mask_64))) -+ ), -+ (XVORN_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk))>; -+ -+ -+def : LASXPat<(add (v4i64 (abs LASX256D:$a)), (v4i64 (abs LASX256D:$b))), -+ (XVADDA_D (v4i64 LASX256D:$a),(v4i64 LASX256D:$b))>; -+ -+def : LASXPat<(add (v8i32 (abs LASX256W:$a)), (v8i32 (abs LASX256W:$b))), -+ (XVADDA_W (v8i32 LASX256W:$a),(v8i32 LASX256W:$b))>; -+ -+def : LASXPat<(add (v16i16 (abs LASX256H:$a)), (v16i16 (abs LASX256H:$b))), -+ (XVADDA_H (v16i16 LASX256H:$a),(v16i16 LASX256H:$b))>; -+ -+def : LASXPat<(add (v32i8 (abs LASX256B:$a)), (v32i8 (abs LASX256B:$b))), -+ (XVADDA_B (v32i8 LASX256B:$a),(v32i8 LASX256B:$b))>; -+ -+ -+def : LASXPat<(and v32i8:$xj, (xor (shl xvsplat_imm_eq_1, v32i8:$xk), -+ (xvsplati8 imm_mask))), -+ (XVBITCLR_B v32i8:$xj, v32i8:$xk)>; -+ -+def : LASXPat<(and v16i16:$xj, (xor (shl xvsplat_imm_eq_1, v16i16:$xk), -+ (xvsplati16 imm_mask))), -+ (XVBITCLR_H v16i16:$xj, v16i16:$xk)>; -+ -+def : LASXPat<(and v8i32:$xj, (xor (shl xvsplat_imm_eq_1, v8i32:$xk), -+ (xvsplati32 imm_mask))), -+ (XVBITCLR_W v8i32:$xj, v8i32:$xk)>; -+ -+def : LASXPat<(and v4i64:$xj, (xor (shl xvsplat_imm_eq_1, v4i64:$xk), -+ (xvsplati64 imm_mask_64))), -+ (XVBITCLR_D v4i64:$xj, v4i64:$xk)>; -+ -+ -+def : LASXPat<(insert_subvector (v16i16 LASX256H:$dst), -+ (v8i16 LSX128H:$src), (i64 0)), -+ (XVPERMI_QH (v16i16 LASX256H:$dst), -+ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), -+ LSX128H:$src, sub_128)), -+ (i32 48))>; -+ -+def : LASXPat<(insert_subvector (v8i32 LASX256W:$dst), -+ (v4i32 LSX128W:$src), (i64 0)), -+ (XVPERMI_QW (v8i32 LASX256W:$dst), -+ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), -+ LSX128W:$src, sub_128)), -+ (i32 48))>; -+ -+def : LASXPat<(insert_subvector (v4i64 LASX256D:$dst), -+ (v2i64 LSX128D:$src), (i64 0)), -+ (XVPERMI_QD (v4i64 LASX256D:$dst), -+ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), -+ LSX128D:$src, sub_128)), -+ (i32 48))>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td -new file mode 100644 -index 000000000..50df4d724 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td -@@ -0,0 +1,449 @@ -+//===- LoongArchLSXInstrFormats.td - LoongArch LSX Instruction Formats ---*- tablegen -*-===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+ -+class LSXInst : InstLA<(outs), (ins), "", [], FrmOther>, -+ EXT_LSX { -+} -+ -+class LSXCBranch : LSXInst { -+} -+ -+class LSXSpecial : LSXInst { -+} -+ -+class LSXPseudo pattern>: -+ LoongArchPseudo { -+ let Predicates = [HasLSX]; -+} -+ -+class LSX_3R op>: LSXInst { -+ bits<5> vk; -+ bits<5> vj; -+ bits<5> vd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = vk; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_3R_1GP op>: LSXInst { -+ bits<5> rk; -+ bits<5> vj; -+ bits<5> vd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I5 op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<5> si5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = si5; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I5_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<5> ui5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = ui5; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_2R op>: LSXInst { -+ bits<5> vj; -+ bits<5> vd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_2R_1GP op>: LSXInst { -+ bits<5> rj; -+ bits<5> vd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I1_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I2_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I3_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I4_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I6_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<6> ui6; -+ -+ let Inst{31-16} = op; -+ let Inst{15-10} = ui6; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I1_R_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I2_R_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I3_R_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I4_R_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_ELM_COPY_B op>: LSXInst { -+ bits<5> rd; -+ bits<5> vj; -+ bits<4> ui4; -+ -+ let Inst{31-14} = op; -+ let Inst{13-10} = ui4; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = rd; -+} -+ -+class LSX_ELM_COPY_H op>: LSXInst { -+ bits<5> rd; -+ bits<5> vj; -+ bits<3> ui3; -+ -+ let Inst{31-13} = op; -+ let Inst{12-10} = ui3; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = rd; -+} -+ -+class LSX_ELM_COPY_W op>: LSXInst { -+ bits<5> rd; -+ bits<5> vj; -+ bits<2> ui2; -+ -+ let Inst{31-12} = op; -+ let Inst{11-10} = ui2; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = rd; -+} -+ -+class LSX_ELM_COPY_D op>: LSXInst { -+ bits<5> rd; -+ bits<5> vj; -+ bits<1> ui1; -+ -+ let Inst{31-11} = op; -+ let Inst{10} = ui1; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = rd; -+} -+ -+class LSX_I8_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<8> ui8; -+ -+ let Inst{31-18} = op; -+ let Inst{17-10} = ui8; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I7_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<7> ui7; -+ -+ let Inst{31-17} = op; -+ let Inst{16-10} = ui7; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I12_S op>: LSXInst { -+ bits<5> vd; -+// bits<5> rj; -+// bits<12> si12; -+ bits<17> addr; -+ -+ let Inst{31-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI12_S op>: LSXInst { -+ bits<5> vd; -+ bits<17> addr; -+ -+ let Inst{31-22} = op; -+ let Inst{21-10} = addr{11-0}; -+ let Inst{9-5} = addr{16-12}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI11_S op>: LSXInst { -+ bits<5> vd; -+ bits<16> addr; -+ -+ let Inst{31-21} = op; -+ let Inst{20-10} = addr{10-0}; -+ let Inst{9-5} = addr{15-11}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI10_S op>: LSXInst { -+ bits<5> vd; -+ bits<15> addr; -+ -+ let Inst{31-20} = op; -+ let Inst{19-10} = addr{9-0}; -+ let Inst{9-5} = addr{14-10}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI9_S op>: LSXInst { -+ bits<5> vd; -+ bits<14> addr; -+ -+ let Inst{31-19} = op; -+ let Inst{18-10} = addr{8-0}; -+ let Inst{9-5} = addr{13-9}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SET op>: LSXInst { -+ bits<5> vj; -+ bits<3> cd; -+ -+ let Inst{31-10} = op; -+ let Inst{9-5} = vj; -+ let Inst{4-3} = 0b00; -+ let Inst{2-0} = cd; -+} -+ -+class LSX_VR4MUL op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<5> vk; -+ bits<5> va; -+ -+ let Inst{31-20} = op; -+ let Inst{19-15} = va; -+ let Inst{14-10} = vk; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_VFCMP op>: LSXInst { -+ bits<5> vd; -+ bits<5> vj; -+ bits<5> vk; -+ bits<5> cond; -+ -+ let Inst{31-20} = op; -+ let Inst{19-15} = cond; -+ let Inst{14-10} = vk; -+ let Inst{9-5} = vj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_Addr_SI8_idx1 op>: LSXInst { -+ bits<5> vd; -+ bits<13> addr; -+ bits<1> idx; -+ -+ let Inst{31-19} = op; -+ let Inst{18-11} = addr{7-0}; -+ let Inst{10} = idx; -+ let Inst{9-5} = addr{12-8}; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI8_idx1 op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<1> idx; -+ -+ let Inst{31-19} = op; -+ let Inst{18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI8_idx2 op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<2> idx; -+ -+ let Inst{31-20} = op; -+ let Inst{19-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI8_idx3 op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<3> idx; -+ -+ let Inst{31-21} = op; -+ let Inst{20-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_SI8_idx4 op>: LSXInst { -+ bits<5> vd; -+ bits<5> rj; -+ bits<8> si8; -+ bits<4> idx; -+ -+ let Inst{31-22} = op; -+ let Inst{21-18} = idx; -+ let Inst{17-10} = si8; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_3R_2GP op>: LSXInst { -+ bits<5> rk; -+ bits<5> rj; -+ bits<5> vd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = rk; -+ let Inst{9-5} = rj; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_I5_mode_U op>: LSXInst { -+ bits<5> vd; -+ bits<5> mode; -+ bits<5> ui5; -+ -+ let Inst{31-15} = op; -+ let Inst{14-10} = ui5; -+ let Inst{9-5} = mode; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_1R_I13 op>: LSXInst { -+ bits<13> i13; -+ bits<5> vd; -+ -+ let Inst{31-18} = op; -+ let Inst{17-5} = i13; -+ let Inst{4-0} = vd; -+} -+ -+class LSX_1R_I13_I10 op>: LSXInst { -+ bits<10> i10; -+ bits<5> vd; -+ -+ let Inst{31-15} = op; -+ let Inst{14-5} = i10; -+ let Inst{4-0} = vd; -+} -+ -+ -+ -+ -+ -+ -+ -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td -new file mode 100644 -index 000000000..3d0ea3901 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td -@@ -0,0 +1,5906 @@ -+//===- LoongArchLSXInstrInfo.td - LSX instructions -*- tablegen ------------*-=// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+// -+// This file describes LoongArch LSX instructions. -+// -+//===----------------------------------------------------------------------===// -+ -+def SDT_LoongArchVecCond : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<1>]>; -+def SDT_VSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, -+ SDTCisInt<1>, -+ SDTCisSameAs<1, 2>, -+ SDTCisVT<3, OtherVT>]>; -+def SDT_VFSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, -+ SDTCisFP<1>, -+ SDTCisSameAs<1, 2>, -+ SDTCisVT<3, OtherVT>]>; -+def SDT_VSHF : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>, -+ SDTCisInt<1>, SDTCisVec<1>, -+ SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; -+def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, -+ SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>; -+def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, -+ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>; -+def SDTVABSD : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, -+ SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; -+ -+def SDT_VBROADCAST : SDTypeProfile<1, 1, [SDTCisVec<0>]>; -+def LoongArchVBROADCAST : SDNode<"LoongArchISD::VBROADCAST", SDT_VBROADCAST>; -+ -+def LoongArchVAllNonZero : SDNode<"LoongArchISD::VALL_NONZERO", SDT_LoongArchVecCond>; -+def LoongArchVAnyNonZero : SDNode<"LoongArchISD::VANY_NONZERO", SDT_LoongArchVecCond>; -+def LoongArchVAllZero : SDNode<"LoongArchISD::VALL_ZERO", SDT_LoongArchVecCond>; -+def LoongArchVAnyZero : SDNode<"LoongArchISD::VANY_ZERO", SDT_LoongArchVecCond>; -+def LoongArchVNOR : SDNode<"LoongArchISD::VNOR", SDTIntBinOp, -+ [SDNPCommutative, SDNPAssociative]>; -+def LoongArchVSHF : SDNode<"LoongArchISD::VSHF", SDT_VSHF>; -+def LoongArchSHF : SDNode<"LoongArchISD::SHF", SDT_SHF>; -+def LoongArchVPACKEV : SDNode<"LoongArchISD::VPACKEV", SDT_ILV>; -+def LoongArchVPACKOD : SDNode<"LoongArchISD::VPACKOD", SDT_ILV>; -+def LoongArchVILVH : SDNode<"LoongArchISD::VILVH", SDT_ILV>; -+def LoongArchVILVL : SDNode<"LoongArchISD::VILVL", SDT_ILV>; -+def LoongArchVPICKEV : SDNode<"LoongArchISD::VPICKEV", SDT_ILV>; -+def LoongArchVPICKOD : SDNode<"LoongArchISD::VPICKOD", SDT_ILV>; -+def LoongArchVABSD : SDNode<"LoongArchISD::VABSD", SDTVABSD>; -+def LoongArchUVABSD : SDNode<"LoongArchISD::UVABSD", SDTVABSD>; -+ -+def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>; -+def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>; -+ -+def LoongArchVExtractSExt : SDNode<"LoongArchISD::VEXTRACT_SEXT_ELT", -+ SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; -+def LoongArchVExtractZExt : SDNode<"LoongArchISD::VEXTRACT_ZEXT_ELT", -+ SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; -+ -+def immZExt1Ptr : ImmLeaf(Imm);}]>; -+def immZExt2Ptr : ImmLeaf(Imm);}]>; -+def immZExt3Ptr : ImmLeaf(Imm);}]>; -+def immZExt4Ptr : ImmLeaf(Imm);}]>; -+def immZExt5Ptr : ImmLeaf(Imm);}]>; -+def immZExt10 : ImmLeaf(Imm);}]>; -+def immZExt8 : ImmLeaf(Imm);}]>; -+def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>; -+def immZExt6 : ImmLeaf; -+def immZExt4 : ImmLeaf(Imm);}]>; -+def immZExt3 : ImmLeaf(Imm);}]>; -+def immZExt2 : ImmLeaf(Imm);}]>; -+def immZExt1 : ImmLeaf(Imm);}]>; -+def immSExt12_l : ImmLeaf(Imm);}]>; -+def immSExt11Ptr : ImmLeaf(Imm);}]>; -+ -+def immSExt11_1 : ImmLeaf(Imm<<1);}]>; -+def immSExt10Ptr : ImmLeaf(Imm);}]>; -+def immSExt10_2 : ImmLeaf(Imm<<2);}]>; -+def immSExt9Ptr : ImmLeaf(Imm);}]>; -+def immSExt9_3 : ImmLeaf(Imm<<3);}]>; -+def immSExt8 : ImmLeaf(Imm);}]>; -+def immSExt5 : ImmLeaf(Imm);}]>; -+def immSExt8_1 : ImmLeaf(Imm<<1);}]>; -+def immSExt8_2 : ImmLeaf(Imm<<2);}]>; -+def immSExt8_3 : ImmLeaf(Imm<<3);}]>; -+ -+def addrimm10 : ComplexPattern; -+def addrimm10lsl2 : ComplexPattern; -+def addrimm9lsl3 : ComplexPattern; -+def addrimm11lsl1 : ComplexPattern; -+ -+ -+class SimmLslAsmOperandClass Supers = [], -+ int Shift = 0> : AsmOperandClass { -+ let Name = "Simm" # Bits # "_Lsl" # Shift; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift; -+} -+ -+def Simm11Lsl1AsmOperand -+ : SimmLslAsmOperandClass<11, [], 1>; -+ -+def immSExt11_1_O : Operand { -+ let EncoderMethod = "getSImm11Lsl1Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; -+ let ParserMatchClass = Simm11Lsl1AsmOperand; -+} -+ -+def Simm10Lsl2AsmOperand -+ : SimmLslAsmOperandClass<10, [], 2>; -+ -+def immSExt10_2_O : Operand { -+ let EncoderMethod = "getSImm10Lsl2Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<4>"; -+ let ParserMatchClass = Simm10Lsl2AsmOperand; -+} -+ -+def Simm9Lsl3AsmOperand -+ : SimmLslAsmOperandClass<9, [], 3>; -+ -+def immSExt9_3_O : Operand { -+ let EncoderMethod = "getSImm9Lsl3Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; -+ let ParserMatchClass = Simm9Lsl3AsmOperand; -+} -+ -+def Simm8Lsl3AsmOperand -+ : SimmLslAsmOperandClass<8, [], 3>; -+ -+def immSExt8_3_O : Operand { -+ let EncoderMethod = "getSImm8Lsl3Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; -+ let ParserMatchClass = Simm8Lsl3AsmOperand; -+} -+ -+def Simm8Lsl2AsmOperand -+ : SimmLslAsmOperandClass<8, [], 2>; -+ -+def immSExt8_2_O : Operand { -+ let EncoderMethod = "getSImm8Lsl2Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<4>"; -+ let ParserMatchClass = Simm8Lsl2AsmOperand; -+} -+ -+def Simm8Lsl1AsmOperand -+ : SimmLslAsmOperandClass<8, [], 1>; -+ -+def immSExt8_1_O : Operand { -+ let EncoderMethod = "getSImm8Lsl1Encoding"; -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; -+ let ParserMatchClass = Simm8Lsl1AsmOperand; -+} -+ -+ -+class ConstantSImmAsmOperandClass Supers = [], -+ int Offset = 0> : AsmOperandClass { -+ let Name = "ConstantSImm" # Bits # "_" # Offset; -+ let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">"; -+ let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "SImm" # Bits # "_" # Offset; -+} -+ -+class ConstantUImmRangeAsmOperandClass Supers = []> -+ : AsmOperandClass { -+ let Name = "ConstantUImmRange" # Bottom # "_" # Top; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">"; -+ let SuperClasses = Supers; -+ let DiagnosticType = "UImmRange" # Bottom # "_" # Top; -+} -+ -+def SImm16RelaxedAsmOperandClass -+ : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { -+ let Name = "SImm16_Relaxed"; -+ let PredicateMethod = "isAnyImm<16>"; -+ let DiagnosticType = "SImm16_Relaxed"; -+} -+ -+def ConstantSImm11Lsl1AsmOperandClass : AsmOperandClass { -+ let Name = "SImm11Lsl1"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<11, 1>"; -+ let SuperClasses = [SImm12Operand]; -+ let DiagnosticType = "SImm11_Lsl1"; -+} -+ -+def ConstantSImm9Lsl3AsmOperandClass : AsmOperandClass { -+ let Name = "SImm9Lsl3"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<9, 3>"; -+ let SuperClasses = [SImm12Operand]; -+ let DiagnosticType = "SImm9_Lsl3"; -+} -+ -+def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { -+ let Name = "SImm10Lsl2"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<10, 2>"; -+ let SuperClasses = [SImm12Operand]; -+ let DiagnosticType = "SImm10_Lsl2"; -+} -+def ConstantSImm11AsmOperandClass -+ : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>; -+def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass { -+ let Name = "SImm10Lsl1"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<10, 1>"; -+ let SuperClasses = [ConstantSImm11AsmOperandClass]; -+ let DiagnosticType = "SImm10_Lsl1"; -+} -+def ConstantUImm10AsmOperandClass -+ : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>; -+def ConstantSImm10AsmOperandClass -+ : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>; -+def ConstantSImm9AsmOperandClass -+ : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>; -+def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass { -+ let Name = "SImm7Lsl2"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledSImm<7, 2>"; -+ let SuperClasses = [ConstantSImm9AsmOperandClass]; -+ let DiagnosticType = "SImm7_Lsl2"; -+} -+def ConstantUImm8AsmOperandClass -+ : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>; -+def ConstantUImm7Sub1AsmOperandClass -+ : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> { -+ // Specify the names since the -1 offset causes invalid identifiers otherwise. -+ let Name = "UImm7_N1"; -+ let DiagnosticType = "UImm7_N1"; -+} -+def ConstantUImm7AsmOperandClass -+ : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>; -+def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass { -+ let Name = "UImm6Lsl2"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledUImm<6, 2>"; -+ let SuperClasses = [ConstantUImm7AsmOperandClass]; -+ let DiagnosticType = "UImm6_Lsl2"; -+} -+def ConstantUImm6AsmOperandClass -+ : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>; -+def ConstantSImm6AsmOperandClass -+ : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>; -+def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { -+ let Name = "UImm5Lsl2"; -+ let RenderMethod = "addImmOperands"; -+ let PredicateMethod = "isScaledUImm<5, 2>"; -+ let SuperClasses = [ConstantSImm6AsmOperandClass]; -+ let DiagnosticType = "UImm5_Lsl2"; -+} -+def ConstantUImm5_Range2_64AsmOperandClass -+ : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>; -+def ConstantUImm5Plus33AsmOperandClass -+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass], -+ 33>; -+def ConstantUImm5ReportUImm6AsmOperandClass -+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> { -+ let Name = "ConstantUImm5_0_Report_UImm6"; -+ let DiagnosticType = "UImm5_0_Report_UImm6"; -+} -+def ConstantUImm5Plus32AsmOperandClass -+ : ConstantUImmAsmOperandClass< -+ 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>; -+def ConstantUImm5Plus32NormalizeAsmOperandClass -+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> { -+ let Name = "ConstantUImm5_32_Norm"; -+ // We must also subtract 32 when we render the operand. -+ let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; -+} -+def ConstantUImm5Plus1ReportUImm6AsmOperandClass -+ : ConstantUImmAsmOperandClass< -+ 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>{ -+ let Name = "ConstantUImm5_Plus1_Report_UImm6"; -+} -+def ConstantUImm5Plus1AsmOperandClass -+ : ConstantUImmAsmOperandClass< -+ 5, [ConstantUImm5Plus1ReportUImm6AsmOperandClass], 1>; -+def ConstantUImm5AsmOperandClass -+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>; -+def ConstantSImm5AsmOperandClass -+ : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>; -+def ConstantUImm4AsmOperandClass -+ : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>; -+def ConstantSImm4AsmOperandClass -+ : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>; -+def ConstantUImm3AsmOperandClass -+ : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>; -+def ConstantUImm2AsmOperandClass -+ : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass]>; -+def ConstantUImm1AsmOperandClass -+ : ConstantUImmAsmOperandClass<1, [ConstantUImm2AsmOperandClass]>; -+def ConstantImmzAsmOperandClass : AsmOperandClass { -+ let Name = "ConstantImmz"; -+ let RenderMethod = "addConstantUImmOperands<1>"; -+ let PredicateMethod = "isConstantImmz"; -+ let SuperClasses = [ConstantUImm1AsmOperandClass]; -+ let DiagnosticType = "Immz"; -+} -+ -+foreach I = {1, 2, 3, 4, 5, 6, 8} in -+ def vsplat_uimm # I : Operand { -+ let PrintMethod = "printUImm<" # I # ">"; -+ let ParserMatchClass = -+ !cast("ConstantUImm" # I # "AsmOperandClass"); -+ } -+ -+foreach I = {5, 10} in -+ def vsplat_simm # I : Operand { -+ let ParserMatchClass = -+ !cast("ConstantSImm" # I # "AsmOperandClass"); -+ } -+ -+foreach I = {1, 4, 7, 8, 10, 20, 26} in -+ def uimm # I : Operand { -+ let PrintMethod = "printUImm<" # I # ">"; -+ let ParserMatchClass = -+ !cast("ConstantUImm" # I # "AsmOperandClass"); -+ } -+ -+foreach I = {1, 2, 3, 4, 5, 6, 7, 8} in -+ def uimm # I # _ptr : Operand { -+ let PrintMethod = "printUImm<" # I # ">"; -+ let ParserMatchClass = -+ !cast("ConstantUImm" # I # "AsmOperandClass"); -+ } -+ -+ -+def addrimm12 : ComplexPattern; -+ -+ -+def LoongArchMemSimm12AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm12"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<12>"; -+ let DiagnosticType = "MemSImm12"; -+} -+ -+def mem_simm12 : mem_generic { -+ let MIOperandInfo = (ops ptr_rc, simm12); -+ let EncoderMethod = "getMemEncoding"; -+ let ParserMatchClass = LoongArchMemSimm12AsmOperand; -+} -+ -+foreach I = {4, 6, 9, 10, 11} in -+ def simm # I : Operand { -+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; -+ let ParserMatchClass = -+ !cast("ConstantSImm" # I # "AsmOperandClass"); -+ } -+ -+def LoongArchMemSimm9AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm9"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<9>"; -+ let DiagnosticType = "MemSImm9"; -+} -+ -+def LoongArchMemSimm10AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm10"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<10>"; -+ let DiagnosticType = "MemSImm10"; -+} -+ -+def LoongArchMemSimm11AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm11"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<11>"; -+ let DiagnosticType = "MemSImm11"; -+} -+ -+def simm13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; -+ -+def simm10Op : Operand { -+ let DecoderMethod = "DecodeSIMM10"; -+} -+ -+def simm13Op : Operand { -+ let DecoderMethod = "DecodeSIMM13"; -+} -+ -+def LoongArchMemSimm10Lsl2AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm10_2"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<10, 2>"; -+ let DiagnosticType = "MemSImm10Lsl2"; -+} -+ -+ -+def simm10_lsl2 : Operand { -+// let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, 2>"; -+ let ParserMatchClass = -+ !cast("ConstantSImm10Lsl2AsmOperandClass"); -+} -+ -+def mem_simm10_lsl2 : mem_generic { -+ let MIOperandInfo = (ops ptr_rc, !cast("simm10_lsl2")); -+ let EncoderMethod = "getMemEncoding10l2"; -+ let ParserMatchClass = -+ !cast("LoongArchMemSimm10Lsl2AsmOperand"); -+} -+ -+ -+def LoongArchMemSimm11Lsl1AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm11_1"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<11, 1>"; -+ let DiagnosticType = "MemSImm11Lsl1"; -+} -+ -+ -+def simm11_lsl1 : Operand { -+ // let DecoderMethod = "DecodeSImmWithOffsetAndScale<11, 1>"; -+ let ParserMatchClass = -+ !cast("ConstantSImm11Lsl1AsmOperandClass"); -+} -+ -+def mem_simm11_lsl1 : mem_generic { -+ let MIOperandInfo = (ops ptr_rc, !cast("simm11_lsl1")); -+ let EncoderMethod = "getMemEncoding11l1"; -+ let ParserMatchClass = -+ !cast("LoongArchMemSimm11Lsl1AsmOperand"); -+} -+ -+def LoongArchMemSimm9Lsl3AsmOperand : AsmOperandClass { -+ let Name = "MemOffsetSimm9_3"; -+ let SuperClasses = [LoongArchMemAsmOperand]; -+ let RenderMethod = "addMemOperands"; -+ let ParserMethod = "parseMemOperand"; -+ let PredicateMethod = "isMemWithSimmOffset<9, 3>"; -+ let DiagnosticType = "MemSImm9Lsl3"; -+} -+ -+ -+def simm9_lsl3 : Operand { -+ // let DecoderMethod = "DecodeSImmWithOffsetAndScale<9, 3>"; -+ let ParserMatchClass = -+ !cast("ConstantSImm9Lsl3AsmOperandClass"); -+} -+ -+def mem_simm9_lsl3 : mem_generic { -+ let MIOperandInfo = (ops ptr_rc, !cast("simm9_lsl3")); -+ let EncoderMethod = "getMemEncoding9l3"; -+ let ParserMatchClass = -+ !cast("LoongArchMemSimm9Lsl3AsmOperand"); -+} -+ -+ -+ -+ -+// Operands -+ -+def immZExt2Lsa : ImmLeaf(Imm - 1);}]>; -+ -+// Pattern fragments -+def vextract_sext_i8 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractSExt node:$vec, node:$idx, i8)>; -+def vextract_sext_i16 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractSExt node:$vec, node:$idx, i16)>; -+def vextract_sext_i32 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractSExt node:$vec, node:$idx, i32)>; -+def vextract_sext_i64 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractSExt node:$vec, node:$idx, i64)>; -+ -+def vextract_zext_i8 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractZExt node:$vec, node:$idx, i8)>; -+def vextract_zext_i16 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractZExt node:$vec, node:$idx, i16)>; -+def vextract_zext_i32 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractZExt node:$vec, node:$idx, i32)>; -+def vextract_zext_i64 : PatFrag<(ops node:$vec, node:$idx), -+ (LoongArchVExtractZExt node:$vec, node:$idx, i64)>; -+ -+def vldrepl_v16i8 : PatFrag<(ops node:$v1), -+ (v16i8 (LoongArchVBROADCAST node:$v1))>; -+def vldrepl_v8i16 : PatFrag<(ops node:$v1), -+ (v8i16 (LoongArchVBROADCAST node:$v1))>; -+def vldrepl_v4i32 : PatFrag<(ops node:$v1), -+ (v4i32 (LoongArchVBROADCAST node:$v1))>; -+def vldrepl_v2i64 : PatFrag<(ops node:$v1), -+ (v2i64 (LoongArchVBROADCAST node:$v1))>; -+ -+def vinsert_v16i8 : PatFrag<(ops node:$vec, node:$val, node:$idx), -+ (v16i8 (vector_insert node:$vec, node:$val, node:$idx))>; -+def vinsert_v8i16 : PatFrag<(ops node:$vec, node:$val, node:$idx), -+ (v8i16 (vector_insert node:$vec, node:$val, node:$idx))>; -+def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx), -+ (v4i32 (vector_insert node:$vec, node:$val, node:$idx))>; -+def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx), -+ (v2i64 (vector_insert node:$vec, node:$val, node:$idx))>; -+ -+class vfsetcc_type : -+ PatFrag<(ops node:$lhs, node:$rhs), -+ (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>; -+ -+// ISD::SETFALSE cannot occur -+def vfseteq_v4f32 : vfsetcc_type; -+def vfseteq_v2f64 : vfsetcc_type; -+def vfsetge_v4f32 : vfsetcc_type; -+def vfsetge_v2f64 : vfsetcc_type; -+def vfsetgt_v4f32 : vfsetcc_type; -+def vfsetgt_v2f64 : vfsetcc_type; -+def vfsetle_v4f32 : vfsetcc_type; -+def vfsetle_v2f64 : vfsetcc_type; -+def vfsetlt_v4f32 : vfsetcc_type; -+def vfsetlt_v2f64 : vfsetcc_type; -+def vfsetne_v4f32 : vfsetcc_type; -+def vfsetne_v2f64 : vfsetcc_type; -+def vfsetoeq_v4f32 : vfsetcc_type; -+def vfsetoeq_v2f64 : vfsetcc_type; -+def vfsetoge_v4f32 : vfsetcc_type; -+def vfsetoge_v2f64 : vfsetcc_type; -+def vfsetogt_v4f32 : vfsetcc_type; -+def vfsetogt_v2f64 : vfsetcc_type; -+def vfsetole_v4f32 : vfsetcc_type; -+def vfsetole_v2f64 : vfsetcc_type; -+def vfsetolt_v4f32 : vfsetcc_type; -+def vfsetolt_v2f64 : vfsetcc_type; -+def vfsetone_v4f32 : vfsetcc_type; -+def vfsetone_v2f64 : vfsetcc_type; -+def vfsetord_v4f32 : vfsetcc_type; -+def vfsetord_v2f64 : vfsetcc_type; -+def vfsetun_v4f32 : vfsetcc_type; -+def vfsetun_v2f64 : vfsetcc_type; -+def vfsetueq_v4f32 : vfsetcc_type; -+def vfsetueq_v2f64 : vfsetcc_type; -+def vfsetuge_v4f32 : vfsetcc_type; -+def vfsetuge_v2f64 : vfsetcc_type; -+def vfsetugt_v4f32 : vfsetcc_type; -+def vfsetugt_v2f64 : vfsetcc_type; -+def vfsetule_v4f32 : vfsetcc_type; -+def vfsetule_v2f64 : vfsetcc_type; -+def vfsetult_v4f32 : vfsetcc_type; -+def vfsetult_v2f64 : vfsetcc_type; -+def vfsetune_v4f32 : vfsetcc_type; -+def vfsetune_v2f64 : vfsetcc_type; -+ -+ -+ -+// ISD::SETTRUE cannot occur -+// ISD::SETFALSE2 cannot occur -+// ISD::SETTRUE2 cannot occur -+ -+class vsetcc_type : -+ PatFrag<(ops node:$lhs, node:$rhs), -+ (ResTy (vsetcc node:$lhs, node:$rhs, CC))>; -+ -+def vseteq_v16i8 : vsetcc_type; -+def vseteq_v8i16 : vsetcc_type; -+def vseteq_v4i32 : vsetcc_type; -+def vseteq_v2i64 : vsetcc_type; -+def vsetle_v16i8 : vsetcc_type; -+def vsetle_v8i16 : vsetcc_type; -+def vsetle_v4i32 : vsetcc_type; -+def vsetle_v2i64 : vsetcc_type; -+def vsetlt_v16i8 : vsetcc_type; -+def vsetlt_v8i16 : vsetcc_type; -+def vsetlt_v4i32 : vsetcc_type; -+def vsetlt_v2i64 : vsetcc_type; -+def vsetule_v16i8 : vsetcc_type; -+def vsetule_v8i16 : vsetcc_type; -+def vsetule_v4i32 : vsetcc_type; -+def vsetule_v2i64 : vsetcc_type; -+def vsetult_v16i8 : vsetcc_type; -+def vsetult_v8i16 : vsetcc_type; -+def vsetult_v4i32 : vsetcc_type; -+def vsetult_v2i64 : vsetcc_type; -+ -+def vsplati8 : PatFrag<(ops node:$e0), -+ (v16i8 (build_vector node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0))>; -+def vsplati16 : PatFrag<(ops node:$e0), -+ (v8i16 (build_vector node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0, -+ node:$e0, node:$e0))>; -+def vsplati32 : PatFrag<(ops node:$e0), -+ (v4i32 (build_vector node:$e0, node:$e0, -+ node:$e0, node:$e0))>; -+ -+def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ -+ APInt Imm; -+ SDNode *BV = N->getOperand(0).getNode(); -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -+}]>; -+ -+def vsplati64 : PatFrag<(ops node:$e0), -+ (v2i64 (build_vector node:$e0, node:$e0))>; -+ -+def vsplati64_splat_d : PatFrag<(ops node:$e0), -+ (v2i64 (bitconvert -+ (v4i32 (and -+ (v4i32 (build_vector node:$e0, -+ node:$e0, -+ node:$e0, -+ node:$e0)), -+ vsplati64_imm_eq_1))))>; -+ -+def vsplatf32 : PatFrag<(ops node:$e0), -+ (v4f32 (build_vector node:$e0, node:$e0, -+ node:$e0, node:$e0))>; -+def vsplatf64 : PatFrag<(ops node:$e0), -+ (v2f64 (build_vector node:$e0, node:$e0))>; -+ -+def vsplati8_elt : PatFrag<(ops node:$v, node:$i), -+ (LoongArchVSHF (vsplati8 node:$i), node:$v, node:$v)>; -+def vsplati16_elt : PatFrag<(ops node:$v, node:$i), -+ (LoongArchVSHF (vsplati16 node:$i), node:$v, node:$v)>; -+def vsplati32_elt : PatFrag<(ops node:$v, node:$i), -+ (LoongArchVSHF (vsplati32 node:$i), node:$v, node:$v)>; -+def vsplati64_elt : PatFrag<(ops node:$v, node:$i), -+ (LoongArchVSHF (vsplati64_splat_d node:$i),node:$v, node:$v)>; -+ -+class SplatPatLeaf -+ : PatLeaf { -+ Operand OpClass = opclass; -+} -+ -+class SplatComplexPattern roots = [], -+ list props = []> : -+ ComplexPattern { -+ Operand OpClass = opclass; -+} -+ -+def vsplati8_uimm3 : SplatComplexPattern; -+ -+def vsplati8_uimm4 : SplatComplexPattern; -+ -+def vsplati8_uimm5 : SplatComplexPattern; -+ -+def vsplati8_uimm8 : SplatComplexPattern; -+ -+def vsplati8_simm5 : SplatComplexPattern; -+ -+def vsplati16_uimm3 : SplatComplexPattern; -+ -+def vsplati16_uimm4 : SplatComplexPattern; -+ -+def vsplati16_uimm5 : SplatComplexPattern; -+ -+def vsplati16_simm5 : SplatComplexPattern; -+ -+def vsplati32_uimm2 : SplatComplexPattern; -+ -+def vsplati32_uimm5 : SplatComplexPattern; -+ -+def vsplati32_simm5 : SplatComplexPattern; -+ -+def vsplati64_uimm1 : SplatComplexPattern; -+ -+def vsplati64_uimm5 : SplatComplexPattern; -+ -+def vsplati64_uimm6 : SplatComplexPattern; -+ -+def vsplati64_simm5 : SplatComplexPattern; -+ -+ -+// Any build_vector that is a constant splat with a value that equals 1 -+// FIXME: These should be a ComplexPattern but we can't use them because the -+// ISel generator requires the uses to have a name, but providing a name -+// causes other errors ("used in pattern but not operand list") -+def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{ -+ APInt Imm; -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ return selectVSplat(N, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -+}]>; -+ -+def vbitclr_b : PatFrag<(ops node:$vj, node:$vk), -+ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), -+ immAllOnesV))>; -+def vbitclr_h : PatFrag<(ops node:$vj, node:$vk), -+ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), -+ immAllOnesV))>; -+def vbitclr_w : PatFrag<(ops node:$vj, node:$vk), -+ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), -+ immAllOnesV))>; -+def vbitclr_d : PatFrag<(ops node:$vj, node:$vk), -+ (and node:$vj, (xor (shl (v2i64 vsplati64_imm_eq_1), -+ node:$vk), -+ (bitconvert (v4i32 immAllOnesV))))>; -+ -+def vbneg_b : PatFrag<(ops node:$vj, node:$vk), -+ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbneg_h : PatFrag<(ops node:$vj, node:$vk), -+ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbneg_w : PatFrag<(ops node:$vj, node:$vk), -+ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbneg_d : PatFrag<(ops node:$vj, node:$vk), -+ (xor node:$vj, (shl (v2i64 vsplati64_imm_eq_1), -+ node:$vk))>; -+ -+def vbset_b : PatFrag<(ops node:$vj, node:$vk), -+ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbset_h : PatFrag<(ops node:$vj, node:$vk), -+ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbset_w : PatFrag<(ops node:$vj, node:$vk), -+ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; -+def vbset_d : PatFrag<(ops node:$vj, node:$vk), -+ (or node:$vj, (shl (v2i64 vsplati64_imm_eq_1), -+ node:$vk))>; -+ -+def muladd : PatFrag<(ops node:$vd, node:$vj, node:$vk), -+ (add node:$vd, (mul node:$vj, node:$vk))>; -+ -+def mulsub : PatFrag<(ops node:$vd, node:$vj, node:$vk), -+ (sub node:$vd, (mul node:$vj, node:$vk))>; -+ -+class IsCommutable { -+ bit isCommutable = 1; -+} -+ -+ -+ -+//class -+class LSX_3R_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; -+} -+ -+class LSX_3RN_DESC_BASE : -+ LSX_3R_DESC_BASE; -+ -+class LSX_3R_4R_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, -+ ROVK:$vk))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_3R_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, GPR32Opnd:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $rk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, GPR32Opnd:$rk))]; -+} -+ -+class LSX_VEC_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; -+} -+ -+class LSX_VEC_PSEUDO_BASE : -+ LSXPseudo<(outs ROVD:$vd), (ins ROVJ:$vj, ROVK:$vk), -+ [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]>; -+ -+class LSX_3RF_DESC_BASE : -+ LSX_3R_DESC_BASE; -+ -+class LSX_3RFN_DESC_BASE : -+ LSX_3R_DESC_BASE; -+ -+class LSX_3R_DESC_BASE1 { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vk, ROVK:$vj))]; -+} -+ -+class LSX_3RF_DESC_BASE1 : -+ LSX_3R_DESC_BASE1; -+ -+class LSX_3R_VSHF_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF ROVD:$vd_in, ROVJ:$vj, -+ ROVK:$vk))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_3R_4R_VSHF_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVD:$va); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF ROVD:$va, ROVJ:$vj, -+ ROVK:$vk))]; -+} -+ -+class LSX_I5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $si5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$si5))]; -+} -+ -+class LSX_I5_U_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui5))]; -+} -+ -+class LSX_BIT_3_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui3))]; -+} -+ -+class LSX_BIT_3N_DESC_BASE : -+ LSX_BIT_3_DESC_BASE; -+ -+class LSX_BIT_4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui4))]; -+} -+ -+class LSX_BIT_4N_DESC_BASE : -+ LSX_BIT_4_DESC_BASE; -+ -+class LSX_BIT_5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui5))]; -+} -+ -+class LSX_BIT_5N_DESC_BASE : -+ LSX_BIT_5_DESC_BASE; -+ -+class LSX_BIT_6_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui6))]; -+} -+ -+class LSX_BIT_6N_DESC_BASE : -+ LSX_BIT_6_DESC_BASE; -+ -+class LSX_2R_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; -+} -+ -+class LSX_2RN_DESC_BASE : -+ LSX_2R_DESC_BASE; -+ -+class LSX_2RF_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; -+} -+ -+class LSX_2RFN_DESC_BASE : -+ LSX_2R_DESC_BASE; -+ -+class LSX_2RF_DESC_BASE_CVT { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; -+} -+ -+class LSX_2RFN_DESC_BASE_CVT : -+ LSX_2RF_DESC_BASE_CVT; -+ -+class LSX_2RF_DESC_BASE_tmp { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); -+ list Pattern = []; -+} -+ -+class LSX_2R_REPL_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROS:$rj); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj"); -+ list Pattern = [(set ROVD:$vd, (VT (OpNode ROS:$rj)))]; -+} -+ -+class LSX_INSERT_U4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$rj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$rj, Imm:$ui4))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_INSERT_U4N_DESC_BASE : -+ LSX_INSERT_U4_DESC_BASE; -+ -+class LSX_INSERT_U3_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui3))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_INSERT_U3N_DESC_BASE : -+ LSX_INSERT_U3_DESC_BASE; -+ -+class LSX_INSERT_U2_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui2"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui2))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_INSERT_U2N_DESC_BASE : -+ LSX_INSERT_U2_DESC_BASE; -+ -+class LSX_INSERT_U1_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui1); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui1"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui1))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_INSERT_U1N_DESC_BASE : -+ LSX_INSERT_U1_DESC_BASE; -+ -+class LSX_PICK_U1_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui1); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui1"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui1))]; -+} -+ -+class LSX_PICK_U2_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui2"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui2))]; -+} -+ -+class LSX_PICK_U3_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui3"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui3))]; -+} -+ -+class LSX_PICK_U4_DESC_BASE { -+ dag OutOperandList = (outs ROD:$rd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui4"); -+ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui4))]; -+} -+ -+class LSX_ELM_U3_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui3, ROVJ:$vj, -+ ROVJ:$vj))]; -+} -+ -+class LSX_ELM_U2_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui2"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui2, ROVJ:$vj, -+ ROVJ:$vj))]; -+} -+ -+class LSX_ELM_U1_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui1); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui1"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui1, ROVJ:$vj, -+ ROVJ:$vj))]; -+} -+ -+class LSX_ELM_U4_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui4, ROVJ:$vj, -+ ROVJ:$vj))]; -+} -+ -+class LSX_ELM_U4_SLD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, -+ Imm:$ui4))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_ELM_U3_SLD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, -+ Imm:$ui3))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_ELM_U2_SLD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui2); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui2"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, -+ Imm:$ui2))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_ELM_U1_SLD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui1); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui1"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, -+ Imm:$ui1))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_BIT_U3_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui3))]; -+} -+ -+class LSX_BIT_U4_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui4))]; -+} -+ -+class LSX_BIT_U5_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui5))]; -+} -+ -+class LSX_BIT_U6_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui6))]; -+} -+ -+class LSX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm6:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt6:$ui6))]; -+} -+ -+class LSX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm3:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt3:$ui3))]; -+} -+ -+class LSX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt4:$ui4))]; -+} -+ -+class LSX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; -+} -+ -+class LSX_I8_SHF_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (LoongArchSHF immZExt8:$ui8, ROVJ:$vj))]; -+} -+ -+class LSX_I8_SHUF_DESC_BASE_D { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt8:$ui8))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+def LoongArchSelect : SDNode<"LoongArchISD::VSELECT" ,SDTSelect>; -+def LoongArchVROR : SDNode<"LoongArchISD::VROR", -+ SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, -+ SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]>, []>; -+def LoongArchVRORI : SDNode<"LoongArchISD::VRORI", -+ SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, -+ SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>, []>; -+ -+class LSX2_RORI_U3_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui3))]; -+} -+ -+class LSX2_RORI_U4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui4))]; -+} -+ -+class LSX2_RORI_U5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui5))]; -+} -+ -+class LSX2_RORI_U6_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui6))]; -+} -+ -+class LSX_BIND_U4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui4))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_BIND_U4N_DESC_BASE : -+ LSX_BIND_U4_DESC_BASE; -+ -+class LSX_BIND_U5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui5))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_BIND_U5N_DESC_BASE : -+ LSX_BIND_U5_DESC_BASE; -+ -+class LSX_BIND_U6_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui6))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_BIND_U6N_DESC_BASE : -+ LSX_BIND_U6_DESC_BASE; -+ -+class LSX_BIND_U7_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm7:$ui7); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui7"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt7:$ui7))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_BIND_U7N_DESC_BASE : -+ LSX_BIND_U7_DESC_BASE; -+ -+ -+class LD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); -+ list Pattern = [(set ROVD:$vd, (TyNode (OpNode Addr:$addr)))]; -+ string DecoderMethod = "DecodeLSX128Mem"; -+} -+ -+class ST_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); -+ list Pattern = [(OpNode (TyNode ROVD:$vd), Addr:$addr)]; -+ string DecoderMethod = "DecodeLSX128Mem"; -+} -+ -+class LSX_VEC_ADDR_PSEUDO_BASE : -+ LSXPseudo<(outs), (ins ROVD:$vd, MemOpnd:$addr), -+ [(OpNode (TyNode ROVD:$vd), MemOpnd:$addr)]>; -+ -+ -+class LSX_SET_DESC_BASE { -+ dag OutOperandList = (outs FCFROpnd:$cd); -+ dag InOperandList = (ins ROVD:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$cd, $vj"); -+ list Pattern = []; -+} -+ -+class LSX_SET_DESC_BASE_tmp { -+ dag OutOperandList = (outs FCFROpnd:$cd); -+ dag InOperandList = (ins ROVD:$vj); -+ string AsmString = !strconcat(instr_asm, "\t$cd, $vj"); -+ list Pattern = []; -+} -+ -+class LSX_VMul_Reg4 { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVA:$va); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk, ROVA:$va))]; -+} -+ -+class LSX_4RF { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVA:$va); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk, ROVA:$va))]; -+} -+ -+ -+class LSX_VFCMP_Reg3 { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; -+} -+ -+class LSX_I12_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si12); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si12"); -+ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si12))]; -+} -+ -+class LSX_I11_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si11); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si11"); -+ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si11))]; -+} -+ -+class LSX_I10_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si10); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si10"); -+ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si10))]; -+} -+ -+class LSX_I9_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si9); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si9"); -+ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si9))]; -+} -+ -+ -+class LSX_I8_U1_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm1:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt1:$idx)]; -+ string DecoderMethod = "DecodeLSX128memstl"; -+} -+ -+ -+class LSX_I8_U2_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm2:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt2:$idx)]; -+ string DecoderMethod = "DecodeLSX128memstl"; -+} -+ -+class LSX_I8_U3_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm3:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt3:$idx)]; -+ string DecoderMethod = "DecodeLSX128memstl"; -+} -+ -+class LSX_I8_U4_DESC_BASE { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm4:$idx); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); -+ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt4:$idx)]; -+ string DecoderMethod = "DecodeLSX128memstl"; -+} -+ -+class LSX_I5_U_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui5))]; -+} -+ -+class LSX_I5_DESC_BASE_Intrinsic { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, ImmOp:$si5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $si5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$si5))]; -+} -+ -+class LSX_LDX_LA { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins PtrRC:$rj, RORK:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk"); -+ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, RORK:$rk))]; -+} -+ -+class LSX_SDX_LA { -+ dag OutOperandList = (outs); -+ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, RORK:$rk); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk"); -+ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, RORK:$rk)]; -+} -+ -+class LSX_U5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; -+} -+ -+class LSX_U5_4R_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt5:$ui5))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_U3_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm3:$ui3); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt3:$ui3))]; -+} -+ -+class LSX_2R_U4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt4:$ui4))]; -+} -+ -+class LSX_2R_U5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; -+} -+ -+class LSX_2R_U6_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm6:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt6:$ui6))]; -+} -+ -+class LSX_2R_3R_U4_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm4:$ui4); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt4:$ui4))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_3R_U5_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm5:$ui5); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt5:$ui5))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_3R_U6_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm6:$ui6); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt6:$ui6))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_3R_U7_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm7:$ui7); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui7"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt7:$ui7))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_3R_U8_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt8:$ui8))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_3R_SELECT { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, vsplat_uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, vsplati8_uimm8:$ui8, ROVJ:$vj))]; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class LSX_2R_U8_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, uimm8:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt8:$ui8))]; -+} -+ -+class LSX_I13_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins immOp:$i13); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $i13"); -+ list Pattern = [(set ROVD:$vd, (OpNode (Ty simm13:$i13)))]; -+ string DecoderMethod = "DecodeLSX128Mem13"; -+} -+ -+class LSX_I13_DESC_BASE_10 { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ImmOp:$i10); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $i10"); -+ list Pattern = [(set ROVD:$vd, (OpNode Imm:$i10))]; -+ bit hasSideEffects = 0; -+ string DecoderMethod = "DecodeLSX128Mem10"; -+} -+ -+class LSX_BIT_U8_VREPLVE_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui8); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); -+ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui8))]; -+} -+ -+ -+class LSXPat pred = [HasLSX]> : -+ Pat, Requires; -+ -+// Instruction encoding. -+ -+ -+def VSADD_B : LSX_3R<0b01110000010001100>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.b", LSX128BOpnd>; -+ -+def VSADD_H : LSX_3R<0b01110000010001101>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.h", LSX128HOpnd>; -+ -+def VSADD_W : LSX_3R<0b01110000010001110>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.w", LSX128WOpnd>; -+ -+def VSADD_D : LSX_3R<0b01110000010001111>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.d", LSX128DOpnd>; -+ -+ -+def VSSUB_B : LSX_3R<0b01110000010010000>, -+ LSX_3RN_DESC_BASE<"vssub.b", LSX128BOpnd>; -+ -+def VSSUB_H : LSX_3R<0b01110000010010001>, -+ LSX_3RN_DESC_BASE<"vssub.h", LSX128HOpnd>; -+ -+def VSSUB_W : LSX_3R<0b01110000010010010>, -+ LSX_3RN_DESC_BASE<"vssub.w", LSX128WOpnd>; -+ -+def VSSUB_D : LSX_3R<0b01110000010010011>, -+ LSX_3RN_DESC_BASE<"vssub.d", LSX128DOpnd>; -+ -+ -+def VSADD_BU : LSX_3R<0b01110000010010100>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.bu", LSX128BOpnd>; -+ -+def VSADD_HU : LSX_3R<0b01110000010010101>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.hu", LSX128HOpnd>; -+ -+def VSADD_WU : LSX_3R<0b01110000010010110>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.wu", LSX128WOpnd>; -+ -+def VSADD_DU : LSX_3R<0b01110000010010111>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vsadd.du", LSX128DOpnd>; -+ -+ -+def VSSUB_BU : LSX_3R<0b01110000010011000>, -+ LSX_3RN_DESC_BASE<"vssub.bu", LSX128BOpnd>; -+ -+def VSSUB_HU : LSX_3R<0b01110000010011001>, -+ LSX_3RN_DESC_BASE<"vssub.hu", LSX128HOpnd>; -+ -+def VSSUB_WU : LSX_3R<0b01110000010011010>, -+ LSX_3RN_DESC_BASE<"vssub.wu", LSX128WOpnd>; -+ -+def VSSUB_DU : LSX_3R<0b01110000010011011>, -+ LSX_3RN_DESC_BASE<"vssub.du", LSX128DOpnd>; -+ -+ -+def VHADDW_H_B : LSX_3R<0b01110000010101000>, -+ LSX_3RN_DESC_BASE<"vhaddw.h.b", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VHADDW_W_H : LSX_3R<0b01110000010101001>, -+ LSX_3RN_DESC_BASE<"vhaddw.w.h", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VHADDW_D_W : LSX_3R<0b01110000010101010>, -+ LSX_3RN_DESC_BASE<"vhaddw.d.w", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+ -+def VHSUBW_H_B : LSX_3R<0b01110000010101100>, -+ LSX_3RN_DESC_BASE<"vhsubw.h.b", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VHSUBW_W_H : LSX_3R<0b01110000010101101>, -+ LSX_3RN_DESC_BASE<"vhsubw.w.h", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VHSUBW_D_W : LSX_3R<0b01110000010101110>, -+ LSX_3RN_DESC_BASE<"vhsubw.d.w", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+ -+def VHADDW_HU_BU : LSX_3R<0b01110000010110000>, -+ LSX_3RN_DESC_BASE<"vhaddw.hu.bu", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VHADDW_WU_HU : LSX_3R<0b01110000010110001>, -+ LSX_3RN_DESC_BASE<"vhaddw.wu.hu", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VHADDW_DU_WU : LSX_3R<0b01110000010110010>, -+ LSX_3RN_DESC_BASE<"vhaddw.du.wu", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+ -+def VHSUBW_HU_BU : LSX_3R<0b01110000010110100>, -+ LSX_3RN_DESC_BASE<"vhsubw.hu.bu", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VHSUBW_WU_HU : LSX_3R<0b01110000010110101>, -+ LSX_3RN_DESC_BASE<"vhsubw.wu.hu", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VHSUBW_DU_WU : LSX_3R<0b01110000010110110>, -+ LSX_3RN_DESC_BASE<"vhsubw.du.wu", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+ -+def VADDA_B : LSX_3R<0b01110000010111000>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vadda.b", LSX128BOpnd>; -+ -+def VADDA_H : LSX_3R<0b01110000010111001>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vadda.h", LSX128HOpnd>; -+ -+def VADDA_W : LSX_3R<0b01110000010111010>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vadda.w", LSX128WOpnd>; -+ -+def VADDA_D : LSX_3R<0b01110000010111011>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vadda.d", LSX128DOpnd>; -+ -+ -+def VABSD_B : LSX_3R<0b01110000011000000>, -+ LSX_3RN_DESC_BASE<"vabsd.b", LSX128BOpnd>; -+ -+def VABSD_H : LSX_3R<0b01110000011000001>, -+ LSX_3RN_DESC_BASE<"vabsd.h", LSX128HOpnd>; -+ -+def VABSD_W : LSX_3R<0b01110000011000010>, -+ LSX_3RN_DESC_BASE<"vabsd.w", LSX128WOpnd>; -+ -+def VABSD_D : LSX_3R<0b01110000011000011>, -+ LSX_3RN_DESC_BASE<"vabsd.d", LSX128DOpnd>; -+ -+ -+def VABSD_BU : LSX_3R<0b01110000011000100>, -+ LSX_3RN_DESC_BASE<"vabsd.bu", LSX128BOpnd>; -+ -+def VABSD_HU : LSX_3R<0b01110000011000101>, -+ LSX_3RN_DESC_BASE<"vabsd.hu", LSX128HOpnd>; -+ -+def VABSD_WU : LSX_3R<0b01110000011000110>, -+ LSX_3RN_DESC_BASE<"vabsd.wu", LSX128WOpnd>; -+ -+def VABSD_DU : LSX_3R<0b01110000011000111>, -+ LSX_3RN_DESC_BASE<"vabsd.du", LSX128DOpnd>; -+ -+ -+def VAVG_B : LSX_3R<0b01110000011001000>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.b", LSX128BOpnd>; -+ -+def VAVG_H : LSX_3R<0b01110000011001001>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.h", LSX128HOpnd>; -+ -+def VAVG_W : LSX_3R<0b01110000011001010>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.w", LSX128WOpnd>; -+ -+def VAVG_D : LSX_3R<0b01110000011001011>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.d", LSX128DOpnd>; -+ -+ -+def VAVG_BU : LSX_3R<0b01110000011001100>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.bu", LSX128BOpnd>; -+ -+def VAVG_HU : LSX_3R<0b01110000011001101>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.hu", LSX128HOpnd>; -+ -+def VAVG_WU : LSX_3R<0b01110000011001110>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.wu", LSX128WOpnd>; -+ -+def VAVG_DU : LSX_3R<0b01110000011001111>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavg.du", LSX128DOpnd>; -+ -+ -+def VAVGR_B : LSX_3R<0b01110000011010000>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.b", LSX128BOpnd>; -+ -+def VAVGR_H : LSX_3R<0b01110000011010001>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.h", LSX128HOpnd>; -+ -+def VAVGR_W : LSX_3R<0b01110000011010010>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.w", LSX128WOpnd>; -+ -+def VAVGR_D : LSX_3R<0b01110000011010011>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.d", LSX128DOpnd>; -+ -+ -+def VAVGR_BU : LSX_3R<0b01110000011010100>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.bu", LSX128BOpnd>; -+ -+def VAVGR_HU : LSX_3R<0b01110000011010101>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.hu", LSX128HOpnd>; -+ -+def VAVGR_WU : LSX_3R<0b01110000011010110>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.wu", LSX128WOpnd>; -+ -+def VAVGR_DU : LSX_3R<0b01110000011010111>, IsCommutable, -+ LSX_3RN_DESC_BASE<"vavgr.du", LSX128DOpnd>; -+ -+ -+def VMAX_B : LSX_3R<0b01110000011100000>, -+ LSX_3R_DESC_BASE<"vmax.b", smax, LSX128BOpnd>; -+ -+def VMAX_H : LSX_3R<0b01110000011100001>, -+ LSX_3R_DESC_BASE<"vmax.h", smax, LSX128HOpnd>; -+ -+def VMAX_W : LSX_3R<0b01110000011100010>, -+ LSX_3R_DESC_BASE<"vmax.w", smax, LSX128WOpnd>; -+ -+def VMAX_D : LSX_3R<0b01110000011100011>, -+ LSX_3R_DESC_BASE<"vmax.d", smax, LSX128DOpnd>; -+ -+ -+def VMIN_B : LSX_3R<0b01110000011100100>, -+ LSX_3R_DESC_BASE<"vmin.b", smin, LSX128BOpnd>; -+ -+def VMIN_H : LSX_3R<0b01110000011100101>, -+ LSX_3R_DESC_BASE<"vmin.h", smin, LSX128HOpnd>; -+ -+def VMIN_W : LSX_3R<0b01110000011100110>, -+ LSX_3R_DESC_BASE<"vmin.w", smin, LSX128WOpnd>; -+ -+def VMIN_D : LSX_3R<0b01110000011100111>, -+ LSX_3R_DESC_BASE<"vmin.d", smin, LSX128DOpnd>; -+ -+ -+def VMAX_BU : LSX_3R<0b01110000011101000>, -+ LSX_3R_DESC_BASE<"vmax.bu", umax, LSX128BOpnd>; -+ -+def VMAX_HU : LSX_3R<0b01110000011101001>, -+ LSX_3R_DESC_BASE<"vmax.hu", umax, LSX128HOpnd>; -+ -+def VMAX_WU : LSX_3R<0b01110000011101010>, -+ LSX_3R_DESC_BASE<"vmax.wu", umax, LSX128WOpnd>; -+ -+def VMAX_DU : LSX_3R<0b01110000011101011>, -+ LSX_3R_DESC_BASE<"vmax.du", umax, LSX128DOpnd>; -+ -+ -+def VMIN_BU : LSX_3R<0b01110000011101100>, -+ LSX_3R_DESC_BASE<"vmin.bu", umin, LSX128BOpnd>; -+ -+def VMIN_HU : LSX_3R<0b01110000011101101>, -+ LSX_3R_DESC_BASE<"vmin.hu", umin, LSX128HOpnd>; -+ -+def VMIN_WU : LSX_3R<0b01110000011101110>, -+ LSX_3R_DESC_BASE<"vmin.wu", umin, LSX128WOpnd>; -+ -+def VMIN_DU : LSX_3R<0b01110000011101111>, -+ LSX_3R_DESC_BASE<"vmin.du", umin, LSX128DOpnd>; -+ -+ -+def VMUL_B : LSX_3R<0b01110000100001000>, -+ LSX_3R_DESC_BASE<"vmul.b", mul, LSX128BOpnd>; -+ -+def VMUL_H : LSX_3R<0b01110000100001001>, -+ LSX_3R_DESC_BASE<"vmul.h", mul, LSX128HOpnd>; -+ -+def VMUL_W : LSX_3R<0b01110000100001010>, -+ LSX_3R_DESC_BASE<"vmul.w", mul, LSX128WOpnd>; -+ -+def VMUL_D : LSX_3R<0b01110000100001011>, -+ LSX_3R_DESC_BASE<"vmul.d", mul, LSX128DOpnd>; -+ -+ -+def VMADD_B : LSX_3R<0b01110000101010000>, -+ LSX_3R_4R_DESC_BASE<"vmadd.b", muladd, LSX128BOpnd>; -+ -+def VMADD_H : LSX_3R<0b01110000101010001>, -+ LSX_3R_4R_DESC_BASE<"vmadd.h", muladd, LSX128HOpnd>; -+ -+def VMADD_W : LSX_3R<0b01110000101010010>, -+ LSX_3R_4R_DESC_BASE<"vmadd.w", muladd, LSX128WOpnd>; -+ -+def VMADD_D : LSX_3R<0b01110000101010011>, -+ LSX_3R_4R_DESC_BASE<"vmadd.d", muladd, LSX128DOpnd>; -+ -+ -+def VMSUB_B : LSX_3R<0b01110000101010100>, -+ LSX_3R_4R_DESC_BASE<"vmsub.b", mulsub, LSX128BOpnd>; -+ -+def VMSUB_H : LSX_3R<0b01110000101010101>, -+ LSX_3R_4R_DESC_BASE<"vmsub.h", mulsub, LSX128HOpnd>; -+ -+def VMSUB_W : LSX_3R<0b01110000101010110>, -+ LSX_3R_4R_DESC_BASE<"vmsub.w", mulsub, LSX128WOpnd>; -+ -+def VMSUB_D : LSX_3R<0b01110000101010111>, -+ LSX_3R_4R_DESC_BASE<"vmsub.d", mulsub, LSX128DOpnd>; -+ -+ -+def VDIV_B : LSX_3R<0b01110000111000000>, -+ LSX_3R_DESC_BASE<"vdiv.b", sdiv, LSX128BOpnd>; -+ -+def VDIV_H : LSX_3R<0b01110000111000001>, -+ LSX_3R_DESC_BASE<"vdiv.h", sdiv, LSX128HOpnd>; -+ -+def VDIV_W : LSX_3R<0b01110000111000010>, -+ LSX_3R_DESC_BASE<"vdiv.w", sdiv, LSX128WOpnd>; -+ -+def VDIV_D : LSX_3R<0b01110000111000011>, -+ LSX_3R_DESC_BASE<"vdiv.d", sdiv, LSX128DOpnd>; -+ -+ -+def VMOD_B : LSX_3R<0b01110000111000100>, -+ LSX_3R_DESC_BASE<"vmod.b", srem, LSX128BOpnd>; -+ -+def VMOD_H : LSX_3R<0b01110000111000101>, -+ LSX_3R_DESC_BASE<"vmod.h", srem, LSX128HOpnd>; -+ -+def VMOD_W : LSX_3R<0b01110000111000110>, -+ LSX_3R_DESC_BASE<"vmod.w", srem, LSX128WOpnd>; -+ -+def VMOD_D : LSX_3R<0b01110000111000111>, -+ LSX_3R_DESC_BASE<"vmod.d", srem, LSX128DOpnd>; -+ -+ -+def VDIV_BU : LSX_3R<0b01110000111001000>, -+ LSX_3R_DESC_BASE<"vdiv.bu", udiv, LSX128BOpnd>; -+ -+def VDIV_HU : LSX_3R<0b01110000111001001>, -+ LSX_3R_DESC_BASE<"vdiv.hu", udiv, LSX128HOpnd>; -+ -+def VDIV_WU : LSX_3R<0b01110000111001010>, -+ LSX_3R_DESC_BASE<"vdiv.wu", udiv, LSX128WOpnd>; -+ -+def VDIV_DU : LSX_3R<0b01110000111001011>, -+ LSX_3R_DESC_BASE<"vdiv.du", udiv, LSX128DOpnd>; -+ -+ -+def VMOD_BU : LSX_3R<0b01110000111001100>, -+ LSX_3R_DESC_BASE<"vmod.bu", urem, LSX128BOpnd>; -+ -+def VMOD_HU : LSX_3R<0b01110000111001101>, -+ LSX_3R_DESC_BASE<"vmod.hu", urem, LSX128HOpnd>; -+ -+def VMOD_WU : LSX_3R<0b01110000111001110>, -+ LSX_3R_DESC_BASE<"vmod.wu", urem, LSX128WOpnd>; -+ -+def VMOD_DU : LSX_3R<0b01110000111001111>, -+ LSX_3R_DESC_BASE<"vmod.du", urem, LSX128DOpnd>; -+ -+ -+def VSLL_B : LSX_3R<0b01110000111010000>, -+ LSX_3R_DESC_BASE<"vsll.b", shl, LSX128BOpnd>; -+ -+def VSLL_H : LSX_3R<0b01110000111010001>, -+ LSX_3R_DESC_BASE<"vsll.h", shl, LSX128HOpnd>; -+ -+def VSLL_W : LSX_3R<0b01110000111010010>, -+ LSX_3R_DESC_BASE<"vsll.w", shl, LSX128WOpnd>; -+ -+def VSLL_D : LSX_3R<0b01110000111010011>, -+ LSX_3R_DESC_BASE<"vsll.d", shl, LSX128DOpnd>; -+ -+ -+def VSRL_B : LSX_3R<0b01110000111010100>, -+ LSX_3R_DESC_BASE<"vsrl.b", srl, LSX128BOpnd>; -+ -+def VSRL_H : LSX_3R<0b01110000111010101>, -+ LSX_3R_DESC_BASE<"vsrl.h", srl, LSX128HOpnd>; -+ -+def VSRL_W : LSX_3R<0b01110000111010110>, -+ LSX_3R_DESC_BASE<"vsrl.w", srl, LSX128WOpnd>; -+ -+def VSRL_D : LSX_3R<0b01110000111010111>, -+ LSX_3R_DESC_BASE<"vsrl.d", srl, LSX128DOpnd>; -+ -+ -+def VSRA_B : LSX_3R<0b01110000111011000>, -+ LSX_3R_DESC_BASE<"vsra.b", sra, LSX128BOpnd>; -+ -+def VSRA_H : LSX_3R<0b01110000111011001>, -+ LSX_3R_DESC_BASE<"vsra.h", sra, LSX128HOpnd>; -+ -+def VSRA_W : LSX_3R<0b01110000111011010>, -+ LSX_3R_DESC_BASE<"vsra.w", sra, LSX128WOpnd>; -+ -+def VSRA_D : LSX_3R<0b01110000111011011>, -+ LSX_3R_DESC_BASE<"vsra.d", sra, LSX128DOpnd>; -+ -+ -+def VSRLR_B : LSX_3R<0b01110000111100000>, -+ LSX_3RN_DESC_BASE<"vsrlr.b", LSX128BOpnd>; -+ -+def VSRLR_H : LSX_3R<0b01110000111100001>, -+ LSX_3RN_DESC_BASE<"vsrlr.h", LSX128HOpnd>; -+ -+def VSRLR_W : LSX_3R<0b01110000111100010>, -+ LSX_3RN_DESC_BASE<"vsrlr.w", LSX128WOpnd>; -+ -+def VSRLR_D : LSX_3R<0b01110000111100011>, -+ LSX_3RN_DESC_BASE<"vsrlr.d", LSX128DOpnd>; -+ -+ -+def VSRAR_B : LSX_3R<0b01110000111100100>, -+ LSX_3RN_DESC_BASE<"vsrar.b", LSX128BOpnd>; -+ -+def VSRAR_H : LSX_3R<0b01110000111100101>, -+ LSX_3RN_DESC_BASE<"vsrar.h", LSX128HOpnd>; -+ -+def VSRAR_W : LSX_3R<0b01110000111100110>, -+ LSX_3RN_DESC_BASE<"vsrar.w", LSX128WOpnd>; -+ -+def VSRAR_D : LSX_3R<0b01110000111100111>, -+ LSX_3RN_DESC_BASE<"vsrar.d", LSX128DOpnd>; -+ -+ -+def VBITCLR_B : LSX_3R<0b01110001000011000>, -+ LSX_3R_DESC_BASE<"vbitclr.b", vbitclr_b, LSX128BOpnd>; -+ -+def VBITCLR_H : LSX_3R<0b01110001000011001>, -+ LSX_3R_DESC_BASE<"vbitclr.h", vbitclr_h, LSX128HOpnd>; -+ -+def VBITCLR_W : LSX_3R<0b01110001000011010>, -+ LSX_3R_DESC_BASE<"vbitclr.w", vbitclr_w, LSX128WOpnd>; -+ -+def VBITCLR_D : LSX_3R<0b01110001000011011>, -+ LSX_3R_DESC_BASE<"vbitclr.d", vbitclr_d, LSX128DOpnd>; -+ -+ -+def VBITSET_B : LSX_3R<0b01110001000011100>, -+ LSX_3RN_DESC_BASE<"vbitset.b", LSX128BOpnd>; -+ -+def VBITSET_H : LSX_3R<0b01110001000011101>, -+ LSX_3RN_DESC_BASE<"vbitset.h", LSX128HOpnd>; -+ -+def VBITSET_W : LSX_3R<0b01110001000011110>, -+ LSX_3RN_DESC_BASE<"vbitset.w", LSX128WOpnd>; -+ -+def VBITSET_D : LSX_3R<0b01110001000011111>, -+ LSX_3RN_DESC_BASE<"vbitset.d", LSX128DOpnd>; -+ -+ -+def VBITREV_B : LSX_3R<0b01110001000100000>, -+ LSX_3RN_DESC_BASE<"vbitrev.b", LSX128BOpnd>; -+ -+def VBITREV_H : LSX_3R<0b01110001000100001>, -+ LSX_3RN_DESC_BASE<"vbitrev.h", LSX128HOpnd>; -+ -+def VBITREV_W : LSX_3R<0b01110001000100010>, -+ LSX_3RN_DESC_BASE<"vbitrev.w", LSX128WOpnd>; -+ -+def VBITREV_D : LSX_3R<0b01110001000100011>, -+ LSX_3RN_DESC_BASE<"vbitrev.d", LSX128DOpnd>; -+ -+ -+def VPACKEV_B : LSX_3R<0b01110001000101100>, -+ LSX_3R_DESC_BASE<"vpackev.b", LoongArchVPACKEV, LSX128BOpnd>; -+ -+def VPACKEV_H : LSX_3R<0b01110001000101101>, -+ LSX_3R_DESC_BASE<"vpackev.h", LoongArchVPACKEV, LSX128HOpnd>; -+ -+def VPACKEV_W : LSX_3R<0b01110001000101110>, -+ LSX_3R_DESC_BASE<"vpackev.w", LoongArchVPACKEV, LSX128WOpnd>; -+ -+def VPACKEV_D : LSX_3R<0b01110001000101111>, -+ LSX_3R_DESC_BASE<"vpackev.d", LoongArchVPACKEV, LSX128DOpnd>; -+ -+ -+def VPACKOD_B : LSX_3R<0b01110001000110000>, -+ LSX_3R_DESC_BASE<"vpackod.b", LoongArchVPACKOD, LSX128BOpnd>; -+ -+def VPACKOD_H : LSX_3R<0b01110001000110001>, -+ LSX_3R_DESC_BASE<"vpackod.h", LoongArchVPACKOD, LSX128HOpnd>; -+ -+def VPACKOD_W : LSX_3R<0b01110001000110010>, -+ LSX_3R_DESC_BASE<"vpackod.w", LoongArchVPACKOD, LSX128WOpnd>; -+ -+def VPACKOD_D : LSX_3R<0b01110001000110011>, -+ LSX_3R_DESC_BASE<"vpackod.d", LoongArchVPACKOD, LSX128DOpnd>; -+ -+ -+def VILVL_B : LSX_3R<0b01110001000110100>, -+ LSX_3R_DESC_BASE<"vilvl.b", LoongArchVILVL, LSX128BOpnd>; -+ -+def VILVL_H : LSX_3R<0b01110001000110101>, -+ LSX_3R_DESC_BASE<"vilvl.h", LoongArchVILVL, LSX128HOpnd>; -+ -+def VILVL_W : LSX_3R<0b01110001000110110>, -+ LSX_3R_DESC_BASE<"vilvl.w", LoongArchVILVL, LSX128WOpnd>; -+ -+def VILVL_D : LSX_3R<0b01110001000110111>, -+ LSX_3R_DESC_BASE<"vilvl.d", LoongArchVILVL, LSX128DOpnd>; -+ -+ -+def VILVH_B : LSX_3R<0b01110001000111000>, -+ LSX_3R_DESC_BASE<"vilvh.b", LoongArchVILVH, LSX128BOpnd>; -+ -+def VILVH_H : LSX_3R<0b01110001000111001>, -+ LSX_3R_DESC_BASE<"vilvh.h", LoongArchVILVH, LSX128HOpnd>; -+ -+def VILVH_W : LSX_3R<0b01110001000111010>, -+ LSX_3R_DESC_BASE<"vilvh.w", LoongArchVILVH, LSX128WOpnd>; -+ -+def VILVH_D : LSX_3R<0b01110001000111011>, -+ LSX_3R_DESC_BASE<"vilvh.d", LoongArchVILVH, LSX128DOpnd>; -+ -+ -+def VPICKEV_B : LSX_3R<0b01110001000111100>, -+ LSX_3R_DESC_BASE<"vpickev.b", LoongArchVPICKEV, LSX128BOpnd>; -+ -+def VPICKEV_H : LSX_3R<0b01110001000111101>, -+ LSX_3R_DESC_BASE<"vpickev.h", LoongArchVPICKEV, LSX128HOpnd>; -+ -+def VPICKEV_W : LSX_3R<0b01110001000111110>, -+ LSX_3R_DESC_BASE<"vpickev.w", LoongArchVPICKEV, LSX128WOpnd>; -+ -+def VPICKEV_D : LSX_3R<0b01110001000111111>, -+ LSX_3R_DESC_BASE<"vpickev.d", LoongArchVPICKEV, LSX128DOpnd>; -+ -+ -+def VPICKOD_B : LSX_3R<0b01110001001000000>, -+ LSX_3R_DESC_BASE<"vpickod.b", LoongArchVPICKOD, LSX128BOpnd>; -+ -+def VPICKOD_H : LSX_3R<0b01110001001000001>, -+ LSX_3R_DESC_BASE<"vpickod.h", LoongArchVPICKOD, LSX128HOpnd>; -+ -+def VPICKOD_W : LSX_3R<0b01110001001000010>, -+ LSX_3R_DESC_BASE<"vpickod.w", LoongArchVPICKOD, LSX128WOpnd>; -+ -+def VPICKOD_D : LSX_3R<0b01110001001000011>, -+ LSX_3R_DESC_BASE<"vpickod.d", LoongArchVPICKOD, LSX128DOpnd>; -+ -+ -+def VREPLVE_B : LSX_3R_1GP<0b01110001001000100>, -+ LSX_3R_VREPLVE_DESC_BASE<"vreplve.b", vsplati8_elt, LSX128BOpnd>; -+ -+def VREPLVE_H : LSX_3R_1GP<0b01110001001000101>, -+ LSX_3R_VREPLVE_DESC_BASE<"vreplve.h", vsplati16_elt, LSX128HOpnd>; -+ -+def VREPLVE_W : LSX_3R_1GP<0b01110001001000110>, -+ LSX_3R_VREPLVE_DESC_BASE<"vreplve.w", vsplati32_elt, LSX128WOpnd>; -+ -+def VREPLVE_D : LSX_3R_1GP<0b01110001001000111>, -+ LSX_3R_VREPLVE_DESC_BASE<"vreplve.d", vsplati64_elt, LSX128DOpnd>; -+ -+ -+def VAND_V : LSX_3R<0b01110001001001100>, -+ LSX_VEC_DESC_BASE<"vand.v", and, LSX128BOpnd>; -+class AND_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class AND_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class AND_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+ -+def AND_V_H_PSEUDO : AND_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def AND_V_W_PSEUDO : AND_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def AND_V_D_PSEUDO : AND_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+ -+def VOR_V : LSX_3R<0b01110001001001101>, -+ LSX_VEC_DESC_BASE<"vor.v", or, LSX128BOpnd>; -+class OR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class OR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class OR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+ -+def OR_V_H_PSEUDO : OR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def OR_V_W_PSEUDO : OR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def OR_V_D_PSEUDO : OR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+ -+def VXOR_V : LSX_3R<0b01110001001001110>, -+ LSX_VEC_DESC_BASE<"vxor.v", xor, LSX128BOpnd>; -+class XOR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class XOR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class XOR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+ -+def XOR_V_H_PSEUDO : XOR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def XOR_V_W_PSEUDO : XOR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def XOR_V_D_PSEUDO : XOR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+ -+def VNOR_V : LSX_3R<0b01110001001001111>, -+ LSX_VEC_DESC_BASE<"vnor.v", LoongArchVNOR, LSX128BOpnd>; -+class NOR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class NOR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+class NOR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; -+ -+def NOR_V_H_PSEUDO : NOR_V_H_PSEUDO_DESC, -+ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def NOR_V_W_PSEUDO : NOR_V_W_PSEUDO_DESC, -+ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+def NOR_V_D_PSEUDO : NOR_V_D_PSEUDO_DESC, -+ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+ -+def VFADD_S : LSX_3R<0b01110001001100001>, IsCommutable, -+ LSX_3RF_DESC_BASE<"vfadd.s", fadd, LSX128WOpnd>; -+ -+def VFADD_D : LSX_3R<0b01110001001100010>, IsCommutable, -+ LSX_3RF_DESC_BASE<"vfadd.d", fadd, LSX128DOpnd>; -+ -+ -+def VFSUB_S : LSX_3R<0b01110001001100101>, -+ LSX_3RF_DESC_BASE<"vfsub.s", fsub, LSX128WOpnd>; -+ -+def VFSUB_D : LSX_3R<0b01110001001100110>, -+ LSX_3RF_DESC_BASE<"vfsub.d", fsub, LSX128DOpnd>; -+ -+ -+def VFMUL_S : LSX_3R<0b01110001001110001>, -+ LSX_3RF_DESC_BASE<"vfmul.s", fmul, LSX128WOpnd>; -+ -+def VFMUL_D : LSX_3R<0b01110001001110010>, -+ LSX_3RF_DESC_BASE<"vfmul.d", fmul, LSX128DOpnd>; -+ -+ -+def VFDIV_S : LSX_3R<0b01110001001110101>, -+ LSX_3RF_DESC_BASE<"vfdiv.s", fdiv, LSX128WOpnd>; -+ -+def VFDIV_D : LSX_3R<0b01110001001110110>, -+ LSX_3RF_DESC_BASE<"vfdiv.d", fdiv, LSX128DOpnd>; -+ -+ -+def VFMAX_S : LSX_3R<0b01110001001111001>, -+ LSX_3RFN_DESC_BASE<"vfmax.s", LSX128WOpnd>; -+ -+def VFMAX_D : LSX_3R<0b01110001001111010>, -+ LSX_3RFN_DESC_BASE<"vfmax.d", LSX128DOpnd>; -+ -+ -+def VFMIN_S : LSX_3R<0b01110001001111101>, -+ LSX_3RFN_DESC_BASE<"vfmin.s", LSX128WOpnd>; -+ -+def VFMIN_D : LSX_3R<0b01110001001111110>, -+ LSX_3RFN_DESC_BASE<"vfmin.d", LSX128DOpnd>; -+ -+ -+def VFMAXA_S : LSX_3R<0b01110001010000001>, -+ LSX_3RFN_DESC_BASE<"vfmaxa.s", LSX128WOpnd>; -+ -+def VFMAXA_D : LSX_3R<0b01110001010000010>, -+ LSX_3RFN_DESC_BASE<"vfmaxa.d", LSX128DOpnd>; -+ -+ -+def VFMINA_S : LSX_3R<0b01110001010000101>, -+ LSX_3RFN_DESC_BASE<"vfmina.s", LSX128WOpnd>; -+ -+def VFMINA_D : LSX_3R<0b01110001010000110>, -+ LSX_3RFN_DESC_BASE<"vfmina.d", LSX128DOpnd>; -+ -+ -+def VSHUF_H : LSX_3R<0b01110001011110101>, -+ LSX_3R_VSHF_DESC_BASE<"vshuf.h", LSX128HOpnd>; -+ -+def VSHUF_W : LSX_3R<0b01110001011110110>, -+ LSX_3R_VSHF_DESC_BASE<"vshuf.w", LSX128WOpnd>; -+ -+def VSHUF_D : LSX_3R<0b01110001011110111>, -+ LSX_3R_VSHF_DESC_BASE<"vshuf.d", LSX128DOpnd>; -+ -+ -+def VSEQI_B : LSX_I5<0b01110010100000000>, -+ LSX_I5_DESC_BASE_Intrinsic<"vseqi.b", int_loongarch_lsx_vseqi_b, simm5_32, immSExt5, LSX128BOpnd>; -+ -+def VSEQI_H : LSX_I5<0b01110010100000001>, -+ LSX_I5_DESC_BASE_Intrinsic<"vseqi.h", int_loongarch_lsx_vseqi_h, simm5_32, immSExt5, LSX128HOpnd>; -+ -+def VSEQI_W : LSX_I5<0b01110010100000010>, -+ LSX_I5_DESC_BASE_Intrinsic<"vseqi.w", int_loongarch_lsx_vseqi_w, simm5_32, immSExt5, LSX128WOpnd>; -+ -+def VSEQI_D : LSX_I5<0b01110010100000011>, -+ LSX_I5_DESC_BASE_Intrinsic<"vseqi.d", int_loongarch_lsx_vseqi_d, simm5_32, immSExt5, LSX128DOpnd>; -+ -+ -+def VSLEI_B : LSX_I5<0b01110010100000100>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslei.b", int_loongarch_lsx_vslei_b, simm5_32, immSExt5, LSX128BOpnd>; -+ -+def VSLEI_H : LSX_I5<0b01110010100000101>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslei.h", int_loongarch_lsx_vslei_h, simm5_32, immSExt5, LSX128HOpnd>; -+ -+def VSLEI_W : LSX_I5<0b01110010100000110>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslei.w", int_loongarch_lsx_vslei_w, simm5_32, immSExt5, LSX128WOpnd>; -+ -+def VSLEI_D : LSX_I5<0b01110010100000111>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslei.d", int_loongarch_lsx_vslei_d, simm5_32, immSExt5, LSX128DOpnd>; -+ -+ -+def VSLEI_BU : LSX_I5_U<0b01110010100001000>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.bu", int_loongarch_lsx_vslei_bu, uimm5, immZExt5, LSX128BOpnd>; -+ -+def VSLEI_HU : LSX_I5_U<0b01110010100001001>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.hu", int_loongarch_lsx_vslei_hu, uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSLEI_WU : LSX_I5_U<0b01110010100001010>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.wu", int_loongarch_lsx_vslei_wu, uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSLEI_DU : LSX_I5_U<0b01110010100001011>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.du", int_loongarch_lsx_vslei_du, uimm5, immZExt5, LSX128DOpnd>; -+ -+ -+def VSLTI_B : LSX_I5<0b01110010100001100>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslti.b", int_loongarch_lsx_vslti_b, simm5_32, immSExt5, LSX128BOpnd>; -+ -+def VSLTI_H : LSX_I5<0b01110010100001101>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslti.h", int_loongarch_lsx_vslti_h, simm5_32, immSExt5, LSX128HOpnd>; -+ -+def VSLTI_W : LSX_I5<0b01110010100001110>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslti.w", int_loongarch_lsx_vslti_w, simm5_32, immSExt5, LSX128WOpnd>; -+ -+def VSLTI_D : LSX_I5<0b01110010100001111>, -+ LSX_I5_DESC_BASE_Intrinsic<"vslti.d", int_loongarch_lsx_vslti_d, simm5_32, immSExt5, LSX128DOpnd>; -+ -+ -+def VSLTI_BU : LSX_I5_U<0b01110010100010000>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.bu", int_loongarch_lsx_vslti_bu, uimm5, immZExt5, LSX128BOpnd>; -+ -+def VSLTI_HU : LSX_I5_U<0b01110010100010001>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.hu", int_loongarch_lsx_vslti_hu, uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSLTI_WU : LSX_I5_U<0b01110010100010010>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.wu", int_loongarch_lsx_vslti_wu, uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSLTI_DU : LSX_I5_U<0b01110010100010011>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.du", int_loongarch_lsx_vslti_du, uimm5, immZExt5, LSX128DOpnd>; -+ -+ -+def VADDI_BU : LSX_I5_U<0b01110010100010100>, -+ LSX_I5_U_DESC_BASE<"vaddi.bu", add, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VADDI_HU : LSX_I5_U<0b01110010100010101>, -+ LSX_I5_U_DESC_BASE<"vaddi.hu", add, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VADDI_WU : LSX_I5_U<0b01110010100010110>, -+ LSX_I5_U_DESC_BASE<"vaddi.wu", add, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VADDI_DU : LSX_I5_U<0b01110010100010111>, -+ LSX_I5_U_DESC_BASE<"vaddi.du", add, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VSUBI_BU : LSX_I5_U<0b01110010100011000>, -+ LSX_I5_U_DESC_BASE<"vsubi.bu", sub, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VSUBI_HU : LSX_I5_U<0b01110010100011001>, -+ LSX_I5_U_DESC_BASE<"vsubi.hu", sub, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VSUBI_WU : LSX_I5_U<0b01110010100011010>, -+ LSX_I5_U_DESC_BASE<"vsubi.wu", sub, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSUBI_DU : LSX_I5_U<0b01110010100011011>, -+ LSX_I5_U_DESC_BASE<"vsubi.du", sub, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VMAXI_B : LSX_I5<0b01110010100100000>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.b", int_loongarch_lsx_vmaxi_b, simm5_32, immSExt5, LSX128BOpnd>; -+ -+def VMAXI_H : LSX_I5<0b01110010100100001>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.h", int_loongarch_lsx_vmaxi_h, simm5_32, immSExt5, LSX128HOpnd>; -+ -+def VMAXI_W : LSX_I5<0b01110010100100010>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.w", int_loongarch_lsx_vmaxi_w, simm5_32, immSExt5, LSX128WOpnd>; -+ -+def VMAXI_D : LSX_I5<0b01110010100100011>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.d", int_loongarch_lsx_vmaxi_d, simm5_32, immSExt5, LSX128DOpnd>; -+ -+ -+def VMINI_B : LSX_I5<0b01110010100100100>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmini.b", int_loongarch_lsx_vmini_b, simm5_32, immSExt5, LSX128BOpnd>; -+ -+def VMINI_H : LSX_I5<0b01110010100100101>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmini.h", int_loongarch_lsx_vmini_h, simm5_32, immSExt5, LSX128HOpnd>; -+ -+def VMINI_W : LSX_I5<0b01110010100100110>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmini.w", int_loongarch_lsx_vmini_w, simm5_32, immSExt5, LSX128WOpnd>; -+ -+def VMINI_D : LSX_I5<0b01110010100100111>, -+ LSX_I5_DESC_BASE_Intrinsic<"vmini.d", int_loongarch_lsx_vmini_d, simm5_32, immSExt5, LSX128DOpnd>; -+ -+ -+def VMAXI_BU : LSX_I5_U<0b01110010100101000>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.bu", int_loongarch_lsx_vmaxi_bu, uimm5, immZExt5, LSX128BOpnd>; -+ -+def VMAXI_HU : LSX_I5_U<0b01110010100101001>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.hu", int_loongarch_lsx_vmaxi_hu, uimm5, immZExt5, LSX128HOpnd>; -+ -+def VMAXI_WU : LSX_I5_U<0b01110010100101010>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.wu", int_loongarch_lsx_vmaxi_wu, uimm5, immZExt5, LSX128WOpnd>; -+ -+def VMAXI_DU : LSX_I5_U<0b01110010100101011>, -+ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.du", int_loongarch_lsx_vmaxi_du, uimm5, immZExt5, LSX128DOpnd>; -+ -+ -+def VMINI_BU : LSX_I5_U<0b01110010100101100>, -+ LSX_I5_U_DESC_BASE<"vmini.bu", umin, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VMINI_HU : LSX_I5_U<0b01110010100101101>, -+ LSX_I5_U_DESC_BASE<"vmini.hu", umin, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VMINI_WU : LSX_I5_U<0b01110010100101110>, -+ LSX_I5_U_DESC_BASE<"vmini.wu", umin, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VMINI_DU : LSX_I5_U<0b01110010100101111>, -+ LSX_I5_U_DESC_BASE<"vmini.du", umin, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VCLO_B : LSX_2R<0b0111001010011100000000>, -+ LSX_2RN_DESC_BASE<"vclo.b", LSX128BOpnd>; -+ -+def VCLO_H : LSX_2R<0b0111001010011100000001>, -+ LSX_2RN_DESC_BASE<"vclo.h", LSX128HOpnd>; -+ -+def VCLO_W : LSX_2R<0b0111001010011100000010>, -+ LSX_2RN_DESC_BASE<"vclo.w", LSX128WOpnd>; -+ -+def VCLO_D : LSX_2R<0b0111001010011100000011>, -+ LSX_2RN_DESC_BASE<"vclo.d", LSX128DOpnd>; -+ -+ -+def VCLZ_B : LSX_2R<0b0111001010011100000100>, -+ LSX_2R_DESC_BASE<"vclz.b", ctlz, LSX128BOpnd>; -+ -+def VCLZ_H : LSX_2R<0b0111001010011100000101>, -+ LSX_2R_DESC_BASE<"vclz.h", ctlz, LSX128HOpnd>; -+ -+def VCLZ_W : LSX_2R<0b0111001010011100000110>, -+ LSX_2R_DESC_BASE<"vclz.w", ctlz, LSX128WOpnd>; -+ -+def VCLZ_D : LSX_2R<0b0111001010011100000111>, -+ LSX_2R_DESC_BASE<"vclz.d", ctlz, LSX128DOpnd>; -+ -+ -+def VPCNT_B : LSX_2R<0b0111001010011100001000>, -+ LSX_2R_DESC_BASE<"vpcnt.b", ctpop, LSX128BOpnd>; -+ -+def VPCNT_H : LSX_2R<0b0111001010011100001001>, -+ LSX_2R_DESC_BASE<"vpcnt.h", ctpop, LSX128HOpnd>; -+ -+def VPCNT_W : LSX_2R<0b0111001010011100001010>, -+ LSX_2R_DESC_BASE<"vpcnt.w", ctpop, LSX128WOpnd>; -+ -+def VPCNT_D : LSX_2R<0b0111001010011100001011>, -+ LSX_2R_DESC_BASE<"vpcnt.d", ctpop, LSX128DOpnd>; -+ -+ -+def VFLOGB_S : LSX_2R<0b0111001010011100110001>, -+ LSX_2RFN_DESC_BASE<"vflogb.s", LSX128WOpnd>; -+ -+def VFLOGB_D : LSX_2R<0b0111001010011100110010>, -+ LSX_2RFN_DESC_BASE<"vflogb.d", LSX128DOpnd>; -+ -+ -+def VFCLASS_S : LSX_2R<0b0111001010011100110101>, -+ LSX_2RFN_DESC_BASE<"vfclass.s", LSX128WOpnd>; -+ -+def VFCLASS_D : LSX_2R<0b0111001010011100110110>, -+ LSX_2RFN_DESC_BASE<"vfclass.d", LSX128DOpnd>; -+ -+ -+def VFSQRT_S : LSX_2R<0b0111001010011100111001>, -+ LSX_2RF_DESC_BASE<"vfsqrt.s", fsqrt, LSX128WOpnd>; -+ -+def VFSQRT_D : LSX_2R<0b0111001010011100111010>, -+ LSX_2RF_DESC_BASE<"vfsqrt.d", fsqrt, LSX128DOpnd>; -+ -+ -+def VFRECIP_S : LSX_2R<0b0111001010011100111101>, -+ LSX_2RFN_DESC_BASE<"vfrecip.s", LSX128WOpnd>; -+ -+def VFRECIP_D : LSX_2R<0b0111001010011100111110>, -+ LSX_2RFN_DESC_BASE<"vfrecip.d", LSX128DOpnd>; -+ -+ -+def VFRSQRT_S : LSX_2R<0b0111001010011101000001>, -+ LSX_2RFN_DESC_BASE<"vfrsqrt.s", LSX128WOpnd>; -+ -+def VFRSQRT_D : LSX_2R<0b0111001010011101000010>, -+ LSX_2RFN_DESC_BASE<"vfrsqrt.d", LSX128DOpnd>; -+ -+ -+def VFRINT_S : LSX_2R<0b0111001010011101001101>, -+ LSX_2RF_DESC_BASE<"vfrint.s", frint, LSX128WOpnd>; -+ -+def VFRINT_D : LSX_2R<0b0111001010011101001110>, -+ LSX_2RF_DESC_BASE<"vfrint.d", frint, LSX128DOpnd>; -+ -+ -+def VFCVTL_S_H : LSX_2R<0b0111001010011101111010>, -+ LSX_2RFN_DESC_BASE_CVT<"vfcvtl.s.h", LSX128WOpnd, LSX128HOpnd>; -+ -+def VFCVTH_S_H : LSX_2R<0b0111001010011101111011>, -+ LSX_2RFN_DESC_BASE_CVT<"vfcvth.s.h", LSX128WOpnd, LSX128HOpnd>; -+ -+ -+def VFCVTL_D_S : LSX_2R<0b0111001010011101111100>, -+ LSX_2RFN_DESC_BASE_CVT<"vfcvtl.d.s", LSX128DOpnd, LSX128WOpnd>; -+ -+def VFCVTH_D_S : LSX_2R<0b0111001010011101111101>, -+ LSX_2RFN_DESC_BASE_CVT<"vfcvth.d.s", LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFFINT_S_W : LSX_2R<0b0111001010011110000000>, -+ LSX_2RF_DESC_BASE<"vffint.s.w", sint_to_fp, LSX128WOpnd>; -+ -+def VFFINT_S_WU : LSX_2R<0b0111001010011110000001>, -+ LSX_2RF_DESC_BASE<"vffint.s.wu", uint_to_fp, LSX128WOpnd>; -+ -+ -+def VFFINT_D_L : LSX_2R<0b0111001010011110000010>, -+ LSX_2RF_DESC_BASE<"vffint.d.l", sint_to_fp, LSX128DOpnd>; -+ -+def VFFINT_D_LU : LSX_2R<0b0111001010011110000011>, -+ LSX_2RF_DESC_BASE<"vffint.d.lu", uint_to_fp, LSX128DOpnd>; -+ -+ -+def VFTINT_W_S : LSX_2R<0b0111001010011110001100>, -+ LSX_2RFN_DESC_BASE<"vftint.w.s", LSX128WOpnd>; -+ -+def VFTINT_L_D : LSX_2R<0b0111001010011110001101>, -+ LSX_2RFN_DESC_BASE<"vftint.l.d", LSX128DOpnd>; -+ -+ -+def VFTINT_WU_S : LSX_2R<0b0111001010011110010110>, -+ LSX_2RFN_DESC_BASE<"vftint.wu.s", LSX128WOpnd>; -+ -+def VFTINT_LU_D : LSX_2R<0b0111001010011110010111>, -+ LSX_2RFN_DESC_BASE<"vftint.lu.d", LSX128DOpnd>; -+ -+ -+def VFTINTRZ_WU_S : LSX_2R<0b0111001010011110011100>, -+ LSX_2RF_DESC_BASE<"vftintrz.wu.s", fp_to_uint, LSX128WOpnd>; -+ -+def VFTINTRZ_LU_D : LSX_2R<0b0111001010011110011101>, -+ LSX_2RF_DESC_BASE<"vftintrz.lu.d", fp_to_uint, LSX128DOpnd>; -+ -+ -+def VREPLGR2VR_B : LSX_2R_1GP<0b0111001010011111000000>, -+ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.b", v16i8, vsplati8, LSX128BOpnd, GPR32Opnd>; -+ -+def VREPLGR2VR_H : LSX_2R_1GP<0b0111001010011111000001>, -+ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.h", v8i16, vsplati16, LSX128HOpnd, GPR32Opnd>; -+ -+def VREPLGR2VR_W : LSX_2R_1GP<0b0111001010011111000010>, -+ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.w", v4i32, vsplati32, LSX128WOpnd, GPR32Opnd>; -+ -+def VREPLGR2VR_D : LSX_2R_1GP<0b0111001010011111000011>, -+ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.d", v2i64, vsplati64, LSX128DOpnd, GPR64Opnd>; -+ -+ -+class LSX_2R_FILL_PSEUDO_BASE : -+ LSXPseudo<(outs RCVD:$vd), (ins RCVS:$fs), -+ [(set RCVD:$vd, (OpNode RCVS:$fs))]> { -+ let usesCustomInserter = 1; -+} -+ -+class FILL_FW_PSEUDO_DESC : LSX_2R_FILL_PSEUDO_BASE; -+class FILL_FD_PSEUDO_DESC : LSX_2R_FILL_PSEUDO_BASE; -+ -+def FILL_FW_PSEUDO : FILL_FW_PSEUDO_DESC; -+def FILL_FD_PSEUDO : FILL_FD_PSEUDO_DESC; -+ -+ -+def VSRLRI_B : LSX_I3_U<0b0111001010100100001>, -+ LSX_BIT_3N_DESC_BASE<"vsrlri.b", uimm3, immZExt3, LSX128BOpnd>; -+ -+def VSRLRI_H : LSX_I4_U<0b011100101010010001>, -+ LSX_BIT_4N_DESC_BASE<"vsrlri.h", uimm4, immZExt4, LSX128HOpnd>; -+ -+def VSRLRI_W : LSX_I5_U<0b01110010101001001>, -+ LSX_BIT_5N_DESC_BASE<"vsrlri.w", uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSRLRI_D : LSX_I6_U<0b0111001010100101>, -+ LSX_BIT_6N_DESC_BASE<"vsrlri.d", uimm6, immZExt6, LSX128DOpnd>; -+ -+ -+def VSRARI_B : LSX_I3_U<0b0111001010101000001>, -+ LSX_BIT_3N_DESC_BASE<"vsrari.b", uimm3, immZExt3, LSX128BOpnd>; -+ -+def VSRARI_H : LSX_I4_U<0b011100101010100001>, -+ LSX_BIT_4N_DESC_BASE<"vsrari.h", uimm4, immZExt4, LSX128HOpnd>; -+ -+def VSRARI_W : LSX_I5_U<0b01110010101010001>, -+ LSX_BIT_5N_DESC_BASE<"vsrari.w", uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSRARI_D : LSX_I6_U<0b0111001010101001>, -+ LSX_BIT_6N_DESC_BASE<"vsrari.d", uimm6, immZExt6, LSX128DOpnd>; -+ -+ -+def VINSGR2VR_B : LSX_I4_R_U<0b011100101110101110>, -+ LSX_INSERT_U4_DESC_BASE<"vinsgr2vr.b", vinsert_v16i8, uimm4, immZExt4Ptr, LSX128BOpnd, GPR32Opnd>; -+ -+def VINSGR2VR_H : LSX_I3_R_U<0b0111001011101011110>, -+ LSX_INSERT_U3_DESC_BASE<"vinsgr2vr.h", vinsert_v8i16, uimm3, immZExt3Ptr, LSX128HOpnd, GPR32Opnd>; -+ -+def VINSGR2VR_W : LSX_I2_R_U<0b01110010111010111110>, -+ LSX_INSERT_U2_DESC_BASE<"vinsgr2vr.w", vinsert_v4i32, uimm2, immZExt2Ptr, LSX128WOpnd, GPR32Opnd>; -+ -+def VINSGR2VR_D : LSX_I1_R_U<0b011100101110101111110>, -+ LSX_INSERT_U1_DESC_BASE<"vinsgr2vr.d", vinsert_v2i64, uimm1, immZExt1Ptr, LSX128DOpnd, GPR64Opnd>; -+ -+ -+def VPICKVE2GR_B : LSX_ELM_COPY_B<0b011100101110111110>, -+ LSX_PICK_U4_DESC_BASE<"vpickve2gr.b", vextract_sext_i8, v16i8, uimm4_ptr, immZExt4Ptr, GPR32Opnd, LSX128BOpnd>; -+ -+def VPICKVE2GR_H : LSX_ELM_COPY_H<0b0111001011101111110>, -+ LSX_PICK_U3_DESC_BASE<"vpickve2gr.h", vextract_sext_i16, v8i16, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LSX128HOpnd>; -+ -+def VPICKVE2GR_W : LSX_ELM_COPY_W<0b01110010111011111110>, -+ LSX_PICK_U2_DESC_BASE<"vpickve2gr.w", vextract_sext_i32, v4i32, uimm2_ptr, immZExt2Ptr, GPR32Opnd, LSX128WOpnd>; -+ -+def VPICKVE2GR_D : LSX_ELM_COPY_D<0b011100101110111111110>, -+ LSX_PICK_U1_DESC_BASE<"vpickve2gr.d", vextract_sext_i64, v2i64, uimm1_ptr, immZExt1Ptr, GPR64Opnd, LSX128DOpnd>; -+ -+ -+def VPICKVE2GR_BU : LSX_ELM_COPY_B<0b011100101111001110>, -+ LSX_PICK_U4_DESC_BASE<"vpickve2gr.bu", vextract_zext_i8, v16i8, uimm4_ptr, immZExt4Ptr, GPR32Opnd, LSX128BOpnd>; -+ -+def VPICKVE2GR_HU : LSX_ELM_COPY_H<0b0111001011110011110>, -+ LSX_PICK_U3_DESC_BASE<"vpickve2gr.hu", vextract_zext_i16, v8i16, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LSX128HOpnd>; -+ -+def VPICKVE2GR_WU : LSX_ELM_COPY_W<0b01110010111100111110>, -+ LSX_PICK_U2_DESC_BASE<"vpickve2gr.wu", vextract_zext_i32, v4i32, uimm2_ptr, immZExt2Ptr, GPR32Opnd, LSX128WOpnd>; -+ -+def VPICKVE2GR_DU : LSX_ELM_COPY_D<0b011100101111001111110>, -+ LSX_PICK_U1_DESC_BASE<"vpickve2gr.du", int_loongarch_lsx_vpickve2gr_du, v2i64, uimm1, immZExt1, GPR64Opnd, LSX128DOpnd>; -+ -+ -+def : LSXPat<(vextract_zext_i64 (v2i64 LSX128D:$vj), immZExt1Ptr:$idx), -+ (VPICKVE2GR_D LSX128D:$vj, immZExt1:$idx)>; -+def : LSXPat<(vextract_zext_i64 (v2f64 LSX128D:$vj), immZExt1Ptr:$idx), -+ (VPICKVE2GR_D LSX128D:$vj, immZExt1:$idx)>; -+ -+ -+def VREPLVEI_B : LSX_I4_U<0b011100101111011110>, -+ LSX_ELM_U4_VREPLVE_DESC_BASE<"vreplvei.b", vsplati8_uimm4, LSX128BOpnd>; -+ -+def VREPLVEI_H : LSX_I3_U<0b0111001011110111110>, -+ LSX_ELM_U3_VREPLVE_DESC_BASE<"vreplvei.h", vsplati16_uimm3, LSX128HOpnd>; -+ -+def VREPLVEI_W : LSX_I2_U<0b01110010111101111110>, -+ LSX_ELM_U2_VREPLVE_DESC_BASE<"vreplvei.w", vsplati32_uimm2, LSX128WOpnd>; -+ -+def VREPLVEI_D : LSX_I1_U<0b011100101111011111110>, -+ LSX_ELM_U1_VREPLVE_DESC_BASE<"vreplvei.d", vsplati64_uimm1, LSX128DOpnd>; -+ -+ -+def VSAT_B : LSX_I3_U<0b0111001100100100001>, -+ LSX_BIT_3N_DESC_BASE<"vsat.b", uimm3, immZExt3, LSX128BOpnd>; -+ -+def VSAT_H : LSX_I4_U<0b011100110010010001>, -+ LSX_BIT_4N_DESC_BASE<"vsat.h", uimm4, immZExt4, LSX128HOpnd>; -+ -+def VSAT_W : LSX_I5_U<0b01110011001001001>, -+ LSX_BIT_5N_DESC_BASE<"vsat.w", uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSAT_D : LSX_I6_U<0b0111001100100101>, -+ LSX_BIT_6N_DESC_BASE<"vsat.d", uimm6, immZExt6, LSX128DOpnd>; -+ -+ -+def VSAT_BU : LSX_I3_U<0b0111001100101000001>, -+ LSX_BIT_3N_DESC_BASE<"vsat.bu", uimm3, immZExt3, LSX128BOpnd>; -+ -+def VSAT_HU : LSX_I4_U<0b011100110010100001>, -+ LSX_BIT_4N_DESC_BASE<"vsat.hu", uimm4, immZExt4, LSX128HOpnd>; -+ -+def VSAT_WU : LSX_I5_U<0b01110011001010001>, -+ LSX_BIT_5N_DESC_BASE<"vsat.wu", uimm5, immZExt5, LSX128WOpnd>; -+ -+def VSAT_DU : LSX_I6_U<0b0111001100101001>, -+ LSX_BIT_6N_DESC_BASE<"vsat.du", uimm6, immZExt6, LSX128DOpnd>; -+ -+ -+def VSLLI_B : LSX_I3_U<0b0111001100101100001>, -+ LSX_BIT_U3_VREPLVE_DESC_BASE<"vslli.b", shl, vsplati8_uimm3, LSX128BOpnd>; -+ -+def VSLLI_H : LSX_I4_U<0b011100110010110001>, -+ LSX_BIT_U4_VREPLVE_DESC_BASE<"vslli.h", shl, vsplati16_uimm4, LSX128HOpnd>; -+ -+def VSLLI_W : LSX_I5_U<0b01110011001011001>, -+ LSX_BIT_U5_VREPLVE_DESC_BASE<"vslli.w", shl, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSLLI_D : LSX_I6_U<0b0111001100101101>, -+ LSX_BIT_U6_VREPLVE_DESC_BASE<"vslli.d", shl, vsplati64_uimm6, LSX128DOpnd>; -+ -+ -+def VSRLI_B : LSX_I3_U<0b0111001100110000001>, -+ LSX_BIT_U3_VREPLVE_DESC_BASE<"vsrli.b", srl, vsplati8_uimm3, LSX128BOpnd>; -+ -+def VSRLI_H : LSX_I4_U<0b011100110011000001>, -+ LSX_BIT_U4_VREPLVE_DESC_BASE<"vsrli.h", srl, vsplati16_uimm4, LSX128HOpnd>; -+ -+def VSRLI_W : LSX_I5_U<0b01110011001100001>, -+ LSX_BIT_U5_VREPLVE_DESC_BASE<"vsrli.w", srl, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSRLI_D : LSX_I6_U<0b0111001100110001>, -+ LSX_BIT_U6_VREPLVE_DESC_BASE<"vsrli.d", srl, vsplati64_uimm6, LSX128DOpnd>; -+ -+ -+def VSRAI_B : LSX_I3_U<0b0111001100110100001>, -+ LSX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"vsrai.b", int_loongarch_lsx_vsrai_b, LSX128BOpnd>; -+ -+def VSRAI_H : LSX_I4_U<0b011100110011010001>, -+ LSX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"vsrai.h", int_loongarch_lsx_vsrai_h, LSX128HOpnd>; -+ -+def VSRAI_W : LSX_I5_U<0b01110011001101001>, -+ LSX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"vsrai.w", int_loongarch_lsx_vsrai_w, LSX128WOpnd>; -+ -+def VSRAI_D : LSX_I6_U<0b0111001100110101>, -+ LSX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"vsrai.d", int_loongarch_lsx_vsrai_d, LSX128DOpnd>; -+ -+ -+def VSHUF4I_B : LSX_I8_U<0b01110011100100>, -+ LSX_I8_SHF_DESC_BASE<"vshuf4i.b", LSX128BOpnd>; -+ -+def VSHUF4I_H : LSX_I8_U<0b01110011100101>, -+ LSX_I8_SHF_DESC_BASE<"vshuf4i.h", LSX128HOpnd>; -+ -+def VSHUF4I_W : LSX_I8_U<0b01110011100110>, -+ LSX_I8_SHF_DESC_BASE<"vshuf4i.w", LSX128WOpnd>; -+ -+def VSHUF4I_D : LSX_I8_U<0b01110011100111>, -+ LSX_I8_SHUF_DESC_BASE_D<"vshuf4i.d", int_loongarch_lsx_vshuf4i_d, LSX128DOpnd>; -+ -+ -+def VROTR_B : LSX_3R<0b01110000111011100>, -+ LSX_3R_DESC_BASE<"vrotr.b", LoongArchVROR, LSX128BOpnd>; -+ -+def VROTR_H : LSX_3R<0b01110000111011101>, -+ LSX_3R_DESC_BASE<"vrotr.h", LoongArchVROR, LSX128HOpnd>; -+ -+def VROTR_W : LSX_3R<0b01110000111011110>, -+ LSX_3R_DESC_BASE<"vrotr.w", LoongArchVROR, LSX128WOpnd>; -+ -+def VROTR_D : LSX_3R<0b01110000111011111>, -+ LSX_3R_DESC_BASE<"vrotr.d", LoongArchVROR, LSX128DOpnd>; -+ -+ -+def VMSKLTZ_B : LSX_2R<0b0111001010011100010000>, -+ LSX_2RN_DESC_BASE<"vmskltz.b", LSX128BOpnd>; -+ -+def VMSKLTZ_H : LSX_2R<0b0111001010011100010001>, -+ LSX_2RN_DESC_BASE<"vmskltz.h", LSX128HOpnd>; -+ -+def VMSKLTZ_W : LSX_2R<0b0111001010011100010010>, -+ LSX_2RN_DESC_BASE<"vmskltz.w", LSX128WOpnd>; -+ -+def VMSKLTZ_D : LSX_2R<0b0111001010011100010011>, -+ LSX_2RN_DESC_BASE<"vmskltz.d", LSX128DOpnd>; -+ -+ -+def VROTRI_B : LSX_I3_U<0b0111001010100000001>, -+ LSX2_RORI_U3_DESC_BASE<"vrotri.b", uimm3, immZExt3, LSX128BOpnd>; -+ -+def VROTRI_H : LSX_I4_U<0b011100101010000001>, -+ LSX2_RORI_U4_DESC_BASE<"vrotri.h", uimm4, immZExt4, LSX128HOpnd>; -+ -+def VROTRI_W : LSX_I5_U<0b01110010101000001>, -+ LSX2_RORI_U5_DESC_BASE<"vrotri.w", uimm5, immZExt5, LSX128WOpnd>; -+ -+def VROTRI_D : LSX_I6_U<0b0111001010100001>, -+ LSX2_RORI_U6_DESC_BASE<"vrotri.d", uimm6, immZExt6, LSX128DOpnd>; -+ -+ -+def VSRLNI_B_H : LSX_I4_U<0b011100110100000001>, -+ LSX_BIND_U4N_DESC_BASE<"vsrlni.b.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSRLNI_H_W : LSX_I5_U<0b01110011010000001>, -+ LSX_BIND_U5N_DESC_BASE<"vsrlni.h.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSRLNI_W_D : LSX_I6_U<0b0111001101000001>, -+ LSX_BIND_U6N_DESC_BASE<"vsrlni.w.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSRLNI_D_Q : LSX_I7_U<0b011100110100001>, -+ LSX_BIND_U7N_DESC_BASE<"vsrlni.d.q", LSX128DOpnd>; -+ -+ -+def VSRLRNI_B_H : LSX_I4_U<0b011100110100010001>, -+ LSX_BIND_U4_DESC_BASE<"vsrlrni.b.h", int_loongarch_lsx_vsrlrni_b_h, uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSRLRNI_H_W : LSX_I5_U<0b01110011010001001>, -+ LSX_BIND_U5_DESC_BASE<"vsrlrni.h.w", int_loongarch_lsx_vsrlrni_h_w, uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSRLRNI_W_D : LSX_I6_U<0b0111001101000101>, -+ LSX_BIND_U6_DESC_BASE<"vsrlrni.w.d", int_loongarch_lsx_vsrlrni_w_d, uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSRLRNI_D_Q : LSX_I7_U<0b011100110100011>, -+ LSX_BIND_U7_DESC_BASE<"vsrlrni.d.q", int_loongarch_lsx_vsrlrni_d_q, LSX128DOpnd>; -+ -+ -+def VSSRLNI_B_H : LSX_I4_U<0b011100110100100001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrlni.b.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRLNI_H_W : LSX_I5_U<0b01110011010010001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrlni.h.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRLNI_W_D : LSX_I6_U<0b0111001101001001>, -+ LSX_BIND_U6N_DESC_BASE<"vssrlni.w.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRLNI_D_Q : LSX_I7_U<0b011100110100101>, -+ LSX_BIND_U7N_DESC_BASE<"vssrlni.d.q", LSX128DOpnd>; -+ -+ -+def VSSRLNI_BU_H : LSX_I4_U<0b011100110100110001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrlni.bu.h", uimm4, immZExt4, LSX128BOpnd> ; -+ -+def VSSRLNI_HU_W : LSX_I5_U<0b01110011010011001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrlni.hu.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRLNI_WU_D : LSX_I6_U<0b0111001101001101>, -+ LSX_BIND_U6N_DESC_BASE<"vssrlni.wu.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRLNI_DU_Q : LSX_I7_U<0b011100110100111>, -+ LSX_BIND_U7N_DESC_BASE<"vssrlni.du.q", LSX128DOpnd>; -+ -+ -+def VSSRLRNI_BU_H : LSX_I4_U<0b011100110101010001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrlrni.bu.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRLRNI_HU_W : LSX_I5_U<0b01110011010101001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrlrni.hu.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRLRNI_WU_D : LSX_I6_U<0b0111001101010101>, -+ LSX_BIND_U6N_DESC_BASE<"vssrlrni.wu.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRLRNI_DU_Q : LSX_I7_U<0b011100110101011>, -+ LSX_BIND_U7N_DESC_BASE<"vssrlrni.du.q", LSX128DOpnd>; -+ -+ -+def VSRARNI_B_H : LSX_I4_U<0b011100110101110001>, -+ LSX_BIND_U4N_DESC_BASE<"vsrarni.b.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSRARNI_H_W : LSX_I5_U<0b01110011010111001>, -+ LSX_BIND_U5N_DESC_BASE<"vsrarni.h.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSRARNI_W_D : LSX_I6_U<0b0111001101011101>, -+ LSX_BIND_U6N_DESC_BASE<"vsrarni.w.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSRARNI_D_Q : LSX_I7_U<0b011100110101111>, -+ LSX_BIND_U7N_DESC_BASE<"vsrarni.d.q", LSX128DOpnd>; -+ -+ -+def VSSRANI_B_H : LSX_I4_U<0b011100110110000001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrani.b.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRANI_H_W : LSX_I5_U<0b01110011011000001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrani.h.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRANI_W_D : LSX_I6_U<0b0111001101100001>, -+ LSX_BIND_U6N_DESC_BASE<"vssrani.w.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRANI_D_Q : LSX_I7_U<0b011100110110001>, -+ LSX_BIND_U7N_DESC_BASE<"vssrani.d.q", LSX128DOpnd>; -+ -+ -+def VSSRANI_BU_H : LSX_I4_U<0b011100110110010001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrani.bu.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRANI_HU_W : LSX_I5_U<0b01110011011001001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrani.hu.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRANI_WU_D : LSX_I6_U<0b0111001101100101>, -+ LSX_BIND_U6N_DESC_BASE<"vssrani.wu.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRANI_DU_Q : LSX_I7_U<0b011100110110011>, -+ LSX_BIND_U7N_DESC_BASE<"vssrani.du.q", LSX128DOpnd>; -+ -+ -+def VSSRARNI_B_H : LSX_I4_U<0b011100110110100001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrarni.b.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRARNI_H_W : LSX_I5_U<0b01110011011010001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrarni.h.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRARNI_W_D : LSX_I6_U<0b0111001101101001>, -+ LSX_BIND_U6N_DESC_BASE<"vssrarni.w.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRARNI_D_Q : LSX_I7_U<0b011100110110101>, -+ LSX_BIND_U7N_DESC_BASE<"vssrarni.d.q", LSX128DOpnd>; -+ -+ -+def VSSRARNI_BU_H : LSX_I4_U<0b011100110110110001>, -+ LSX_BIND_U4N_DESC_BASE<"vssrarni.bu.h", uimm4, immZExt4, LSX128BOpnd>; -+ -+def VSSRARNI_HU_W : LSX_I5_U<0b01110011011011001>, -+ LSX_BIND_U5N_DESC_BASE<"vssrarni.hu.w", uimm5, immZExt5, LSX128HOpnd>; -+ -+def VSSRARNI_WU_D : LSX_I6_U<0b0111001101101101>, -+ LSX_BIND_U6N_DESC_BASE<"vssrarni.wu.d", uimm6, immZExt6, LSX128WOpnd>; -+ -+def VSSRARNI_DU_Q : LSX_I7_U<0b011100110110111>, -+ LSX_BIND_U7N_DESC_BASE<"vssrarni.du.q", LSX128DOpnd>; -+ -+ -+ -+def VLD : LSX_I12_S<0b0010110000>, -+ LD_DESC_BASE<"vld", load, v16i8, LSX128BOpnd, mem>; -+ -+def VST : LSX_I12_S<0b0010110001>, -+ ST_DESC_BASE<"vst", store, v16i8, LSX128BOpnd, mem_simm12>; -+ -+ -+def VSETEQZ_V : LSX_SET<0b0111001010011100100110>, -+ LSX_SET_DESC_BASE<"vseteqz.v", LSX128BOpnd>; -+ -+def VSETNEZ_V : LSX_SET<0b0111001010011100100111>, -+ LSX_SET_DESC_BASE<"vsetnez.v", LSX128BOpnd>; -+ -+ -+def VSETANYEQZ_B : LSX_SET<0b0111001010011100101000>, -+ LSX_SET_DESC_BASE<"vsetanyeqz.b", LSX128BOpnd>; -+ -+def VSETANYEQZ_H : LSX_SET<0b0111001010011100101001>, -+ LSX_SET_DESC_BASE<"vsetanyeqz.h", LSX128HOpnd>; -+ -+def VSETANYEQZ_W : LSX_SET<0b0111001010011100101010>, -+ LSX_SET_DESC_BASE<"vsetanyeqz.w", LSX128WOpnd>; -+ -+def VSETANYEQZ_D : LSX_SET<0b0111001010011100101011>, -+ LSX_SET_DESC_BASE<"vsetanyeqz.d", LSX128DOpnd>; -+ -+ -+def VSETALLNEZ_B : LSX_SET<0b0111001010011100101100>, -+ LSX_SET_DESC_BASE<"vsetallnez.b", LSX128BOpnd>; -+ -+def VSETALLNEZ_H : LSX_SET<0b0111001010011100101101>, -+ LSX_SET_DESC_BASE<"vsetallnez.h", LSX128HOpnd>; -+ -+def VSETALLNEZ_W : LSX_SET<0b0111001010011100101110>, -+ LSX_SET_DESC_BASE<"vsetallnez.w", LSX128WOpnd>; -+ -+def VSETALLNEZ_D : LSX_SET<0b0111001010011100101111>, -+ LSX_SET_DESC_BASE<"vsetallnez.d", LSX128DOpnd>; -+ -+class LSX_CBRANCH_PSEUDO_DESC_BASE : -+ LoongArchPseudo<(outs GPR32Opnd:$rd), -+ (ins RCVS:$vj), -+ [(set GPR32Opnd:$rd, (OpNode (TyNode RCVS:$vj)))]> { -+ bit usesCustomInserter = 1; -+} -+ -+def SNZ_B_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SNZ_H_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SNZ_W_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SNZ_D_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SNZ_V_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+ -+def SZ_B_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SZ_H_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SZ_W_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SZ_D_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+def SZ_V_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; -+ -+ -+def VFMADD_S : LSX_VR4MUL<0b000010010001>, -+ LSX_4RF<"vfmadd.s", int_loongarch_lsx_vfmadd_s, LSX128WOpnd>; -+ -+def VFMADD_D : LSX_VR4MUL<0b000010010010>, -+ LSX_4RF<"vfmadd.d", int_loongarch_lsx_vfmadd_d, LSX128DOpnd>; -+ -+def VFMSUB_S : LSX_VR4MUL<0b000010010101>, -+ LSX_4RF<"vfmsub.s", int_loongarch_lsx_vfmsub_s, LSX128WOpnd>; -+ -+def VFMSUB_D : LSX_VR4MUL<0b000010010110>, -+ LSX_4RF<"vfmsub.d", int_loongarch_lsx_vfmsub_d, LSX128DOpnd>; -+ -+def VFNMADD_S : LSX_VR4MUL<0b000010011001>, -+ LSX_4RF<"vfnmadd.s", int_loongarch_lsx_vfnmadd_s, LSX128WOpnd>; -+ -+def VFNMADD_D : LSX_VR4MUL<0b000010011010>, -+ LSX_4RF<"vfnmadd.d", int_loongarch_lsx_vfnmadd_d, LSX128DOpnd>; -+ -+def VFNMSUB_S : LSX_VR4MUL<0b000010011101>, -+ LSX_4RF<"vfnmsub.s", int_loongarch_lsx_vfnmsub_s, LSX128WOpnd>; -+ -+def VFNMSUB_D : LSX_VR4MUL<0b000010011110>, -+ LSX_4RF<"vfnmsub.d", int_loongarch_lsx_vfnmsub_d, LSX128DOpnd>; -+ -+ -+// vfmadd: vj * vk + va -+def : LSXPat<(fma v2f64:$vj, v2f64:$vk, v2f64:$va), -+ (VFMADD_D $vj, $vk, $va)>; -+ -+def : LSXPat<(fma v4f32:$vj, v4f32:$vk, v4f32:$va), -+ (VFMADD_S $vj, $vk, $va)>; -+ -+ -+// vfmsub: vj * vk - va -+def : LSXPat<(fma v2f64:$vj, v2f64:$vk, (fneg v2f64:$va)), -+ (VFMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; -+ -+def : LSXPat<(fma v4f32:$vj, v4f32:$vk, (fneg v4f32:$va)), -+ (VFMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; -+ -+ -+// vfnmadd: -(vj * vk + va) -+def : LSXPat<(fma (fneg v2f64:$vj), v2f64:$vk, (fneg v2f64:$va)), -+ (VFNMADD_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; -+ -+def : LSXPat<(fma (fneg v4f32:$vj), v4f32:$vk, (fneg v4f32:$va)), -+ (VFNMADD_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; -+ -+// vfnmsub: -(vj * vk - va) -+def : LSXPat<(fma (fneg v2f64:$vj), v2f64:$vk, v2f64:$va), -+ (VFNMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; -+ -+def : LSXPat<(fma (fneg v4f32:$vj), v4f32:$vk, v4f32:$va), -+ (VFNMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; -+ -+ -+def VFCMP_CAF_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.caf.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_caf_s>{ -+ bits<5> cond=0x0; -+ } -+ -+def VFCMP_CAF_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.caf.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_caf_d>{ -+ bits<5> cond=0x0; -+ } -+ -+ -+def VFCMP_COR_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cor.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetord_v4f32>{ -+ bits<5> cond=0x14; -+ } -+ -+def VFCMP_COR_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cor.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetord_v2f64>{ -+ bits<5> cond=0x14; -+ } -+ -+ -+def VFCMP_CUN_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cun.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetun_v4f32>{ -+ bits<5> cond=0x8; -+ } -+ -+def VFCMP_CUN_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cun.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetun_v2f64>{ -+ bits<5> cond=0x8; -+ } -+ -+ -+def VFCMP_CUNE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cune.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetune_v4f32>{ -+ bits<5> cond=0x18; -+ } -+ -+def VFCMP_CUNE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cune.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetune_v2f64>{ -+ bits<5> cond=0x18; -+ } -+ -+ -+def VFCMP_CUEQ_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cueq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetueq_v4f32>{ -+ bits<5> cond=0xc; -+ } -+ -+def VFCMP_CUEQ_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cueq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetueq_v2f64>{ -+ bits<5> cond=0xc; -+ } -+ -+def VFCMP_CEQ_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.ceq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetoeq_v4f32>{ -+ bits<5> cond=0x4; -+ } -+ -+def VFCMP_CEQ_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.ceq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetoeq_v2f64>{ -+ bits<5> cond=0x4; -+ } -+ -+ -+def VFCMP_CNE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cne.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetone_v4f32>{ -+ bits<5> cond=0x10; -+ } -+ -+def VFCMP_CNE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cne.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetone_v2f64>{ -+ bits<5> cond=0x10; -+ } -+ -+ -+def VFCMP_CLT_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.clt.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetolt_v4f32>{ -+ bits<5> cond=0x2; -+ } -+ -+def VFCMP_CLT_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.clt.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetolt_v2f64>{ -+ bits<5> cond=0x2; -+ } -+ -+ -+def VFCMP_CULT_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cult.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetult_v4f32>{ -+ bits<5> cond=0xa; -+ } -+ -+def VFCMP_CULT_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cult.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetult_v2f64>{ -+ bits<5> cond=0xa; -+ } -+ -+ -+def VFCMP_CLE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cle.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetole_v4f32>{ -+ bits<5> cond=0x6; -+ } -+ -+def VFCMP_CLE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cle.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetole_v2f64>{ -+ bits<5> cond=0x6; -+ } -+ -+ -+def VFCMP_CULE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.cule.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetule_v4f32>{ -+ bits<5> cond=0xe; -+ } -+ -+def VFCMP_CULE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.cule.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetule_v2f64>{ -+ bits<5> cond=0xe; -+ } -+ -+ -+def VFCMP_SAF_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.saf.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_saf_s>{ -+ bits<5> cond=0x1; -+ } -+ -+def VFCMP_SAF_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.saf.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_saf_d>{ -+ bits<5> cond=0x1; -+ } -+ -+def VFCMP_SOR_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sor.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sor_s>{ -+ bits<5> cond=0x15; -+ } -+ -+def VFCMP_SOR_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sor.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sor_d>{ -+ bits<5> cond=0x15; -+ } -+ -+def VFCMP_SUN_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sun.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sun_s>{ -+ bits<5> cond=0x9; -+ } -+ -+def VFCMP_SUN_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sun.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sun_d>{ -+ bits<5> cond=0x9; -+ } -+ -+def VFCMP_SUNE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sune.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sune_s>{ -+ bits<5> cond=0x19; -+ } -+ -+def VFCMP_SUNE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sune.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sune_d>{ -+ bits<5> cond=0x19; -+ } -+ -+def VFCMP_SUEQ_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sueq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sueq_s>{ -+ bits<5> cond=0xd; -+ } -+ -+def VFCMP_SUEQ_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sueq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sueq_d>{ -+ bits<5> cond=0xd; -+ } -+ -+def VFCMP_SEQ_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.seq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_seq_s>{ -+ bits<5> cond=0x5; -+ } -+ -+def VFCMP_SEQ_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.seq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_seq_d>{ -+ bits<5> cond=0x5; -+ } -+ -+def VFCMP_SNE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sne.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sne_s>{ -+ bits<5> cond=0x11; -+ } -+ -+def VFCMP_SNE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sne.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sne_d>{ -+ bits<5> cond=0x11; -+ } -+ -+def VFCMP_SLT_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.slt.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_slt_s>{ -+ bits<5> cond=0x3; -+ } -+ -+def VFCMP_SLT_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.slt.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_slt_d>{ -+ bits<5> cond=0x3; -+ } -+ -+def VFCMP_SULT_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sult.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sult_s>{ -+ bits<5> cond=0xb; -+ } -+ -+def VFCMP_SULT_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sult.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sult_d>{ -+ bits<5> cond=0xb; -+ } -+ -+def VFCMP_SLE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sle.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sle_s>{ -+ bits<5> cond=0x7; -+ } -+ -+def VFCMP_SLE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sle.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sle_d>{ -+ bits<5> cond=0x7; -+ } -+ -+def VFCMP_SULE_S : LSX_VFCMP<0b000011000101>, -+ LSX_VFCMP_Reg3<"vfcmp.sule.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sule_s>{ -+ bits<5> cond=0xf; -+ } -+ -+def VFCMP_SULE_D : LSX_VFCMP<0b000011000110>, -+ LSX_VFCMP_Reg3<"vfcmp.sule.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sule_d>{ -+ bits<5> cond=0xf; -+ } -+ -+def VBITSEL_V : LSX_VR4MUL<0b000011010001>, -+ LSX_VMul_Reg4<"vbitsel.v", LSX128BOpnd, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd, int_loongarch_lsx_vbitsel_v>; -+ -+def VSHUF_B : LSX_VR4MUL<0b000011010101>, -+ LSX_3R_4R_VSHF_DESC_BASE<"vshuf.b", LSX128BOpnd>; -+ -+ -+class LSX_BSEL_PSEUDO_BASE : -+ LSXPseudo<(outs RO:$vd), (ins RO:$vd_in, RO:$vs, RO:$vt), -+ [(set RO:$vd, (Ty (vselect RO:$vd_in, RO:$vt, RO:$vs)))]>, -+ PseudoInstExpansion<(VBITSEL_V LSX128BOpnd:$vd, LSX128BOpnd:$vs, -+ LSX128BOpnd:$vt, LSX128BOpnd:$vd_in)> { -+ let Constraints = "$vd_in = $vd"; -+} -+ -+def BSEL_B_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+def BSEL_H_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+def BSEL_W_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+def BSEL_D_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+def BSEL_FW_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+def BSEL_FD_PSEUDO : LSX_BSEL_PSEUDO_BASE; -+ -+ -+class LSX_LD_DESC_BASE { -+ dag OutOperandList = (outs ROVD:$vd); -+ dag InOperandList = (ins MemOpnd:$addr); -+ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); -+ list Pattern = [(set ROVD:$vd, (OpNode (TyNode (load Addr:$addr))))]; -+ string DecoderMethod = "DecodeLSX128memlsl"; -+} -+ -+def VLDREPL_B : LSX_SI12_S<0b0011000010>, -+ LSX_LD_DESC_BASE<"vldrepl.b", vldrepl_v16i8, v16i8, LSX128BOpnd>; -+ -+def VLDREPL_H : LSX_SI11_S<0b00110000010>, -+ LSX_LD_DESC_BASE<"vldrepl.h", vldrepl_v8i16, v8i16, LSX128HOpnd, mem_simm11_lsl1, addrimm11lsl1>; -+ -+def VLDREPL_W : LSX_SI10_S<0b001100000010>, -+ LSX_LD_DESC_BASE<"vldrepl.w", vldrepl_v4i32, v4i32, LSX128WOpnd, mem_simm10_lsl2, addrimm10lsl2>; -+ -+def VLDREPL_D : LSX_SI9_S<0b0011000000010>, -+ LSX_LD_DESC_BASE<"vldrepl.d", vldrepl_v2i64, v2i64, LSX128DOpnd, mem_simm9_lsl3, addrimm9lsl3>; -+ -+ -+def VSTELM_B : LSX_SI8_idx4<0b0011000110>, -+ LSX_I8_U4_DESC_BASE<"vstelm.b", int_loongarch_lsx_vstelm_b, simm8_32, immSExt8, LSX128BOpnd>; -+ -+def VSTELM_H : LSX_SI8_idx3<0b00110001010>, -+ LSX_I8_U3_DESC_BASE<"vstelm.h", int_loongarch_lsx_vstelm_h, immSExt8_1_O, immSExt8, LSX128HOpnd>; -+ -+def VSTELM_W : LSX_SI8_idx2<0b001100010010>, -+ LSX_I8_U2_DESC_BASE<"vstelm.w", int_loongarch_lsx_vstelm_w, immSExt8_2_O, immSExt8, LSX128WOpnd>; -+ -+def VSTELM_D : LSX_SI8_idx1<0b0011000100010>, -+ LSX_I8_U1_DESC_BASE<"vstelm.d", int_loongarch_lsx_vstelm_d, immSExt8_3_O, immSExt8, LSX128DOpnd>; -+ -+ -+let mayLoad = 1, canFoldAsLoad = 1 in { -+ def VLDX : LSX_3R_2GP<0b00111000010000000>, -+ LSX_LDX_LA<"vldx", int_loongarch_lsx_vldx, GPR64Opnd, LSX128BOpnd>; -+} -+ -+let mayStore = 1 in{ -+ def VSTX : LSX_3R_2GP<0b00111000010001000>, -+ LSX_SDX_LA<"vstx", int_loongarch_lsx_vstx, GPR64Opnd, LSX128BOpnd>; -+} -+ -+ -+def VADDWEV_H_B : LSX_3R<0b01110000000111100>, -+ LSX_3R_DESC_BASE<"vaddwev.h.b", int_loongarch_lsx_vaddwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWEV_W_H : LSX_3R<0b01110000000111101>, -+ LSX_3R_DESC_BASE<"vaddwev.w.h", int_loongarch_lsx_vaddwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWEV_D_W : LSX_3R<0b01110000000111110>, -+ LSX_3R_DESC_BASE<"vaddwev.d.w", int_loongarch_lsx_vaddwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWEV_Q_D : LSX_3R<0b01110000000111111>, -+ LSX_3R_DESC_BASE<"vaddwev.q.d", int_loongarch_lsx_vaddwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSUBWEV_H_B : LSX_3R<0b01110000001000000>, -+ LSX_3R_DESC_BASE<"vsubwev.h.b", int_loongarch_lsx_vsubwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSUBWEV_W_H : LSX_3R<0b01110000001000001>, -+ LSX_3R_DESC_BASE<"vsubwev.w.h", int_loongarch_lsx_vsubwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSUBWEV_D_W : LSX_3R<0b01110000001000010>, -+ LSX_3R_DESC_BASE<"vsubwev.d.w", int_loongarch_lsx_vsubwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VSUBWEV_Q_D : LSX_3R<0b01110000001000011>, -+ LSX_3R_DESC_BASE<"vsubwev.q.d", int_loongarch_lsx_vsubwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VADDWOD_H_B : LSX_3R<0b01110000001000100>, -+ LSX_3R_DESC_BASE<"vaddwod.h.b", int_loongarch_lsx_vaddwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWOD_W_H : LSX_3R<0b01110000001000101>, -+ LSX_3R_DESC_BASE<"vaddwod.w.h", int_loongarch_lsx_vaddwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWOD_D_W : LSX_3R<0b01110000001000110>, -+ LSX_3R_DESC_BASE<"vaddwod.d.w", int_loongarch_lsx_vaddwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWOD_Q_D : LSX_3R<0b01110000001000111>, -+ LSX_3R_DESC_BASE<"vaddwod.q.d", int_loongarch_lsx_vaddwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSUBWOD_H_B : LSX_3R<0b01110000001001000>, -+ LSX_3R_DESC_BASE<"vsubwod.h.b", int_loongarch_lsx_vsubwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSUBWOD_W_H : LSX_3R<0b01110000001001001>, -+ LSX_3R_DESC_BASE<"vsubwod.w.h", int_loongarch_lsx_vsubwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSUBWOD_D_W : LSX_3R<0b01110000001001010>, -+ LSX_3R_DESC_BASE<"vsubwod.d.w", int_loongarch_lsx_vsubwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VSUBWOD_Q_D : LSX_3R<0b01110000001001011>, -+ LSX_3R_DESC_BASE<"vsubwod.q.d", int_loongarch_lsx_vsubwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VADDWEV_H_BU : LSX_3R<0b01110000001011100>, -+ LSX_3R_DESC_BASE<"vaddwev.h.bu", int_loongarch_lsx_vaddwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWEV_W_HU : LSX_3R<0b01110000001011101>, -+ LSX_3R_DESC_BASE<"vaddwev.w.hu", int_loongarch_lsx_vaddwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWEV_D_WU : LSX_3R<0b01110000001011110>, -+ LSX_3R_DESC_BASE<"vaddwev.d.wu", int_loongarch_lsx_vaddwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWEV_Q_DU : LSX_3R<0b01110000001011111>, -+ LSX_3R_DESC_BASE<"vaddwev.q.du", int_loongarch_lsx_vaddwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSUBWEV_H_BU : LSX_3R<0b01110000001100000>, -+ LSX_3R_DESC_BASE<"vsubwev.h.bu", int_loongarch_lsx_vsubwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSUBWEV_W_HU : LSX_3R<0b01110000001100001>, -+ LSX_3R_DESC_BASE<"vsubwev.w.hu", int_loongarch_lsx_vsubwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSUBWEV_D_WU : LSX_3R<0b01110000001100010>, -+ LSX_3R_DESC_BASE<"vsubwev.d.wu", int_loongarch_lsx_vsubwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VSUBWEV_Q_DU : LSX_3R<0b01110000001100011>, -+ LSX_3R_DESC_BASE<"vsubwev.q.du", int_loongarch_lsx_vsubwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VADDWOD_H_BU : LSX_3R<0b01110000001100100>, -+ LSX_3R_DESC_BASE<"vaddwod.h.bu", int_loongarch_lsx_vaddwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWOD_W_HU : LSX_3R<0b01110000001100101>, -+ LSX_3R_DESC_BASE<"vaddwod.w.hu", int_loongarch_lsx_vaddwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWOD_D_WU : LSX_3R<0b01110000001100110>, -+ LSX_3R_DESC_BASE<"vaddwod.d.wu", int_loongarch_lsx_vaddwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWOD_Q_DU : LSX_3R<0b01110000001100111>, -+ LSX_3R_DESC_BASE<"vaddwod.q.du", int_loongarch_lsx_vaddwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSUBWOD_H_BU : LSX_3R<0b01110000001101000>, -+ LSX_3R_DESC_BASE<"vsubwod.h.bu", int_loongarch_lsx_vsubwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSUBWOD_W_HU : LSX_3R<0b01110000001101001>, -+ LSX_3R_DESC_BASE<"vsubwod.w.hu", int_loongarch_lsx_vsubwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSUBWOD_D_WU : LSX_3R<0b01110000001101010>, -+ LSX_3R_DESC_BASE<"vsubwod.d.wu", int_loongarch_lsx_vsubwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VSUBWOD_Q_DU : LSX_3R<0b01110000001101011>, -+ LSX_3R_DESC_BASE<"vsubwod.q.du", int_loongarch_lsx_vsubwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VADDWEV_H_BU_B : LSX_3R<0b01110000001111100>, -+ LSX_3R_DESC_BASE<"vaddwev.h.bu.b", int_loongarch_lsx_vaddwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWEV_W_HU_H : LSX_3R<0b01110000001111101>, -+ LSX_3R_DESC_BASE<"vaddwev.w.hu.h", int_loongarch_lsx_vaddwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWEV_D_WU_W : LSX_3R<0b01110000001111110>, -+ LSX_3R_DESC_BASE<"vaddwev.d.wu.w", int_loongarch_lsx_vaddwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWEV_Q_DU_D : LSX_3R<0b01110000001111111>, -+ LSX_3R_DESC_BASE<"vaddwev.q.du.d", int_loongarch_lsx_vaddwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VADDWOD_H_BU_B : LSX_3R<0b01110000010000000>, -+ LSX_3R_DESC_BASE<"vaddwod.h.bu.b", int_loongarch_lsx_vaddwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VADDWOD_W_HU_H : LSX_3R<0b01110000010000001>, -+ LSX_3R_DESC_BASE<"vaddwod.w.hu.h", int_loongarch_lsx_vaddwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VADDWOD_D_WU_W : LSX_3R<0b01110000010000010>, -+ LSX_3R_DESC_BASE<"vaddwod.d.wu.w", int_loongarch_lsx_vaddwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VADDWOD_Q_DU_D : LSX_3R<0b01110000010000011>, -+ LSX_3R_DESC_BASE<"vaddwod.q.du.d", int_loongarch_lsx_vaddwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VHADDW_Q_D : LSX_3R<0b01110000010101011>, -+ LSX_3R_DESC_BASE<"vhaddw.q.d", int_loongarch_lsx_vhaddw_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VHSUBW_Q_D : LSX_3R<0b01110000010101111>, -+ LSX_3R_DESC_BASE<"vhsubw.q.d", int_loongarch_lsx_vhsubw_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VHADDW_QU_DU : LSX_3R<0b01110000010110011>, -+ LSX_3R_DESC_BASE<"vhaddw.qu.du", int_loongarch_lsx_vhaddw_qu_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VHSUBW_QU_DU : LSX_3R<0b01110000010110111>, -+ LSX_3R_DESC_BASE<"vhsubw.qu.du", int_loongarch_lsx_vhsubw_qu_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMUH_B : LSX_3R<0b01110000100001100>, -+ LSX_3R_DESC_BASE<"vmuh.b", int_loongarch_lsx_vmuh_b, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMUH_H : LSX_3R<0b01110000100001101>, -+ LSX_3R_DESC_BASE<"vmuh.h", int_loongarch_lsx_vmuh_h, LSX128HOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMUH_W : LSX_3R<0b01110000100001110>, -+ LSX_3R_DESC_BASE<"vmuh.w", int_loongarch_lsx_vmuh_w, LSX128WOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMUH_D : LSX_3R<0b01110000100001111>, -+ LSX_3R_DESC_BASE<"vmuh.d", int_loongarch_lsx_vmuh_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMUH_BU : LSX_3R<0b01110000100010000>, -+ LSX_3R_DESC_BASE<"vmuh.bu", int_loongarch_lsx_vmuh_bu, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMUH_HU : LSX_3R<0b01110000100010001>, -+ LSX_3R_DESC_BASE<"vmuh.hu", int_loongarch_lsx_vmuh_hu, LSX128HOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMUH_WU : LSX_3R<0b01110000100010010>, -+ LSX_3R_DESC_BASE<"vmuh.wu", int_loongarch_lsx_vmuh_wu, LSX128WOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMUH_DU : LSX_3R<0b01110000100010011>, -+ LSX_3R_DESC_BASE<"vmuh.du", int_loongarch_lsx_vmuh_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWEV_H_B : LSX_3R<0b01110000100100000>, -+ LSX_3R_DESC_BASE<"vmulwev.h.b", int_loongarch_lsx_vmulwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWEV_W_H : LSX_3R<0b01110000100100001>, -+ LSX_3R_DESC_BASE<"vmulwev.w.h", int_loongarch_lsx_vmulwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWEV_D_W : LSX_3R<0b01110000100100010>, -+ LSX_3R_DESC_BASE<"vmulwev.d.w", int_loongarch_lsx_vmulwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWEV_Q_D : LSX_3R<0b01110000100100011>, -+ LSX_3R_DESC_BASE<"vmulwev.q.d", int_loongarch_lsx_vmulwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWOD_H_B : LSX_3R<0b01110000100100100>, -+ LSX_3R_DESC_BASE<"vmulwod.h.b", int_loongarch_lsx_vmulwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWOD_W_H : LSX_3R<0b01110000100100101>, -+ LSX_3R_DESC_BASE<"vmulwod.w.h", int_loongarch_lsx_vmulwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWOD_D_W : LSX_3R<0b01110000100100110>, -+ LSX_3R_DESC_BASE<"vmulwod.d.w", int_loongarch_lsx_vmulwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWOD_Q_D : LSX_3R<0b01110000100100111>, -+ LSX_3R_DESC_BASE<"vmulwod.q.d", int_loongarch_lsx_vmulwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWEV_H_BU : LSX_3R<0b01110000100110000>, -+ LSX_3R_DESC_BASE<"vmulwev.h.bu", int_loongarch_lsx_vmulwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWEV_W_HU : LSX_3R<0b01110000100110001>, -+ LSX_3R_DESC_BASE<"vmulwev.w.hu", int_loongarch_lsx_vmulwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWEV_D_WU : LSX_3R<0b01110000100110010>, -+ LSX_3R_DESC_BASE<"vmulwev.d.wu", int_loongarch_lsx_vmulwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWEV_Q_DU : LSX_3R<0b01110000100110011>, -+ LSX_3R_DESC_BASE<"vmulwev.q.du", int_loongarch_lsx_vmulwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWOD_H_BU : LSX_3R<0b01110000100110100>, -+ LSX_3R_DESC_BASE<"vmulwod.h.bu", int_loongarch_lsx_vmulwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWOD_W_HU : LSX_3R<0b01110000100110101>, -+ LSX_3R_DESC_BASE<"vmulwod.w.hu", int_loongarch_lsx_vmulwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWOD_D_WU : LSX_3R<0b01110000100110110>, -+ LSX_3R_DESC_BASE<"vmulwod.d.wu", int_loongarch_lsx_vmulwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWOD_Q_DU : LSX_3R<0b01110000100110111>, -+ LSX_3R_DESC_BASE<"vmulwod.q.du", int_loongarch_lsx_vmulwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWEV_H_BU_B : LSX_3R<0b01110000101000000>, -+ LSX_3R_DESC_BASE<"vmulwev.h.bu.b", int_loongarch_lsx_vmulwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWEV_W_HU_H : LSX_3R<0b01110000101000001>, -+ LSX_3R_DESC_BASE<"vmulwev.w.hu.h", int_loongarch_lsx_vmulwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWEV_D_WU_W : LSX_3R<0b01110000101000010>, -+ LSX_3R_DESC_BASE<"vmulwev.d.wu.w", int_loongarch_lsx_vmulwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWEV_Q_DU_D : LSX_3R<0b01110000101000011>, -+ LSX_3R_DESC_BASE<"vmulwev.q.du.d", int_loongarch_lsx_vmulwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMULWOD_H_BU_B : LSX_3R<0b01110000101000100>, -+ LSX_3R_DESC_BASE<"vmulwod.h.bu.b", int_loongarch_lsx_vmulwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMULWOD_W_HU_H : LSX_3R<0b01110000101000101>, -+ LSX_3R_DESC_BASE<"vmulwod.w.hu.h", int_loongarch_lsx_vmulwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMULWOD_D_WU_W : LSX_3R<0b01110000101000110>, -+ LSX_3R_DESC_BASE<"vmulwod.d.wu.w", int_loongarch_lsx_vmulwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMULWOD_Q_DU_D : LSX_3R<0b01110000101000111>, -+ LSX_3R_DESC_BASE<"vmulwod.q.du.d", int_loongarch_lsx_vmulwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWEV_H_B : LSX_3R<0b01110000101011000>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.h.b", int_loongarch_lsx_vmaddwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWEV_W_H : LSX_3R<0b01110000101011001>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.w.h", int_loongarch_lsx_vmaddwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWEV_D_W : LSX_3R<0b01110000101011010>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.d.w", int_loongarch_lsx_vmaddwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VMADDWEV_Q_D : LSX_3R<0b01110000101011011>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.q.d", int_loongarch_lsx_vmaddwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWOD_H_B : LSX_3R<0b01110000101011100>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.h.b", int_loongarch_lsx_vmaddwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWOD_W_H : LSX_3R<0b01110000101011101>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.w.h", int_loongarch_lsx_vmaddwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWOD_D_W : LSX_3R<0b01110000101011110>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.d.w", int_loongarch_lsx_vmaddwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VMADDWOD_Q_D : LSX_3R<0b01110000101011111>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.q.d", int_loongarch_lsx_vmaddwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWEV_H_BU : LSX_3R<0b01110000101101000>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.h.bu", int_loongarch_lsx_vmaddwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWEV_W_HU : LSX_3R<0b01110000101101001>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.w.hu", int_loongarch_lsx_vmaddwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWEV_D_WU : LSX_3R<0b01110000101101010>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.d.wu", int_loongarch_lsx_vmaddwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VMADDWEV_Q_DU : LSX_3R<0b01110000101101011>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.q.du", int_loongarch_lsx_vmaddwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWOD_H_BU : LSX_3R<0b01110000101101100>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.h.bu", int_loongarch_lsx_vmaddwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWOD_W_HU : LSX_3R<0b01110000101101101>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.w.hu", int_loongarch_lsx_vmaddwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWOD_D_WU : LSX_3R<0b01110000101101110>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.d.wu", int_loongarch_lsx_vmaddwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VMADDWOD_Q_DU : LSX_3R<0b01110000101101111>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.q.du", int_loongarch_lsx_vmaddwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWEV_H_BU_B : LSX_3R<0b01110000101111000>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.h.bu.b", int_loongarch_lsx_vmaddwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWEV_W_HU_H : LSX_3R<0b01110000101111001>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.w.hu.h", int_loongarch_lsx_vmaddwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWEV_D_WU_W : LSX_3R<0b01110000101111010>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.d.wu.w", int_loongarch_lsx_vmaddwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMADDWEV_Q_DU_D : LSX_3R<0b01110000101111011>, -+ LSX_3R_4R_DESC_BASE<"vmaddwev.q.du.d", int_loongarch_lsx_vmaddwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VMADDWOD_H_BU_B : LSX_3R<0b01110000101111100>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.h.bu.b", int_loongarch_lsx_vmaddwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; -+ -+def VMADDWOD_W_HU_H : LSX_3R<0b01110000101111101>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.w.hu.h", int_loongarch_lsx_vmaddwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VMADDWOD_D_WU_W : LSX_3R<0b01110000101111110>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.d.wu.w", int_loongarch_lsx_vmaddwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; -+ -+def VMADDWOD_Q_DU_D : LSX_3R<0b01110000101111111>, -+ LSX_3R_4R_DESC_BASE<"vmaddwod.q.du.d", int_loongarch_lsx_vmaddwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSRLN_B_H : LSX_3R<0b01110000111101001>, -+ LSX_3R_DESC_BASE<"vsrln.b.h", int_loongarch_lsx_vsrln_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSRLN_H_W : LSX_3R<0b01110000111101010>, -+ LSX_3R_DESC_BASE<"vsrln.h.w", int_loongarch_lsx_vsrln_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSRLN_W_D : LSX_3R<0b01110000111101011>, -+ LSX_3R_DESC_BASE<"vsrln.w.d", int_loongarch_lsx_vsrln_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSRAN_B_H : LSX_3R<0b01110000111101101>, -+ LSX_3R_DESC_BASE<"vsran.b.h", int_loongarch_lsx_vsran_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSRAN_H_W : LSX_3R<0b01110000111101110>, -+ LSX_3R_DESC_BASE<"vsran.h.w", int_loongarch_lsx_vsran_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSRAN_W_D : LSX_3R<0b01110000111101111>, -+ LSX_3R_DESC_BASE<"vsran.w.d", int_loongarch_lsx_vsran_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSRLRN_B_H : LSX_3R<0b01110000111110001>, -+ LSX_3R_DESC_BASE<"vsrlrn.b.h", int_loongarch_lsx_vsrlrn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSRLRN_H_W : LSX_3R<0b01110000111110010>, -+ LSX_3R_DESC_BASE<"vsrlrn.h.w", int_loongarch_lsx_vsrlrn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSRLRN_W_D : LSX_3R<0b01110000111110011>, -+ LSX_3R_DESC_BASE<"vsrlrn.w.d", int_loongarch_lsx_vsrlrn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSRARN_B_H : LSX_3R<0b01110000111110101>, -+ LSX_3R_DESC_BASE<"vsrarn.b.h", int_loongarch_lsx_vsrarn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSRARN_H_W : LSX_3R<0b01110000111110110>, -+ LSX_3R_DESC_BASE<"vsrarn.h.w", int_loongarch_lsx_vsrarn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSRARN_W_D : LSX_3R<0b01110000111110111>, -+ LSX_3R_DESC_BASE<"vsrarn.w.d", int_loongarch_lsx_vsrarn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRLN_B_H : LSX_3R<0b01110000111111001>, -+ LSX_3R_DESC_BASE<"vssrln.b.h", int_loongarch_lsx_vssrln_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRLN_H_W : LSX_3R<0b01110000111111010>, -+ LSX_3R_DESC_BASE<"vssrln.h.w", int_loongarch_lsx_vssrln_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRLN_W_D : LSX_3R<0b01110000111111011>, -+ LSX_3R_DESC_BASE<"vssrln.w.d", int_loongarch_lsx_vssrln_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRAN_B_H : LSX_3R<0b01110000111111101>, -+ LSX_3R_DESC_BASE<"vssran.b.h", int_loongarch_lsx_vssran_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRAN_H_W : LSX_3R<0b01110000111111110>, -+ LSX_3R_DESC_BASE<"vssran.h.w", int_loongarch_lsx_vssran_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRAN_W_D : LSX_3R<0b01110000111111111>, -+ LSX_3R_DESC_BASE<"vssran.w.d", int_loongarch_lsx_vssran_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRLRN_B_H : LSX_3R<0b01110001000000001>, -+ LSX_3R_DESC_BASE<"vssrlrn.b.h", int_loongarch_lsx_vssrlrn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRLRN_H_W : LSX_3R<0b01110001000000010>, -+ LSX_3R_DESC_BASE<"vssrlrn.h.w", int_loongarch_lsx_vssrlrn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRLRN_W_D : LSX_3R<0b01110001000000011>, -+ LSX_3R_DESC_BASE<"vssrlrn.w.d", int_loongarch_lsx_vssrlrn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRARN_B_H : LSX_3R<0b01110001000000101>, -+ LSX_3R_DESC_BASE<"vssrarn.b.h", int_loongarch_lsx_vssrarn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRARN_H_W : LSX_3R<0b01110001000000110>, -+ LSX_3R_DESC_BASE<"vssrarn.h.w", int_loongarch_lsx_vssrarn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRARN_W_D : LSX_3R<0b01110001000000111>, -+ LSX_3R_DESC_BASE<"vssrarn.w.d", int_loongarch_lsx_vssrarn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRLN_BU_H : LSX_3R<0b01110001000001001>, -+ LSX_3R_DESC_BASE<"vssrln.bu.h", int_loongarch_lsx_vssrln_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRLN_HU_W : LSX_3R<0b01110001000001010>, -+ LSX_3R_DESC_BASE<"vssrln.hu.w", int_loongarch_lsx_vssrln_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRLN_WU_D : LSX_3R<0b01110001000001011>, -+ LSX_3R_DESC_BASE<"vssrln.wu.d", int_loongarch_lsx_vssrln_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRAN_BU_H : LSX_3R<0b01110001000001101>, -+ LSX_3R_DESC_BASE<"vssran.bu.h", int_loongarch_lsx_vssran_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRAN_HU_W : LSX_3R<0b01110001000001110>, -+ LSX_3R_DESC_BASE<"vssran.hu.w", int_loongarch_lsx_vssran_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRAN_WU_D : LSX_3R<0b01110001000001111>, -+ LSX_3R_DESC_BASE<"vssran.wu.d", int_loongarch_lsx_vssran_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRLRN_BU_H : LSX_3R<0b01110001000010001>, -+ LSX_3R_DESC_BASE<"vssrlrn.bu.h", int_loongarch_lsx_vssrlrn_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRLRN_HU_W : LSX_3R<0b01110001000010010>, -+ LSX_3R_DESC_BASE<"vssrlrn.hu.w", int_loongarch_lsx_vssrlrn_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRLRN_WU_D : LSX_3R<0b01110001000010011>, -+ LSX_3R_DESC_BASE<"vssrlrn.wu.d", int_loongarch_lsx_vssrlrn_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRARN_BU_H : LSX_3R<0b01110001000010101>, -+ LSX_3R_DESC_BASE<"vssrarn.bu.h", int_loongarch_lsx_vssrarn_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRARN_HU_W : LSX_3R<0b01110001000010110>, -+ LSX_3R_DESC_BASE<"vssrarn.hu.w", int_loongarch_lsx_vssrarn_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRARN_WU_D : LSX_3R<0b01110001000010111>, -+ LSX_3R_DESC_BASE<"vssrarn.wu.d", int_loongarch_lsx_vssrarn_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VANDN_V : LSX_3R<0b01110001001010000>, -+ LSX_3R_DESC_BASE<"vandn.v", int_loongarch_lsx_vandn_v, LSX128BOpnd>; -+ -+ -+class LSX_VANDN_PSEUDO_BASE : -+ LSXPseudo<(outs RO:$vd), (ins RO:$vj, RO:$vk), -+ []>, -+ PseudoInstExpansion<(VANDN_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+def VANDN_H_PSEUDO : LSX_VANDN_PSEUDO_BASE; -+def VANDN_W_PSEUDO : LSX_VANDN_PSEUDO_BASE; -+def VANDN_D_PSEUDO : LSX_VANDN_PSEUDO_BASE; -+ -+ -+ -+def VORN_V : LSX_3R<0b01110001001010001>, -+ LSX_3R_DESC_BASE<"vorn.v", int_loongarch_lsx_vorn_v, LSX128BOpnd>; -+ -+ -+class LSX_VORN_PSEUDO_BASE : -+ LSXPseudo<(outs RO:$vd), (ins RO:$vj, RO:$vk), -+ []>, -+ PseudoInstExpansion<(VORN_V LSX128BOpnd:$vd, -+ LSX128BOpnd:$vj, -+ LSX128BOpnd:$vk)>; -+ -+def VORN_H_PSEUDO : LSX_VORN_PSEUDO_BASE; -+def VORN_W_PSEUDO : LSX_VORN_PSEUDO_BASE; -+def VORN_D_PSEUDO : LSX_VORN_PSEUDO_BASE; -+ -+ -+def VFRSTP_B : LSX_3R<0b01110001001010110>, -+ LSX_3R_4R_DESC_BASE<"vfrstp.b", int_loongarch_lsx_vfrstp_b, LSX128BOpnd>; -+ -+def VFRSTP_H : LSX_3R<0b01110001001010111>, -+ LSX_3R_4R_DESC_BASE<"vfrstp.h", int_loongarch_lsx_vfrstp_h, LSX128HOpnd>; -+ -+ -+def VADD_Q : LSX_3R<0b01110001001011010>, IsCommutable, -+ LSX_3R_DESC_BASE<"vadd.q", int_loongarch_lsx_vadd_q, LSX128DOpnd>; -+ -+def VSUB_Q : LSX_3R<0b01110001001011011>, -+ LSX_3R_DESC_BASE<"vsub.q", int_loongarch_lsx_vsub_q, LSX128DOpnd>; -+ -+ -+def VSIGNCOV_B : LSX_3R<0b01110001001011100>, -+ LSX_3R_DESC_BASE<"vsigncov.b", int_loongarch_lsx_vsigncov_b, LSX128BOpnd>; -+ -+def VSIGNCOV_H : LSX_3R<0b01110001001011101>, -+ LSX_3R_DESC_BASE<"vsigncov.h", int_loongarch_lsx_vsigncov_h, LSX128HOpnd>; -+ -+def VSIGNCOV_W : LSX_3R<0b01110001001011110>, -+ LSX_3R_DESC_BASE<"vsigncov.w", int_loongarch_lsx_vsigncov_w, LSX128WOpnd>; -+ -+def VSIGNCOV_D : LSX_3R<0b01110001001011111>, -+ LSX_3R_DESC_BASE<"vsigncov.d", int_loongarch_lsx_vsigncov_d, LSX128DOpnd>; -+ -+ -+def VFCVT_H_S : LSX_3R<0b01110001010001100>, -+ LSX_3RF_DESC_BASE<"vfcvt.h.s", int_loongarch_lsx_vfcvt_h_s, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; -+ -+def VFCVT_S_D : LSX_3R<0b01110001010001101>, -+ LSX_3RF_DESC_BASE1<"vfcvt.s.d", int_loongarch_lsx_vfcvt_s_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VFFINT_S_L : LSX_3R<0b01110001010010000>, -+ LSX_3RF_DESC_BASE<"vffint.s.l", int_loongarch_lsx_vffint_s_l, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VFTINT_W_D : LSX_3R<0b01110001010010011>, -+ LSX_3RF_DESC_BASE<"vftint.w.d", int_loongarch_lsx_vftint_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VFTINTRZ_W_D : LSX_3R<0b01110001010010110>, -+ LSX_3RF_DESC_BASE<"vftintrz.w.d", int_loongarch_lsx_vftintrz_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VFTINTRP_W_D : LSX_3R<0b01110001010010101>, -+ LSX_3RF_DESC_BASE<"vftintrp.w.d", int_loongarch_lsx_vftintrp_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VFTINTRM_W_D : LSX_3R<0b01110001010010100>, -+ LSX_3RF_DESC_BASE<"vftintrm.w.d", int_loongarch_lsx_vftintrm_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+def VFTINTRNE_W_D : LSX_3R<0b01110001010010111>, -+ LSX_3RF_DESC_BASE<"vftintrne.w.d", int_loongarch_lsx_vftintrne_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VBSRL_V : LSX_I5_U<0b01110010100011101>, -+ LSX_U5_DESC_BASE<"vbsrl.v", int_loongarch_lsx_vbsrl_v, LSX128BOpnd>; -+ -+def VBSLL_V : LSX_I5_U<0b01110010100011100>, -+ LSX_U5_DESC_BASE<"vbsll.v", int_loongarch_lsx_vbsll_v, LSX128BOpnd>; -+ -+ -+def VFRSTPI_B : LSX_I5_U<0b01110010100110100>, -+ LSX_U5_4R_DESC_BASE<"vfrstpi.b", int_loongarch_lsx_vfrstpi_b, LSX128BOpnd>; -+ -+def VFRSTPI_H : LSX_I5_U<0b01110010100110101>, -+ LSX_U5_4R_DESC_BASE<"vfrstpi.h", int_loongarch_lsx_vfrstpi_h, LSX128HOpnd>; -+ -+ -+def VNEG_B : LSX_2R<0b0111001010011100001100>, -+ LSX_2R_DESC_BASE<"vneg.b", int_loongarch_lsx_vneg_b, LSX128BOpnd>; -+ -+def VNEG_H : LSX_2R<0b0111001010011100001101>, -+ LSX_2R_DESC_BASE<"vneg.h", int_loongarch_lsx_vneg_h, LSX128HOpnd>; -+ -+def VNEG_W : LSX_2R<0b0111001010011100001110>, -+ LSX_2R_DESC_BASE<"vneg.w", int_loongarch_lsx_vneg_w, LSX128WOpnd>; -+ -+def VNEG_D : LSX_2R<0b0111001010011100001111>, -+ LSX_2R_DESC_BASE<"vneg.d", int_loongarch_lsx_vneg_d, LSX128DOpnd>; -+ -+ -+def VMSKGEZ_B : LSX_2R<0b0111001010011100010100>, -+ LSX_2R_DESC_BASE<"vmskgez.b", int_loongarch_lsx_vmskgez_b, LSX128BOpnd>; -+ -+def VMSKNZ_B : LSX_2R<0b0111001010011100011000>, -+ LSX_2R_DESC_BASE<"vmsknz.b", int_loongarch_lsx_vmsknz_b, LSX128BOpnd>; -+ -+ -+def VFRINTRM_S : LSX_2R<0b0111001010011101010001>, -+ LSX_2RF_DESC_BASE<"vfrintrm.s", int_loongarch_lsx_vfrintrm_s, LSX128WOpnd>; -+ -+def VFRINTRM_D : LSX_2R<0b0111001010011101010010>, -+ LSX_2RF_DESC_BASE<"vfrintrm.d", int_loongarch_lsx_vfrintrm_d, LSX128DOpnd>; -+ -+ -+def VFRINTRP_S : LSX_2R<0b0111001010011101010101>, -+ LSX_2RF_DESC_BASE<"vfrintrp.s", int_loongarch_lsx_vfrintrp_s, LSX128WOpnd>; -+ -+def VFRINTRP_D : LSX_2R<0b0111001010011101010110>, -+ LSX_2RF_DESC_BASE<"vfrintrp.d", int_loongarch_lsx_vfrintrp_d, LSX128DOpnd>; -+ -+ -+def VFRINTRZ_S : LSX_2R<0b0111001010011101011001>, -+ LSX_2RF_DESC_BASE<"vfrintrz.s", int_loongarch_lsx_vfrintrz_s, LSX128WOpnd>; -+ -+def VFRINTRZ_D : LSX_2R<0b0111001010011101011010>, -+ LSX_2RF_DESC_BASE<"vfrintrz.d", int_loongarch_lsx_vfrintrz_d, LSX128DOpnd>; -+ -+ -+def VFRINTRNE_S : LSX_2R<0b0111001010011101011101>, -+ LSX_2RF_DESC_BASE<"vfrintrne.s", int_loongarch_lsx_vfrintrne_s, LSX128WOpnd>; -+ -+def VFRINTRNE_D : LSX_2R<0b0111001010011101011110>, -+ LSX_2RF_DESC_BASE<"vfrintrne.d", int_loongarch_lsx_vfrintrne_d, LSX128DOpnd>; -+ -+ -+def VFFINTL_D_W : LSX_2R<0b0111001010011110000100>, -+ LSX_2RF_DESC_BASE<"vffintl.d.w", int_loongarch_lsx_vffintl_d_w, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFFINTH_D_W : LSX_2R<0b0111001010011110000101>, -+ LSX_2RF_DESC_BASE<"vffinth.d.w", int_loongarch_lsx_vffinth_d_w, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFTINTRM_W_S : LSX_2R<0b0111001010011110001110>, -+ LSX_2RF_DESC_BASE<"vftintrm.w.s", int_loongarch_lsx_vftintrm_w_s, LSX128WOpnd>; -+ -+def VFTINTRM_L_D : LSX_2R<0b0111001010011110001111>, -+ LSX_2RF_DESC_BASE<"vftintrm.l.d", int_loongarch_lsx_vftintrm_l_d, LSX128DOpnd>; -+ -+ -+def VFTINTRP_W_S : LSX_2R<0b0111001010011110010000>, -+ LSX_2RF_DESC_BASE<"vftintrp.w.s", int_loongarch_lsx_vftintrp_w_s, LSX128WOpnd>; -+ -+def VFTINTRP_L_D : LSX_2R<0b0111001010011110010001>, -+ LSX_2RF_DESC_BASE<"vftintrp.l.d", int_loongarch_lsx_vftintrp_l_d, LSX128DOpnd>; -+ -+ -+def VFTINTRZ_W_S : LSX_2R<0b0111001010011110010010>, -+ LSX_2RF_DESC_BASE<"vftintrz.w.s", fp_to_sint, LSX128WOpnd>; -+ -+def VFTINTRZ_L_D : LSX_2R<0b0111001010011110010011>, -+ LSX_2RF_DESC_BASE<"vftintrz.l.d", fp_to_sint, LSX128DOpnd>; -+ -+ -+def VFTINTRNE_W_S : LSX_2R<0b0111001010011110010100>, -+ LSX_2RF_DESC_BASE<"vftintrne.w.s", int_loongarch_lsx_vftintrne_w_s, LSX128WOpnd>; -+ -+def VFTINTRNE_L_D : LSX_2R<0b0111001010011110010101>, -+ LSX_2RF_DESC_BASE<"vftintrne.l.d", int_loongarch_lsx_vftintrne_l_d, LSX128DOpnd>; -+ -+ -+def VFTINTL_L_S : LSX_2R<0b0111001010011110100000>, -+ LSX_2RF_DESC_BASE<"vftintl.l.s", int_loongarch_lsx_vftintl_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFTINTH_L_S : LSX_2R<0b0111001010011110100001>, -+ LSX_2RF_DESC_BASE<"vftinth.l.s", int_loongarch_lsx_vftinth_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFTINTRML_L_S : LSX_2R<0b0111001010011110100010>, -+ LSX_2RF_DESC_BASE<"vftintrml.l.s", int_loongarch_lsx_vftintrml_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFTINTRMH_L_S : LSX_2R<0b0111001010011110100011>, -+ LSX_2RF_DESC_BASE<"vftintrmh.l.s", int_loongarch_lsx_vftintrmh_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFTINTRPL_L_S : LSX_2R<0b0111001010011110100100>, -+ LSX_2RF_DESC_BASE<"vftintrpl.l.s", int_loongarch_lsx_vftintrpl_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFTINTRPH_L_S : LSX_2R<0b0111001010011110100101>, -+ LSX_2RF_DESC_BASE<"vftintrph.l.s", int_loongarch_lsx_vftintrph_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFTINTRZL_L_S : LSX_2R<0b0111001010011110100110>, -+ LSX_2RF_DESC_BASE<"vftintrzl.l.s", int_loongarch_lsx_vftintrzl_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFTINTRZH_L_S : LSX_2R<0b0111001010011110100111>, -+ LSX_2RF_DESC_BASE<"vftintrzh.l.s", int_loongarch_lsx_vftintrzh_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VFTINTRNEL_L_S : LSX_2R<0b0111001010011110101000>, -+ LSX_2RF_DESC_BASE<"vftintrnel.l.s", int_loongarch_lsx_vftintrnel_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+def VFTINTRNEH_L_S : LSX_2R<0b0111001010011110101001>, -+ LSX_2RF_DESC_BASE<"vftintrneh.l.s", int_loongarch_lsx_vftintrneh_l_s, LSX128DOpnd, LSX128WOpnd>; -+ -+ -+def VEXTH_H_B : LSX_2R<0b0111001010011110111000>, -+ LSX_2R_DESC_BASE<"vexth.h.b", int_loongarch_lsx_vexth_h_b, LSX128HOpnd, LSX128BOpnd>; -+ -+def VEXTH_W_H : LSX_2R<0b0111001010011110111001>, -+ LSX_2R_DESC_BASE<"vexth.w.h", int_loongarch_lsx_vexth_w_h, LSX128WOpnd, LSX128HOpnd>; -+ -+def VEXTH_D_W : LSX_2R<0b0111001010011110111010>, -+ LSX_2R_DESC_BASE<"vexth.d.w", int_loongarch_lsx_vexth_d_w, LSX128DOpnd, LSX128WOpnd> ; -+ -+def VEXTH_Q_D : LSX_2R<0b0111001010011110111011>, -+ LSX_2R_DESC_BASE<"vexth.q.d", int_loongarch_lsx_vexth_q_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VEXTH_HU_BU : LSX_2R<0b0111001010011110111100>, -+ LSX_2R_DESC_BASE<"vexth.hu.bu", int_loongarch_lsx_vexth_hu_bu, LSX128HOpnd, LSX128BOpnd>; -+ -+def VEXTH_WU_HU : LSX_2R<0b0111001010011110111101>, -+ LSX_2R_DESC_BASE<"vexth.wu.hu", int_loongarch_lsx_vexth_wu_hu, LSX128WOpnd, LSX128HOpnd>; -+ -+def VEXTH_DU_WU : LSX_2R<0b0111001010011110111110>, -+ LSX_2R_DESC_BASE<"vexth.du.wu", int_loongarch_lsx_vexth_du_wu, LSX128DOpnd, LSX128WOpnd> ; -+ -+def VEXTH_QU_DU : LSX_2R<0b0111001010011110111111>, -+ LSX_2R_DESC_BASE<"vexth.qu.du", int_loongarch_lsx_vexth_qu_du, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSLLWIL_H_B : LSX_I3_U<0b0111001100001000001>, -+ LSX_2R_U3_DESC_BASE<"vsllwil.h.b", int_loongarch_lsx_vsllwil_h_b, LSX128HOpnd, LSX128BOpnd>; -+ -+def VSLLWIL_W_H : LSX_I4_U<0b011100110000100001>, -+ LSX_2R_U4_DESC_BASE<"vsllwil.w.h", int_loongarch_lsx_vsllwil_w_h, LSX128WOpnd, LSX128HOpnd>; -+ -+def VSLLWIL_D_W : LSX_I5_U<0b01110011000010001>, -+ LSX_2R_U5_DESC_BASE<"vsllwil.d.w", int_loongarch_lsx_vsllwil_d_w, LSX128DOpnd, LSX128WOpnd> ; -+ -+ -+def VEXTL_Q_D : LSX_2R<0b0111001100001001000000>, -+ LSX_2R_DESC_BASE<"vextl.q.d", int_loongarch_lsx_vextl_q_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSLLWIL_HU_BU : LSX_I3_U<0b0111001100001100001>, -+ LSX_2R_U3_DESC_BASE<"vsllwil.hu.bu", int_loongarch_lsx_vsllwil_hu_bu, LSX128HOpnd, LSX128BOpnd>; -+ -+def VSLLWIL_WU_HU : LSX_I4_U<0b011100110000110001>, -+ LSX_2R_U4_DESC_BASE<"vsllwil.wu.hu", int_loongarch_lsx_vsllwil_wu_hu, LSX128WOpnd, LSX128HOpnd>; -+ -+def VSLLWIL_DU_WU : LSX_I5_U<0b01110011000011001>, -+ LSX_2R_U5_DESC_BASE<"vsllwil.du.wu", int_loongarch_lsx_vsllwil_du_wu, LSX128DOpnd, LSX128WOpnd> ; -+ -+ -+def VEXTL_QU_DU : LSX_2R<0b0111001100001101000000>, -+ LSX_2R_DESC_BASE<"vextl.qu.du", int_loongarch_lsx_vextl_qu_du, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VBITCLRI_B : LSX_I3_U<0b0111001100010000001>, -+ LSX_2R_U3_DESC_BASE<"vbitclri.b", int_loongarch_lsx_vbitclri_b, LSX128BOpnd, LSX128BOpnd>; -+ -+def VBITCLRI_H : LSX_I4_U<0b011100110001000001>, -+ LSX_2R_U4_DESC_BASE<"vbitclri.h", int_loongarch_lsx_vbitclri_h, LSX128HOpnd, LSX128HOpnd>; -+ -+def VBITCLRI_W : LSX_I5_U<0b01110011000100001>, -+ LSX_2R_U5_DESC_BASE<"vbitclri.w", int_loongarch_lsx_vbitclri_w, LSX128WOpnd, LSX128WOpnd>; -+ -+def VBITCLRI_D : LSX_I6_U<0b0111001100010001>, -+ LSX_2R_U6_DESC_BASE<"vbitclri.d", int_loongarch_lsx_vbitclri_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VBITSETI_B : LSX_I3_U<0b0111001100010100001>, -+ LSX_2R_U3_DESC_BASE<"vbitseti.b", int_loongarch_lsx_vbitseti_b, LSX128BOpnd, LSX128BOpnd>; -+ -+def VBITSETI_H : LSX_I4_U<0b011100110001010001>, -+ LSX_2R_U4_DESC_BASE<"vbitseti.h", int_loongarch_lsx_vbitseti_h, LSX128HOpnd, LSX128HOpnd>; -+ -+def VBITSETI_W : LSX_I5_U<0b01110011000101001>, -+ LSX_2R_U5_DESC_BASE<"vbitseti.w", int_loongarch_lsx_vbitseti_w, LSX128WOpnd, LSX128WOpnd>; -+ -+def VBITSETI_D : LSX_I6_U<0b0111001100010101>, -+ LSX_2R_U6_DESC_BASE<"vbitseti.d", int_loongarch_lsx_vbitseti_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VBITREVI_B : LSX_I3_U<0b0111001100011000001>, -+ LSX_2R_U3_DESC_BASE<"vbitrevi.b", int_loongarch_lsx_vbitrevi_b, LSX128BOpnd, LSX128BOpnd>; -+ -+def VBITREVI_H : LSX_I4_U<0b011100110001100001>, -+ LSX_2R_U4_DESC_BASE<"vbitrevi.h", int_loongarch_lsx_vbitrevi_h, LSX128HOpnd, LSX128HOpnd>; -+ -+def VBITREVI_W : LSX_I5_U<0b01110011000110001>, -+ LSX_2R_U5_DESC_BASE<"vbitrevi.w", int_loongarch_lsx_vbitrevi_w, LSX128WOpnd, LSX128WOpnd>; -+ -+def VBITREVI_D : LSX_I6_U<0b0111001100011001>, -+ LSX_2R_U6_DESC_BASE<"vbitrevi.d", int_loongarch_lsx_vbitrevi_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSSRLRNI_B_H : LSX_I4_U<0b011100110101000001>, -+ LSX_2R_3R_U4_DESC_BASE<"vssrlrni.b.h", int_loongarch_lsx_vssrlrni_b_h, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSSRLRNI_H_W : LSX_I5_U<0b01110011010100001>, -+ LSX_2R_3R_U5_DESC_BASE<"vssrlrni.h.w", int_loongarch_lsx_vssrlrni_h_w, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSSRLRNI_W_D : LSX_I6_U<0b0111001101010001>, -+ LSX_2R_3R_U6_DESC_BASE<"vssrlrni.w.d", int_loongarch_lsx_vssrlrni_w_d, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSSRLRNI_D_Q : LSX_I7_U<0b011100110101001>, -+ LSX_2R_3R_U7_DESC_BASE<"vssrlrni.d.q", int_loongarch_lsx_vssrlrni_d_q, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VSRANI_B_H : LSX_I4_U<0b011100110101100001>, -+ LSX_2R_3R_U4_DESC_BASE<"vsrani.b.h", int_loongarch_lsx_vsrani_b_h, LSX128BOpnd, LSX128BOpnd>; -+ -+def VSRANI_H_W : LSX_I5_U<0b01110011010110001>, -+ LSX_2R_3R_U5_DESC_BASE<"vsrani.h.w", int_loongarch_lsx_vsrani_h_w, LSX128HOpnd, LSX128HOpnd>; -+ -+def VSRANI_W_D : LSX_I6_U<0b0111001101011001>, -+ LSX_2R_3R_U6_DESC_BASE<"vsrani.w.d", int_loongarch_lsx_vsrani_w_d, LSX128WOpnd, LSX128WOpnd>; -+ -+def VSRANI_D_Q : LSX_I7_U<0b011100110101101>, -+ LSX_2R_3R_U7_DESC_BASE<"vsrani.d.q", int_loongarch_lsx_vsrani_d_q, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VEXTRINS_B : LSX_I8_U<0b01110011100011>, -+ LSX_2R_3R_U8_DESC_BASE<"vextrins.b", int_loongarch_lsx_vextrins_b, LSX128BOpnd, LSX128BOpnd>; -+ -+def VEXTRINS_H : LSX_I8_U<0b01110011100010>, -+ LSX_2R_3R_U8_DESC_BASE<"vextrins.h", int_loongarch_lsx_vextrins_h, LSX128HOpnd, LSX128HOpnd>; -+ -+def VEXTRINS_W : LSX_I8_U<0b01110011100001>, -+ LSX_2R_3R_U8_DESC_BASE<"vextrins.w", int_loongarch_lsx_vextrins_w, LSX128WOpnd, LSX128WOpnd>; -+ -+def VEXTRINS_D : LSX_I8_U<0b01110011100000>, -+ LSX_2R_3R_U8_DESC_BASE<"vextrins.d", int_loongarch_lsx_vextrins_d, LSX128DOpnd, LSX128DOpnd>; -+ -+ -+def VBITSELI_B : LSX_I8_U<0b01110011110001>, -+ LSX_2R_3R_U8_DESC_BASE<"vbitseli.b", int_loongarch_lsx_vbitseli_b, LSX128BOpnd, LSX128BOpnd>; -+ -+ -+def VANDI_B : LSX_I8_U<0b01110011110100>, -+ LSX_2R_U8_DESC_BASE<"vandi.b", int_loongarch_lsx_vandi_b, LSX128BOpnd, LSX128BOpnd>; -+ -+ -+def VORI_B : LSX_I8_U<0b01110011110101>, -+ LSX_2R_U8_DESC_BASE<"vori.b", int_loongarch_lsx_vori_b, LSX128BOpnd, LSX128BOpnd>; -+ -+ -+def VXORI_B : LSX_I8_U<0b01110011110110>, -+ LSX_2R_U8_DESC_BASE<"vxori.b", int_loongarch_lsx_vxori_b, LSX128BOpnd, LSX128BOpnd>; -+ -+ -+def VNORI_B : LSX_I8_U<0b01110011110111>, -+ LSX_2R_U8_DESC_BASE<"vnori.b", int_loongarch_lsx_vnori_b, LSX128BOpnd, LSX128BOpnd>; -+ -+ -+def VLDI : LSX_1R_I13<0b01110011111000>, -+ LSX_I13_DESC_BASE<"vldi", int_loongarch_lsx_vldi, i32, simm13Op, LSX128DOpnd>; -+ -+def VLDI_B : LSX_1R_I13_I10<0b01110011111000000>, -+ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_b, simm10, immZExt10, LSX128BOpnd>; -+ -+def VLDI_H : LSX_1R_I13_I10<0b01110011111000001>, -+ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_h, simm10, immZExt10, LSX128HOpnd>; -+ -+def VLDI_W : LSX_1R_I13_I10<0b01110011111000010>, -+ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_w, simm10, immZExt10, LSX128WOpnd>; -+ -+def VLDI_D : LSX_1R_I13_I10<0b01110011111000011>, -+ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_d, simm10, immZExt10, LSX128DOpnd>; -+ -+def VPERMI_W : LSX_I8_U<0b01110011111001>, -+ LSX_2R_3R_U8_DESC_BASE<"vpermi.w", int_loongarch_lsx_vpermi_w, LSX128WOpnd, LSX128WOpnd>; -+ -+ -+def VSEQ_B : LSX_3R<0b01110000000000000>, IsCommutable, -+ LSX_3R_DESC_BASE<"vseq.b", vseteq_v16i8, LSX128BOpnd>; -+ -+def VSEQ_H : LSX_3R<0b01110000000000001>, IsCommutable, -+ LSX_3R_DESC_BASE<"vseq.h", vseteq_v8i16, LSX128HOpnd>; -+ -+def VSEQ_W : LSX_3R<0b01110000000000010>, IsCommutable, -+ LSX_3R_DESC_BASE<"vseq.w", vseteq_v4i32, LSX128WOpnd> ; -+ -+def VSEQ_D : LSX_3R<0b01110000000000011>, IsCommutable, -+ LSX_3R_DESC_BASE<"vseq.d", vseteq_v2i64, LSX128DOpnd>; -+ -+ -+def VSLE_B : LSX_3R<0b01110000000000100>, -+ LSX_3R_DESC_BASE<"vsle.b", vsetle_v16i8, LSX128BOpnd>; -+ -+def VSLE_H : LSX_3R<0b01110000000000101>, -+ LSX_3R_DESC_BASE<"vsle.h", vsetle_v8i16, LSX128HOpnd>; -+ -+def VSLE_W : LSX_3R<0b01110000000000110>, -+ LSX_3R_DESC_BASE<"vsle.w", vsetle_v4i32, LSX128WOpnd>; -+ -+def VSLE_D : LSX_3R<0b01110000000000111>, -+ LSX_3R_DESC_BASE<"vsle.d", vsetle_v2i64, LSX128DOpnd>; -+ -+ -+def VSLE_BU : LSX_3R<0b01110000000001000>, -+ LSX_3R_DESC_BASE<"vsle.bu", vsetule_v16i8, LSX128BOpnd>; -+ -+def VSLE_HU : LSX_3R<0b01110000000001001>, -+ LSX_3R_DESC_BASE<"vsle.hu", vsetule_v8i16, LSX128HOpnd>; -+ -+def VSLE_WU : LSX_3R<0b01110000000001010>, -+ LSX_3R_DESC_BASE<"vsle.wu", vsetule_v4i32, LSX128WOpnd>; -+ -+def VSLE_DU : LSX_3R<0b01110000000001011>, -+ LSX_3R_DESC_BASE<"vsle.du", vsetule_v2i64, LSX128DOpnd>; -+ -+ -+def VSLT_B : LSX_3R<0b01110000000001100>, -+ LSX_3R_DESC_BASE<"vslt.b", vsetlt_v16i8, LSX128BOpnd>; -+ -+def VSLT_H : LSX_3R<0b01110000000001101>, -+ LSX_3R_DESC_BASE<"vslt.h", vsetlt_v8i16, LSX128HOpnd>; -+ -+def VSLT_W : LSX_3R<0b01110000000001110>, -+ LSX_3R_DESC_BASE<"vslt.w", vsetlt_v4i32, LSX128WOpnd>; -+ -+def VSLT_D : LSX_3R<0b01110000000001111>, -+ LSX_3R_DESC_BASE<"vslt.d", vsetlt_v2i64, LSX128DOpnd>; -+ -+ -+def VSLT_BU : LSX_3R<0b01110000000010000>, -+ LSX_3R_DESC_BASE<"vslt.bu", vsetult_v16i8, LSX128BOpnd>; -+ -+def VSLT_HU : LSX_3R<0b01110000000010001>, -+ LSX_3R_DESC_BASE<"vslt.hu", vsetult_v8i16, LSX128HOpnd>; -+ -+def VSLT_WU : LSX_3R<0b01110000000010010>, -+ LSX_3R_DESC_BASE<"vslt.wu", vsetult_v4i32, LSX128WOpnd>; -+ -+def VSLT_DU : LSX_3R<0b01110000000010011>, -+ LSX_3R_DESC_BASE<"vslt.du", vsetult_v2i64, LSX128DOpnd>; -+ -+ -+def VADD_B : LSX_3R<0b01110000000010100>, IsCommutable, -+ LSX_3R_DESC_BASE<"vadd.b", add, LSX128BOpnd>; -+ -+def VADD_H : LSX_3R<0b01110000000010101>, IsCommutable, -+ LSX_3R_DESC_BASE<"vadd.h", add, LSX128HOpnd>; -+ -+def VADD_W : LSX_3R<0b01110000000010110>, IsCommutable, -+ LSX_3R_DESC_BASE<"vadd.w", add, LSX128WOpnd>; -+ -+def VADD_D : LSX_3R<0b01110000000010111>, IsCommutable, -+ LSX_3R_DESC_BASE<"vadd.d", add, LSX128DOpnd>; -+ -+ -+def VSUB_B : LSX_3R<0b01110000000011000>, -+ LSX_3R_DESC_BASE<"vsub.b", sub, LSX128BOpnd>; -+ -+def VSUB_H : LSX_3R<0b01110000000011001>, -+ LSX_3R_DESC_BASE<"vsub.h", sub, LSX128HOpnd>; -+ -+def VSUB_W : LSX_3R<0b01110000000011010>, -+ LSX_3R_DESC_BASE<"vsub.w", sub, LSX128WOpnd>; -+ -+def VSUB_D : LSX_3R<0b01110000000011011>, -+ LSX_3R_DESC_BASE<"vsub.d", sub, LSX128DOpnd>; -+ -+ -+ -+//Pat -+class LSXBitconvertPat preds = [HasLSX]> : -+ LSXPat<(DstVT (bitconvert SrcVT:$src)), -+ (COPY_TO_REGCLASS SrcVT:$src, DstRC), preds>; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+def : LSXBitconvertPat; -+ -+ -+ -+ -+def : LSXPat<(i32 (vextract_sext_i8 v16i8:$vj, i32:$idx)), -+ (SRAI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_B v16i8:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32), (i32 24))>; -+def : LSXPat<(i32 (vextract_sext_i16 v8i16:$vj, i32:$idx)), -+ (SRAI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_H v8i16:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32), (i32 16))>; -+def : LSXPat<(i32 (vextract_sext_i32 v4i32:$vj, i32:$idx)), -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_W v4i32:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32)>; -+def : LSXPat<(i64 (vextract_sext_i64 v2i64:$vj, i32:$idx)), -+ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (VREPLVE_D v2i64:$vj, -+ i32:$idx), -+ sub_64)), -+ GPR64)>; -+ -+def : LSXPat<(i32 (vextract_zext_i8 v16i8:$vj, i32:$idx)), -+ (SRLI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_B v16i8:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32), (i32 24))>; -+def : LSXPat<(i32 (vextract_zext_i16 v8i16:$vj, i32:$idx)), -+ (SRLI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_H v8i16:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32), (i32 16))>; -+def : LSXPat<(i32 (vextract_zext_i32 v4i32:$vj, i32:$idx)), -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_W v4i32:$vj, -+ i32:$idx), -+ sub_lo)), -+ GPR32)>; -+ -+def : LSXPat<(i64 (vextract_zext_i64 v2i64:$vj, i32:$idx)), -+ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (VREPLVE_D v2i64:$vj, -+ i32:$idx), -+ sub_64)), -+ GPR64)>; -+ -+def : LSXPat<(f32 (vector_extract v4f32:$vj, i32:$idx)), -+ (f32 (EXTRACT_SUBREG (VREPLVE_W v4f32:$vj, -+ i32:$idx), -+ sub_lo))>; -+def : LSXPat<(f64 (vector_extract v2f64:$vj, i32:$idx)), -+ (f64 (EXTRACT_SUBREG (VREPLVE_D v2f64:$vj, -+ i32:$idx), -+ sub_64))>; -+ -+def : LSXPat< -+ (i32 (vextract_sext_i8 v16i8:$vj, i64:$idx)), -+ (SRAI_W (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_B v16i8:$vj, -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32), -+ (i32 24))>; -+def : LSXPat< -+ (i32 (vextract_sext_i16 v8i16:$vj, i64:$idx)), -+ (SRAI_W (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_H v8i16:$vj, -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32), -+ (i32 16))>; -+ -+def : LSXPat< -+ (i32 (vextract_sext_i32 v4i32:$vj, i64:$idx)), -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_W v4i32:$vj, -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32)>; -+ -+def : LSXPat< -+ (i64 (vextract_sext_i64 v2i64:$vj, i64:$idx)), -+ (COPY_TO_REGCLASS -+ (i64 (EXTRACT_SUBREG -+ (VREPLVE_D v2i64:$vj, -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_64)), -+ GPR64)>; -+ -+def : LSXPat< -+ (i32 (vextract_zext_i8 v16i8:$vj, i64:$idx)), -+ (SRLI_W (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_B v16i8:$vj, -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32), -+ (i32 24))>; -+def : LSXPat< -+ (i32 (vextract_zext_i16 v8i16:$vj, i64:$idx)), -+ (SRLI_W (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_H v8i16:$vj, -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32), -+ (i32 16))>; -+def : LSXPat< -+ (i32 (vextract_zext_i32 v4i32:$vj, i64:$idx)), -+ (COPY_TO_REGCLASS -+ (i32 (EXTRACT_SUBREG -+ (VREPLVE_W v4i32:$vj, -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo)), -+ GPR32)>; -+def : LSXPat< -+ (i64 (vextract_zext_i64 v2i64:$vj, i64:$idx)), -+ (COPY_TO_REGCLASS -+ (i64 (EXTRACT_SUBREG -+ (VREPLVE_D v2i64:$vj, -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_64)), -+ GPR64)>; -+ -+ def : LSXPat< -+ (f32 (vector_extract v4f32:$vj, i64:$idx)), -+ (f32 (EXTRACT_SUBREG -+ (VREPLVE_W v4f32:$vj, -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_lo))>; -+def : LSXPat< -+ (f64 (vector_extract v2f64:$vj, i64:$idx)), -+ (f64 (EXTRACT_SUBREG -+ (VREPLVE_D v2f64:$vj, -+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), -+ sub_64))>; -+ -+ -+def : LSXPat<(vfseteq_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), -+ (VFCMP_CEQ_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; -+ -+def : LSXPat<(vfseteq_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), -+ (VFCMP_CEQ_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; -+ -+def : LSXPat<(vfsetle_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), -+ (VFCMP_CLE_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; -+ -+def : LSXPat<(vfsetle_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), -+ (VFCMP_CLE_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; -+ -+def : LSXPat<(vfsetlt_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), -+ (VFCMP_CLT_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; -+ -+def : LSXPat<(vfsetlt_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), -+ (VFCMP_CLT_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; -+ -+def : LSXPat<(vfsetne_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), -+ (VFCMP_CNE_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; -+ -+def : LSXPat<(vfsetne_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), -+ (VFCMP_CNE_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; -+ -+ -+class LSX_INSERT_PSEUDO_BASE : -+ LSXPseudo<(outs ROVD:$vd), (ins ROVD:$vd_in, ImmOp:$n, ROFS:$fs), -+ [(set ROVD:$vd, (OpNode (Ty ROVD:$vd_in), ROFS:$fs, Imm:$n))]> { -+ bit usesCustomInserter = 1; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+ -+class INSERT_FW_PSEUDO_DESC : LSX_INSERT_PSEUDO_BASE; -+class INSERT_FD_PSEUDO_DESC : LSX_INSERT_PSEUDO_BASE; -+ -+def INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC; -+def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC; -+ -+ -+class LSX_INSERT_VIDX_PSEUDO_BASE : -+ LSXPseudo<(outs ROVD:$vd), (ins ROVD:$vd_in, ROIdx:$n, ROFS:$fs), -+ [(set ROVD:$vd, (OpNode (Ty ROVD:$vd_in), ROFS:$fs, -+ ROIdx:$n))]> { -+ bit usesCustomInserter = 1; -+ string Constraints = "$vd = $vd_in"; -+} -+ -+class INSERT_H_VIDX64_PSEUDO_DESC : -+ LSX_INSERT_VIDX_PSEUDO_BASE; -+def INSERT_H_VIDX64_PSEUDO : INSERT_H_VIDX64_PSEUDO_DESC; -+ -+class INSERTPostRA : -+ LoongArchPseudo<(outs RC:$xd), (ins RC:$xd_in, RD:$n, RE:$fs), []> { -+ let mayLoad = 1; -+ let mayStore = 1; -+} -+ -+def INSERT_H_VIDX64_PSEUDO_POSTRA : INSERTPostRA; -+ -+class LSX_COPY_PSEUDO_BASE : -+ LSXPseudo<(outs RCD:$vd), (ins RCVS:$vj, ImmOp:$n), -+ [(set RCD:$vd, (OpNode (VecTy RCVS:$vj), Imm:$n))]> { -+ bit usesCustomInserter = 1; -+} -+ -+ -+class COPY_FW_PSEUDO_DESC : LSX_COPY_PSEUDO_BASE; -+class COPY_FD_PSEUDO_DESC : LSX_COPY_PSEUDO_BASE; -+def COPY_FW_PSEUDO : COPY_FW_PSEUDO_DESC; -+def COPY_FD_PSEUDO : COPY_FD_PSEUDO_DESC; -+ -+ -+let isCodeGenOnly = 1 in { -+ -+def VST_H : LSX_I12_S<0b0010110001>, -+ ST_DESC_BASE<"vst", store, v8i16, LSX128HOpnd, mem_simm12>; -+def VST_W : LSX_I12_S<0b0010110001>, -+ ST_DESC_BASE<"vst", store, v4i32, LSX128WOpnd, mem_simm12>; -+def VST_D : LSX_I12_S<0b0010110001>, -+ ST_DESC_BASE<"vst", store, v2i64, LSX128DOpnd, mem_simm12>; -+ -+ -+def VLD_H : LSX_I12_S<0b0010110000>, -+ LD_DESC_BASE<"vld", load, v8i16, LSX128HOpnd, mem_simm12>; -+def VLD_W : LSX_I12_S<0b0010110000>, -+ LD_DESC_BASE<"vld", load, v4i32, LSX128WOpnd, mem_simm12>; -+def VLD_D : LSX_I12_S<0b0010110000>, -+ LD_DESC_BASE<"vld", load, v2i64, LSX128DOpnd, mem_simm12>; -+ -+ -+ -+def VANDI_B_N : LSX_I8_U<0b01110011110100>, -+ LSX_BIT_U8_VREPLVE_DESC_BASE<"vandi.b", and, vsplati8_uimm8, LSX128BOpnd>; -+ -+ -+def VXORI_B_N : LSX_I8_U<0b01110011110110>, -+ LSX_BIT_U8_VREPLVE_DESC_BASE<"vxori.b", xor, vsplati8_uimm8, LSX128BOpnd>; -+ -+ -+def VSRAI_B_N : LSX_I3_U<0b0111001100110100001>, -+ LSX_BIT_U3_VREPLVE_DESC_BASE<"vsrai.b", sra, vsplati8_uimm3, LSX128BOpnd>; -+ -+def VSRAI_H_N : LSX_I4_U<0b011100110011010001>, -+ LSX_BIT_U4_VREPLVE_DESC_BASE<"vsrai.h", sra, vsplati16_uimm4, LSX128HOpnd>; -+ -+def VSRAI_W_N : LSX_I5_U<0b01110011001101001>, -+ LSX_BIT_U5_VREPLVE_DESC_BASE<"vsrai.w", sra, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSRAI_D_N : LSX_I6_U<0b0111001100110101>, -+ LSX_BIT_U6_VREPLVE_DESC_BASE<"vsrai.d", sra, vsplati64_uimm6, LSX128DOpnd>; -+ -+ -+def VMAXI_BU_N : LSX_I5_U<0b01110010100101000>, -+ LSX_I5_U_DESC_BASE<"vmaxi.bu", umax, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VMAXI_HU_N : LSX_I5_U<0b01110010100101001>, -+ LSX_I5_U_DESC_BASE<"vmaxi.hu", umax, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VMAXI_WU_N : LSX_I5_U<0b01110010100101010>, -+ LSX_I5_U_DESC_BASE<"vmaxi.wu", umax, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VMAXI_DU_N : LSX_I5_U<0b01110010100101011>, -+ LSX_I5_U_DESC_BASE<"vmaxi.du", umax, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VMINI_B_N : LSX_I5<0b01110010100100100>, -+ LSX_I5_DESC_BASE<"vmini.b", smin, vsplati8_simm5, LSX128BOpnd>; -+ -+def VMINI_H_N : LSX_I5<0b01110010100100101>, -+ LSX_I5_DESC_BASE<"vmini.h", smin, vsplati16_simm5, LSX128HOpnd>; -+ -+def VMINI_W_N : LSX_I5<0b01110010100100110>, -+ LSX_I5_DESC_BASE<"vmini.w", smin, vsplati32_simm5, LSX128WOpnd>; -+ -+def VMINI_D_N : LSX_I5<0b01110010100100111>, -+ LSX_I5_DESC_BASE<"vmini.d", smin, vsplati64_simm5, LSX128DOpnd>; -+ -+ -+def VMAXI_B_N : LSX_I5<0b01110010100100000>, -+ LSX_I5_DESC_BASE<"vmaxi.b", smax, vsplati8_simm5, LSX128BOpnd>; -+ -+def VMAXI_H_N : LSX_I5<0b01110010100100001>, -+ LSX_I5_DESC_BASE<"vmaxi.h", smax, vsplati16_simm5, LSX128HOpnd>; -+ -+def VMAXI_W_N : LSX_I5<0b01110010100100010>, -+ LSX_I5_DESC_BASE<"vmaxi.w", smax, vsplati32_simm5, LSX128WOpnd>; -+ -+def VMAXI_D_N : LSX_I5<0b01110010100100011>, -+ LSX_I5_DESC_BASE<"vmaxi.d", smax, vsplati64_simm5, LSX128DOpnd>; -+ -+ -+def VSEQI_B_N : LSX_I5<0b01110010100000000>, -+ LSX_I5_DESC_BASE<"vseqi.b", vseteq_v16i8, vsplati8_simm5, LSX128BOpnd>; -+ -+def VSEQI_H_N : LSX_I5<0b01110010100000001>, -+ LSX_I5_DESC_BASE<"vseqi.h", vseteq_v8i16, vsplati16_simm5, LSX128HOpnd>; -+ -+def VSEQI_W_N : LSX_I5<0b01110010100000010>, -+ LSX_I5_DESC_BASE<"vseqi.w", vseteq_v4i32, vsplati32_simm5, LSX128WOpnd>; -+ -+def VSEQI_D_N : LSX_I5<0b01110010100000011>, -+ LSX_I5_DESC_BASE<"vseqi.d", vseteq_v2i64, vsplati64_simm5, LSX128DOpnd>; -+ -+ -+def VSLEI_B_N : LSX_I5<0b01110010100000100>, -+ LSX_I5_DESC_BASE<"vslei.b", vsetle_v16i8, vsplati8_simm5, LSX128BOpnd>; -+ -+def VSLEI_H_N : LSX_I5<0b01110010100000101>, -+ LSX_I5_DESC_BASE<"vslei.h", vsetle_v8i16, vsplati16_simm5, LSX128HOpnd>; -+ -+def VSLEI_W_N : LSX_I5<0b01110010100000110>, -+ LSX_I5_DESC_BASE<"vslei.w", vsetle_v4i32, vsplati32_simm5, LSX128WOpnd>; -+ -+def VSLEI_D_N : LSX_I5<0b01110010100000111>, -+ LSX_I5_DESC_BASE<"vslei.d", vsetle_v2i64, vsplati64_simm5, LSX128DOpnd>; -+ -+def VSLEI_BU_N : LSX_I5_U<0b01110010100001000>, -+ LSX_I5_U_DESC_BASE<"vslei.bu", vsetule_v16i8, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VSLEI_HU_N : LSX_I5_U<0b01110010100001001>, -+ LSX_I5_U_DESC_BASE<"vslei.hu", vsetule_v8i16, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VSLEI_WU_N : LSX_I5_U<0b01110010100001010>, -+ LSX_I5_U_DESC_BASE<"vslei.wu", vsetule_v4i32, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSLEI_DU_N : LSX_I5_U<0b01110010100001011>, -+ LSX_I5_U_DESC_BASE<"vslei.du", vsetule_v2i64, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VSLTI_B_N : LSX_I5<0b01110010100001100>, -+ LSX_I5_DESC_BASE<"vslti.b", vsetlt_v16i8, vsplati8_simm5, LSX128BOpnd>; -+ -+def VSLTI_H_N : LSX_I5<0b01110010100001101>, -+ LSX_I5_DESC_BASE<"vslti.h", vsetlt_v8i16, vsplati16_simm5, LSX128HOpnd>; -+ -+def VSLTI_W_N : LSX_I5<0b01110010100001110>, -+ LSX_I5_DESC_BASE<"vslti.w", vsetlt_v4i32, vsplati32_simm5, LSX128WOpnd>; -+ -+def VSLTI_D_N : LSX_I5<0b01110010100001111>, -+ LSX_I5_DESC_BASE<"vslti.d", vsetlt_v2i64, vsplati64_simm5, LSX128DOpnd>; -+ -+ -+def VSLTI_BU_N : LSX_I5_U<0b01110010100010000>, -+ LSX_I5_U_DESC_BASE<"vslti.bu", vsetult_v16i8, vsplati8_uimm5, LSX128BOpnd>; -+ -+def VSLTI_HU_N : LSX_I5_U<0b01110010100010001>, -+ LSX_I5_U_DESC_BASE<"vslti.hu", vsetult_v8i16, vsplati16_uimm5, LSX128HOpnd>; -+ -+def VSLTI_WU_N : LSX_I5_U<0b01110010100010010>, -+ LSX_I5_U_DESC_BASE<"vslti.wu", vsetult_v4i32, vsplati32_uimm5, LSX128WOpnd>; -+ -+def VSLTI_DU_N : LSX_I5_U<0b01110010100010011>, -+ LSX_I5_U_DESC_BASE<"vslti.du", vsetult_v2i64, vsplati64_uimm5, LSX128DOpnd>; -+ -+ -+def VBITSELI_B_N : LSX_I8_U<0b01110011110001>, -+ LSX_2R_3R_SELECT<"vbitseli.b", vselect, LSX128BOpnd, LSX128BOpnd>; -+ -+} -+ -+ -+def : LSXPat<(v4f32 (load addrimm12:$addr)), (VLD_W addrimm12:$addr)>; -+def : LSXPat<(v2f64 (load addrimm12:$addr)), (VLD_D addrimm12:$addr)>; -+ -+def VST_FW : LSXPat<(store (v4f32 LSX128W:$vj), addrimm12:$addr), -+ (VST_W LSX128W:$vj, addrimm12:$addr)>; -+def VST_FD : LSXPat<(store (v2f64 LSX128D:$vj), addrimm12:$addr), -+ (VST_D LSX128D:$vj, addrimm12:$addr)>; -+ -+def VNEG_FW : LSXPat<(fneg (v4f32 LSX128W:$vj)), -+ (VBITREVI_W LSX128W:$vj, 31)>; -+def VNEG_FD : LSXPat<(fneg (v2f64 LSX128D:$vj)), -+ (VBITREVI_D LSX128D:$vj, 63)>; -+ -+ -+def : LSXPat<(v2i64 (LoongArchVABSD v2i64:$vj, v2i64:$vk, (i32 0))), -+ (v2i64 (VABSD_D $vj, $vk))>; -+ -+def : LSXPat<(v4i32 (LoongArchVABSD v4i32:$vj, v4i32:$vk, (i32 0))), -+ (v4i32 (VABSD_W $vj, $vk))>; -+ -+def : LSXPat<(v8i16 (LoongArchVABSD v8i16:$vj, v8i16:$vk, (i32 0))), -+ (v8i16 (VABSD_H $vj, $vk))>; -+ -+def : LSXPat<(v16i8 (LoongArchVABSD v16i8:$vj, v16i8:$vk, (i32 0))), -+ (v16i8 (VABSD_B $vj, $vk))>; -+ -+def : LSXPat<(v2i64 (LoongArchUVABSD v2i64:$vj, v2i64:$vk, (i32 0))), -+ (v2i64 (VABSD_DU $vj, $vk))>; -+ -+def : LSXPat<(v4i32 (LoongArchUVABSD v4i32:$vj, v4i32:$vk, (i32 0))), -+ (v4i32 (VABSD_WU $vj, $vk))>; -+ -+def : LSXPat<(v8i16 (LoongArchUVABSD v8i16:$vj, v8i16:$vk, (i32 0))), -+ (v8i16 (VABSD_HU $vj, $vk))>; -+ -+def : LSXPat<(v16i8 (LoongArchUVABSD v16i8:$vj, v16i8:$vk, (i32 0))), -+ (v16i8 (VABSD_BU $vj, $vk))>; -+ -+ -+def : LSXPat<(or v16i8:$vj, (shl vsplat_imm_eq_1, v16i8:$vk)), -+ (VBITSET_B v16i8:$vj, v16i8:$vk)>; -+def : LSXPat<(or v8i16:$vj, (shl vsplat_imm_eq_1, v8i16:$vk)), -+ (VBITSET_H v8i16:$vj, v8i16:$vk)>; -+def : LSXPat<(or v4i32:$vj, (shl vsplat_imm_eq_1, v4i32:$vk)), -+ (VBITSET_W v4i32:$vj, v4i32:$vk)>; -+def : LSXPat<(or v2i64:$vj, (shl vsplat_imm_eq_1, v2i64:$vk)), -+ (VBITSET_D v2i64:$vj, v2i64:$vk)>; -+ -+def : LSXPat<(xor v16i8:$vj, (shl vsplat_imm_eq_1, v16i8:$vk)), -+ (VBITREV_B v16i8:$vj, v16i8:$vk)>; -+def : LSXPat<(xor v8i16:$vj, (shl vsplat_imm_eq_1, v8i16:$vk)), -+ (VBITREV_H v8i16:$vj, v8i16:$vk)>; -+def : LSXPat<(xor v4i32:$vj, (shl vsplat_imm_eq_1, v4i32:$vk)), -+ (VBITREV_W v4i32:$vj, v4i32:$vk)>; -+def : LSXPat<(xor v2i64:$vj, (shl (v2i64 vsplati64_imm_eq_1), v2i64:$vk)), -+ (VBITREV_D v2i64:$vj, v2i64:$vk)>; -+ -+def : LSXPat<(and v16i8:$vj, (xor (shl vsplat_imm_eq_1, v16i8:$vk), immAllOnesV)), -+ (VBITCLR_B v16i8:$vj, v16i8:$vk)>; -+def : LSXPat<(and v8i16:$vj, (xor (shl vsplat_imm_eq_1, v8i16:$vk), immAllOnesV)), -+ (VBITCLR_H v8i16:$vj, v8i16:$vk)>; -+def : LSXPat<(and v4i32:$vj, (xor (shl vsplat_imm_eq_1, v4i32:$vk), immAllOnesV)), -+ (VBITCLR_W v4i32:$vj, v4i32:$vk)>; -+def : LSXPat<(and v2i64:$vj, (xor (shl (v2i64 vsplati64_imm_eq_1), v2i64:$vk), (bitconvert (v4i32 immAllOnesV)))), -+ (VBITCLR_D v2i64:$vj, v2i64:$vk)>; -+def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ -+ APInt Imm; -+ SDNode *BV = N->getOperand(0).getNode(); -+ EVT EltTy = N->getValueType(0).getVectorElementType(); -+ -+ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && -+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63; -+}]>; -+ -+def immi32Cst7 : ImmLeaf(Imm) && Imm == 7;}]>; -+def immi32Cst15 : ImmLeaf(Imm) && Imm == 15;}]>; -+def immi32Cst31 : ImmLeaf(Imm) && Imm == 31;}]>; -+ -+def vsplati8imm7 : PatFrag<(ops node:$vt), -+ (and node:$vt, (vsplati8 immi32Cst7))>; -+def vsplati16imm15 : PatFrag<(ops node:$vt), -+ (and node:$vt, (vsplati16 immi32Cst15))>; -+def vsplati32imm31 : PatFrag<(ops node:$vt), -+ (and node:$vt, (vsplati32 immi32Cst31))>; -+def vsplati64imm63 : PatFrag<(ops node:$vt), -+ (and node:$vt, vsplati64_imm_eq_63)>; -+ -+class LSXShiftPat : -+ LSXPat<(VT (Node VT:$vs, (VT (and VT:$vt, Vec)))), -+ (VT (Insn VT:$vs, VT:$vt))>; -+ -+class LSXBitPat : -+ LSXPat<(VT (Node VT:$vs, (shl vsplat_imm_eq_1, (Frag VT:$vt)))), -+ (VT (Insn VT:$vs, VT:$vt))>; -+ -+multiclass LSXShiftPats { -+ def : LSXShiftPat(Insn#_B), -+ (vsplati8 immi32Cst7)>; -+ def : LSXShiftPat(Insn#_H), -+ (vsplati16 immi32Cst15)>; -+ def : LSXShiftPat(Insn#_W), -+ (vsplati32 immi32Cst31)>; -+ def : LSXPat<(v2i64 (Node v2i64:$vs, (v2i64 (and v2i64:$vt, -+ vsplati64_imm_eq_63)))), -+ (v2i64 (!cast(Insn#_D) v2i64:$vs, v2i64:$vt))>; -+} -+ -+multiclass LSXBitPats { -+ def : LSXBitPat(Insn#_B), vsplati8imm7>; -+ def : LSXBitPat(Insn#_H), vsplati16imm15>; -+ def : LSXBitPat(Insn#_W), vsplati32imm31>; -+ def : LSXPat<(Node v2i64:$vs, (shl (v2i64 vsplati64_imm_eq_1), -+ (vsplati64imm63 v2i64:$vt))), -+ (v2i64 (!cast(Insn#_D) v2i64:$vs, v2i64:$vt))>; -+} -+ -+defm : LSXShiftPats; -+defm : LSXShiftPats; -+defm : LSXShiftPats; -+defm : LSXBitPats; -+defm : LSXBitPats; -+ -+def : LSXPat<(and v16i8:$vs, (xor (shl vsplat_imm_eq_1, -+ (vsplati8imm7 v16i8:$vt)), -+ immAllOnesV)), -+ (v16i8 (VBITCLR_B v16i8:$vs, v16i8:$vt))>; -+def : LSXPat<(and v8i16:$vs, (xor (shl vsplat_imm_eq_1, -+ (vsplati16imm15 v8i16:$vt)), -+ immAllOnesV)), -+ (v8i16 (VBITCLR_H v8i16:$vs, v8i16:$vt))>; -+def : LSXPat<(and v4i32:$vs, (xor (shl vsplat_imm_eq_1, -+ (vsplati32imm31 v4i32:$vt)), -+ immAllOnesV)), -+ (v4i32 (VBITCLR_W v4i32:$vs, v4i32:$vt))>; -+def : LSXPat<(and v2i64:$vs, (xor (shl (v2i64 vsplati64_imm_eq_1), -+ (vsplati64imm63 v2i64:$vt)), -+ (bitconvert (v4i32 immAllOnesV)))), -+ (v2i64 (VBITCLR_D v2i64:$vs, v2i64:$vt))>; -+ -+ -+def : LSXPat<(fdiv (v4f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), v4f32:$v), -+ (VFRECIP_S v4f32:$v)>; -+ -+def : LSXPat<(fdiv (v2f64 (build_vector (f64 fpimm1), (f64 fpimm1))), v2f64:$v), -+ (VFRECIP_D v2f64:$v)>; -+ -+def : LSXPat<(fdiv (v4f32 fpimm1), v4f32:$v), -+ (VFRECIP_S v4f32:$v)>; -+ -+def : LSXPat<(fdiv (v2f64 fpimm1), v2f64:$v), -+ (VFRECIP_D v2f64:$v)>; -+ -+ -+def : LSXPat<(fdiv (v4f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), (fsqrt v4f32:$v)), -+ (VFRSQRT_S v4f32:$v)>; -+ -+def : LSXPat<(fdiv (v2f64 (build_vector (f64 fpimm1), (f64 fpimm1))), (fsqrt v2f64:$v)), -+ (VFRSQRT_D v2f64:$v)>; -+ -+def : LSXPat<(fdiv (v4f32 fpimm1), (fsqrt v4f32:$v)), -+ (VFRSQRT_S v4f32:$v)>; -+ -+def : LSXPat<(fdiv (v2f64 fpimm1), (fsqrt v2f64:$v)), -+ (VFRSQRT_D v2f64:$v)>; -+ -+ -+def : LSXPat<(abs v2i64:$v), -+ (VMAX_D v2i64:$v, (VNEG_D v2i64:$v))>; -+ -+def : LSXPat<(abs v4i32:$v), -+ (VMAX_W v4i32:$v, (VNEG_W v4i32:$v))>; -+ -+def : LSXPat<(abs v8i16:$v), -+ (VMAX_H v8i16:$v, (VNEG_H v8i16:$v))>; -+ -+def : LSXPat<(abs v16i8:$v), -+ (VMAX_B v16i8:$v, (VNEG_B v16i8:$v))>; -+ -+ -+def : LSXPat<(sub (v16i8 immAllZerosV), v16i8:$v), -+ (VNEG_B v16i8:$v)>; -+ -+def : LSXPat<(sub (v8i16 immAllZerosV), v8i16:$v), -+ (VNEG_H v8i16:$v)>; -+ -+def : LSXPat<(sub (v4i32 immAllZerosV), v4i32:$v), -+ (VNEG_W v4i32:$v)>; -+ -+def : LSXPat<(sub (v2i64 immAllZerosV), v2i64:$v), -+ (VNEG_D v2i64:$v)>; -+ -+ -+def : LSXPat<(sra -+ (v16i8 (add -+ (v16i8 (add LSX128B:$a, LSX128B:$b)), -+ (v16i8 (srl -+ (v16i8 (add LSX128B:$a, LSX128B:$b)), -+ (v16i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (VAVG_B (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; -+ -+def : LSXPat<(sra -+ (v8i16 (add -+ (v8i16 (add LSX128H:$a, LSX128H:$b)), -+ (v8i16 (srl -+ (v8i16 (add LSX128H:$a, LSX128H:$b)), -+ (v8i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (VAVG_H (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; -+ -+def : LSXPat<(sra -+ (v4i32 (add -+ (v4i32 (add LSX128W:$a, LSX128W:$b)), -+ (v4i32 (srl -+ (v4i32 (add LSX128W:$a, LSX128W:$b)), -+ (v4i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)))), -+ (VAVG_W (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; -+ -+def : LSXPat<(sra -+ (v2i64 (add -+ (v2i64 (add LSX128D:$a, LSX128D:$b)), -+ (v2i64 (srl -+ (v2i64 (add LSX128D:$a, LSX128D:$b)), -+ (v2i64 (build_vector (i64 63),(i64 63))) -+ ) -+ ) -+ ) -+ ), -+ (v2i64 (build_vector (i64 1),(i64 1)))), -+ (VAVG_D (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; -+ -+ -+ -+def : LSXPat<(srl -+ (v16i8 (add LSX128B:$a, LSX128B:$b)), -+ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVG_BU (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; -+ -+def : LSXPat<(srl -+ (v8i16 (add LSX128H:$a, LSX128H:$b)), -+ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVG_HU (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; -+ -+def : LSXPat<(srl -+ (v4i32 (add LSX128W:$a, LSX128W:$b)), -+ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVG_WU (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; -+ -+def : LSXPat<(srl -+ (v2i64 (add LSX128D:$a, LSX128D:$b)), -+ (v2i64 (build_vector (i64 1),(i64 1)) -+ ) -+ ), -+ (VAVG_DU (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; -+ -+ -+ -+ -+def : LSXPat<(sra -+ (v16i8 (add -+ (v16i8 (add (v16i8 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i8 (add LSX128B:$a, LSX128B:$b)) -+ )), -+ (v16i8 (srl -+ (v16i8 ( add (v16i8( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i8 (add LSX128B:$a, LSX128B:$b)) -+ )), -+ (v16i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7), -+ (i32 7),(i32 7),(i32 7),(i32 7)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (VAVGR_B (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; -+ -+def : LSXPat<(sra -+ (v8i16 (add -+ (v8i16 (add (v8i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i16 (add LSX128H:$a, LSX128H:$b)) -+ )), -+ (v8i16 (srl -+ (v8i16 (add (v8i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i16 (add LSX128H:$a, LSX128H:$b)) -+ )), -+ (v8i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), -+ (i32 15),(i32 15),(i32 15),(i32 15)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ ))), -+ (VAVGR_H (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; -+ -+def : LSXPat<(sra -+ (v4i32 (add -+ (v4i32 (add (v4i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v4i32 (add LSX128W:$a, LSX128W:$b)) -+ )), -+ (v4i32 (srl -+ (v4i32 (add (v4i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v4i32 (add LSX128W:$a, LSX128W:$b)) -+ )), -+ (v4i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31)) -+ ) -+ ) -+ ) -+ ) -+ ), -+ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)))), -+ (VAVGR_W (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; -+ -+def : LSXPat<(sra -+ (v2i64 (add -+ (v2i64 (add (v2i64 ( -+ build_vector (i64 1),(i64 1) -+ )), -+ (v2i64 (add LSX128D:$a, LSX128D:$b)) -+ )), -+ (v2i64 (srl -+ (v2i64 (add (v2i64 ( -+ build_vector (i64 1),(i64 1) -+ )), -+ (v2i64 (add LSX128D:$a, LSX128D:$b)) -+ )), -+ (v2i64 (build_vector (i64 63),(i64 63))) -+ ) -+ ) -+ ) -+ ), -+ (v2i64 (build_vector (i64 1),(i64 1)))), -+ (VAVGR_D (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; -+ -+ -+ -+ -+def : LSXPat<(srl -+ (v16i8 (add (v16i8 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v16i8 (add LSX128B:$a, LSX128B:$b)) -+ )), -+ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVGR_BU (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; -+ -+def : LSXPat<(srl -+ (v8i16 (add (v8i16 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v8i16 (add LSX128H:$a, LSX128H:$b)) -+ )), -+ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), -+ (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVGR_HU (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; -+ -+def : LSXPat<(srl -+ (v4i32 (add (v4i32 ( -+ build_vector (i32 1),(i32 1),(i32 1),(i32 1) -+ )), -+ (v4i32 (add LSX128W:$a, LSX128W:$b)) -+ )), -+ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)) -+ ) -+ ), -+ (VAVGR_WU (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; -+ -+def : LSXPat<(srl -+ (v2i64 (add (v2i64 ( -+ build_vector (i64 1),(i64 1) -+ )), -+ (v2i64 (add LSX128D:$a, LSX128D:$b)) -+ )), -+ (v2i64 (build_vector (i64 1),(i64 1)) -+ ) -+ ), -+ (VAVGR_DU (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; -+ -+ -+def : LSXPat<(mulhs LSX128D:$a, LSX128D:$b), -+ (VMUH_D LSX128D:$a, LSX128D:$b)>; -+ -+def : LSXPat<(mulhs LSX128W:$a, LSX128W:$b), -+ (VMUH_W LSX128W:$a, LSX128W:$b)>; -+ -+def : LSXPat<(mulhs LSX128H:$a, LSX128H:$b), -+ (VMUH_H LSX128H:$a, LSX128H:$b)>; -+ -+def : LSXPat<(mulhs LSX128B:$a, LSX128B:$b), -+ (VMUH_B LSX128B:$a, LSX128B:$b)>; -+ -+ -+def : LSXPat<(mulhu LSX128D:$a, LSX128D:$b), -+ (VMUH_DU LSX128D:$a, LSX128D:$b)>; -+ -+def : LSXPat<(mulhu LSX128W:$a, LSX128W:$b), -+ (VMUH_WU LSX128W:$a, LSX128W:$b)>; -+ -+def : LSXPat<(mulhu LSX128H:$a, LSX128H:$b), -+ (VMUH_HU LSX128H:$a, LSX128H:$b)>; -+ -+def : LSXPat<(mulhu LSX128B:$a, LSX128B:$b), -+ (VMUH_BU LSX128B:$a, LSX128B:$b)>; -+ -+ -+ -+//===----------------------------------------------------------------------===// -+// Intrinsics -+//===----------------------------------------------------------------------===// -+ -+def : LSXPat<(int_loongarch_lsx_vseq_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSEQ_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vseq_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSEQ_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vseq_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSEQ_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vseq_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSEQ_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsle_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSLE_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSLE_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSLE_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSLE_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsle_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSLE_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSLE_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSLE_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsle_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSLE_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vslt_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSLT_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSLT_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSLT_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSLT_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vslt_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSLT_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSLT_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSLT_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vslt_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSLT_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vadd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VADD_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VADD_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VADD_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VADD_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsub_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSUB_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsub_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSUB_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsub_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSUB_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsub_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSUB_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsadd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSADD_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSADD_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSADD_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSADD_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssub_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSSUB_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSSUB_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSSUB_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSSUB_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsadd_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSADD_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSADD_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSADD_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsadd_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSADD_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssub_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSSUB_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSSUB_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSSUB_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vssub_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSSUB_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vhaddw_h_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VHADDW_H_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhaddw_w_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VHADDW_W_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhaddw_d_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VHADDW_D_W LSX128W:$vj, LSX128W:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vhsubw_h_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VHSUBW_H_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhsubw_w_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VHSUBW_W_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhsubw_d_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VHSUBW_D_W LSX128W:$vj, LSX128W:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vhaddw_hu_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VHADDW_HU_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhaddw_wu_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VHADDW_WU_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhaddw_du_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VHADDW_DU_WU LSX128W:$vj, LSX128W:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vhsubw_hu_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VHSUBW_HU_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhsubw_wu_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VHSUBW_WU_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vhsubw_du_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VHSUBW_DU_WU LSX128W:$vj, LSX128W:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vadda_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VADDA_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadda_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VADDA_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadda_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VADDA_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vadda_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VADDA_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vabsd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VABSD_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VABSD_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VABSD_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VABSD_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vabsd_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VABSD_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VABSD_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VABSD_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vabsd_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VABSD_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vavg_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VAVG_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VAVG_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VAVG_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VAVG_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vavg_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VAVG_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VAVG_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VAVG_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavg_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VAVG_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vavgr_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VAVGR_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VAVGR_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VAVGR_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VAVGR_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vavgr_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VAVGR_BU LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VAVGR_HU LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VAVGR_WU LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vavgr_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VAVGR_DU LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrlr_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSRLR_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrlr_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSRLR_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrlr_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSRLR_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrlr_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSRLR_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrar_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VSRAR_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrar_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VSRAR_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrar_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VSRAR_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vsrar_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VSRAR_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vbitset_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VBITSET_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitset_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VBITSET_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitset_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VBITSET_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitset_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VBITSET_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vbitrev_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), -+ (VBITREV_B LSX128B:$vj, LSX128B:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitrev_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), -+ (VBITREV_H LSX128H:$vj, LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitrev_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), -+ (VBITREV_W LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vbitrev_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), -+ (VBITREV_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfadd_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFADD_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfadd_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFADD_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfsub_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFSUB_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfsub_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFSUB_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfmax_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFMAX_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfmax_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFMAX_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfmin_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFMIN_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfmin_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFMIN_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfmaxa_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFMAXA_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfmaxa_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFMAXA_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfmina_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFMINA_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfmina_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFMINA_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vclo_b (v16i8 LSX128B:$vj)), -+ (VCLO_B LSX128B:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vclo_h (v8i16 LSX128H:$vj)), -+ (VCLO_H LSX128H:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vclo_w (v4i32 LSX128W:$vj)), -+ (VCLO_W LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vclo_d (v2i64 LSX128D:$vj)), -+ (VCLO_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vflogb_s (v4f32 LSX128W:$vj)), -+ (VFLOGB_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vflogb_d (v2f64 LSX128D:$vj)), -+ (VFLOGB_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfclass_s (v4f32 LSX128W:$vj)), -+ (VFCLASS_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vfclass_d (v2f64 LSX128D:$vj)), -+ (VFCLASS_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfrecip_s (v4f32 LSX128W:$vj)), -+ (VFRECIP_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vfrecip_d (v2f64 LSX128D:$vj)), -+ (VFRECIP_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfrsqrt_s (v4f32 LSX128W:$vj)), -+ (VFRSQRT_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vfrsqrt_d (v2f64 LSX128D:$vj)), -+ (VFRSQRT_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcvtl_s_h (v8i16 LSX128H:$vk)), -+ (VFCVTL_S_H LSX128H:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcvth_s_h (v8i16 LSX128H:$vk)), -+ (VFCVTH_S_H LSX128H:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcvtl_d_s (v4f32 LSX128W:$vj)), -+ (VFCVTL_D_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vfcvth_d_s (v4f32 LSX128W:$vj)), -+ (VFCVTH_D_S LSX128W:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vftint_w_s (v4f32 LSX128W:$vj)), -+ (VFTINT_W_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vftint_l_d (v2f64 LSX128D:$vj)), -+ (VFTINT_L_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vftint_wu_s (v4f32 LSX128W:$vj)), -+ (VFTINT_WU_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vftint_lu_d (v2f64 LSX128D:$vj)), -+ (VFTINT_LU_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vreplgr2vr_b GPR32Opnd:$rj), -+ (VREPLGR2VR_B GPR32Opnd:$rj)>; -+def : LSXPat<(int_loongarch_lsx_vreplgr2vr_h GPR32Opnd:$rj), -+ (VREPLGR2VR_H GPR32Opnd:$rj)>; -+def : LSXPat<(int_loongarch_lsx_vreplgr2vr_w GPR32Opnd:$rj), -+ (VREPLGR2VR_W GPR32Opnd:$rj)>; -+def : LSXPat<(int_loongarch_lsx_vreplgr2vr_d GPR64Opnd:$rj), -+ (VREPLGR2VR_D GPR64Opnd:$rj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrlri_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), -+ (VSRLRI_B LSX128B:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vsrlri_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), -+ (VSRLRI_H LSX128H:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsrlri_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), -+ (VSRLRI_W LSX128W:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsrlri_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), -+ (VSRLRI_D LSX128D:$vj, uimm6:$ui6)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrari_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), -+ (VSRARI_B LSX128B:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vsrari_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), -+ (VSRARI_H LSX128H:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsrari_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), -+ (VSRARI_W LSX128W:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsrari_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), -+ (VSRARI_D LSX128D:$vj, uimm6:$ui6)>; -+ -+def : LSXPat<(int_loongarch_lsx_vinsgr2vr_b (v16i8 LSX128B:$vj), GPR32Opnd:$rj, (immZExt4:$ui4)), -+ (VINSGR2VR_B LSX128B:$vj, GPR32Opnd:$rj, (uimm4i:$ui4))>; -+def : LSXPat<(int_loongarch_lsx_vinsgr2vr_h (v8i16 LSX128H:$vj), GPR32Opnd:$rj, (immZExt3:$ui3)), -+ (VINSGR2VR_H LSX128H:$vj, GPR32Opnd:$rj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vinsgr2vr_w (v4i32 LSX128W:$vj), GPR32Opnd:$rj, (immZExt2:$ui2)), -+ (VINSGR2VR_W LSX128W:$vj, GPR32Opnd:$rj, uimm2:$ui2)>; -+def : LSXPat<(int_loongarch_lsx_vinsgr2vr_d (v2i64 LSX128D:$vj), GPR64Opnd:$rj, (immZExt1:$ui1)), -+ (VINSGR2VR_D LSX128D:$vj, GPR64Opnd:$rj, uimm1i:$ui1)>; -+ -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_b (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VPICKVE2GR_B LSX128B:$vj, (uimm4i:$ui4))>; -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_h (v8i16 LSX128H:$vj), (immZExt3:$ui3)), -+ (VPICKVE2GR_H LSX128H:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_w (v4i32 LSX128W:$vj), (immZExt2:$ui2)), -+ (VPICKVE2GR_W LSX128W:$vj, uimm2:$ui2)>; -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_d (v2i64 LSX128D:$vj), (immZExt1:$ui1)), -+ (VPICKVE2GR_D LSX128D:$vj, uimm1i:$ui1)>; -+ -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_bu (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VPICKVE2GR_BU LSX128B:$vj, (uimm4i:$ui4))>; -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_hu (v8i16 LSX128H:$vj), (immZExt3:$ui3)), -+ (VPICKVE2GR_HU LSX128H:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vpickve2gr_wu (v4i32 LSX128W:$vj), (immZExt2:$ui2)), -+ (VPICKVE2GR_WU LSX128W:$vj, uimm2:$ui2)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsat_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), -+ (VSAT_B LSX128B:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vsat_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), -+ (VSAT_H LSX128H:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsat_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), -+ (VSAT_W LSX128W:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsat_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), -+ (VSAT_D LSX128D:$vj, uimm6:$ui6)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsat_bu (v16i8 LSX128B:$vj), (immZExt3:$ui3)), -+ (VSAT_BU LSX128B:$vj, uimm3:$ui3)>; -+def : LSXPat<(int_loongarch_lsx_vsat_hu (v8i16 LSX128H:$vj), (immZExt4:$ui4)), -+ (VSAT_HU LSX128H:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsat_wu (v4i32 LSX128W:$vj), (immZExt5:$ui5)), -+ (VSAT_WU LSX128W:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsat_du (v2i64 LSX128D:$vj), (immZExt6:$ui6)), -+ (VSAT_DU LSX128D:$vj, uimm6:$ui6)>; -+ -+def : LSXPat<(int_loongarch_lsx_vmskltz_b (v16i8 LSX128B:$vj)), -+ (VMSKLTZ_B LSX128B:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vmskltz_h (v8i16 LSX128H:$vj)), -+ (VMSKLTZ_H LSX128H:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vmskltz_w (v4i32 LSX128W:$vj)), -+ (VMSKLTZ_W LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vmskltz_d (v2i64 LSX128D:$vj)), -+ (VMSKLTZ_D LSX128D:$vj)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrlni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSRLNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsrlni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSRLNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsrlni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSRLNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vsrlni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSRLNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrlni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRLNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRLNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRLNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRLNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrlni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRLNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRLNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRLNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrlni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRLNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrlrni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRLRNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrlrni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRLRNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrlrni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRLRNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrlrni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRLRNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vsrarni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSRARNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vsrarni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSRARNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vsrarni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSRARNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vsrarni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSRARNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrani_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRANI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRANI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRANI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRANI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrani_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRANI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRANI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRANI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrani_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRANI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrarni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRARNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRARNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRARNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRARNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(int_loongarch_lsx_vssrarni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), -+ (VSSRARNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), -+ (VSSRARNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), -+ (VSSRARNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; -+def : LSXPat<(int_loongarch_lsx_vssrarni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), -+ (VSSRARNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; -+ -+def : LSXPat<(load (add iPTR:$vj, GPR64Opnd:$vk)), -+ (VLDX PtrRC:$vj, GPR64Opnd:$vk)>; -+ -+def : LSXPat<(store (v16i8 LSX128B:$vd), (add iPTR:$vj, GPR64Opnd:$vk)), -+ (VSTX LSX128B:$vd, PtrRC:$vj, GPR64Opnd:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vshuf_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk), (v16i8 LSX128B:$va)), -+ (VSHUF_B LSX128B:$vj, LSX128B:$vk, LSX128B:$va)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_ceq_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CEQ_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_ceq_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CEQ_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cor_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_COR_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cor_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_COR_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cun_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CUN_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cun_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CUN_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cune_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CUNE_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cune_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CUNE_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cueq_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CUEQ_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cueq_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CUEQ_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cne_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CNE_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cne_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CNE_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_clt_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CLT_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_clt_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CLT_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cult_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CULT_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cult_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CULT_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cle_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CLE_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cle_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CLE_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vfcmp_cule_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), -+ (VFCMP_CULE_S LSX128W:$vj, LSX128W:$vk)>; -+def : LSXPat<(int_loongarch_lsx_vfcmp_cule_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), -+ (VFCMP_CULE_D LSX128D:$vj, LSX128D:$vk)>; -+ -+def : LSXPat<(int_loongarch_lsx_vftintrz_w_s (v4f32 LSX128W:$vj)), -+ (VFTINTRZ_W_S LSX128W:$vj)>; -+def : LSXPat<(int_loongarch_lsx_vftintrz_l_d (v2f64 LSX128D:$vj)), -+ (VFTINTRZ_L_D LSX128D:$vj)>; -+ -+ -+def imm_mask : ImmLeaf(Imm) && Imm == -1;}]>; -+def imm_mask_64 : ImmLeaf(Imm) && Imm == -1;}]>; -+ -+ -+def : LSXPat<(xor (v8i16 LSX128H:$vj), (vsplati16 imm_mask)), -+ (NOR_V_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vj))>; -+ -+def : LSXPat<(xor (v4i32 LSX128W:$vj), (vsplati32 imm_mask)), -+ (NOR_V_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vj))>; -+ -+def : LSXPat<(xor (v2i64 LSX128D:$vj), (vsplati64 imm_mask_64)), -+ (NOR_V_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vj))>; -+ -+ -+def : LSXPat<(and -+ (v16i8 (xor (v16i8 LSX128B:$vj),(vsplati8 imm_mask))), -+ (v16i8 LSX128B:$vk) -+ ), -+ (VANDN_V (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk))>; -+ -+def : LSXPat<(and -+ (v8i16 (xor (v8i16 LSX128H:$vj), (vsplati16 imm_mask))), -+ (v8i16 LSX128H:$vk) -+ ), -+ (VANDN_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk))>; -+ -+def : LSXPat<(and -+ (v4i32 (xor (v4i32 LSX128W:$vj), (vsplati32 imm_mask))), -+ (v4i32 LSX128W:$vk) -+ ), -+ (VANDN_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk))>; -+ -+def : LSXPat<(and -+ (v2i64 (xor (v2i64 LSX128D:$vj), (vsplati64 imm_mask_64))), -+ (v2i64 LSX128D:$vk) -+ ), -+ (VANDN_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk))>; -+ -+ -+def : LSXPat<(or -+ (v16i8 LSX128B:$vj), -+ (v16i8 (xor (v16i8 LSX128B:$vk), (vsplati8 imm_mask))) -+ ), -+ (VORN_V (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk))>; -+ -+def : LSXPat<(or -+ (v8i16 LSX128H:$vj), -+ (v8i16 (xor (v8i16 LSX128H:$vk), (vsplati16 imm_mask))) -+ ), -+ (VORN_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk))>; -+ -+def : LSXPat<(or -+ (v4i32 LSX128W:$vj), -+ (v4i32 (xor (v4i32 LSX128W:$vk), (vsplati32 imm_mask))) -+ ), -+ (VORN_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk))>; -+ -+def : LSXPat<(or -+ (v2i64 LSX128D:$vj), -+ (v2i64 (xor (v2i64 LSX128D:$vk), (vsplati64 imm_mask_64))) -+ ), -+ (VORN_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk))>; -+ -+ -+def : LSXPat<(add (v2i64 (abs LSX128D:$a)), (v2i64 (abs LSX128D:$b))), -+ (VADDA_D (v2i64 LSX128D:$a),(v2i64 LSX128D:$b))>; -+ -+def : LSXPat<(add (v4i32 (abs LSX128W:$a)), (v4i32 (abs LSX128W:$b))), -+ (VADDA_W (v4i32 LSX128W:$a),(v4i32 LSX128W:$b))>; -+ -+def : LSXPat<(add (v8i16 (abs LSX128H:$a)), (v8i16 (abs LSX128H:$b))), -+ (VADDA_H (v8i16 LSX128H:$a),(v8i16 LSX128H:$b))>; -+ -+def : LSXPat<(add (v16i8 (abs LSX128B:$a)), (v16i8 (abs LSX128B:$b))), -+ (VADDA_B (v16i8 LSX128B:$a),(v16i8 LSX128B:$b))>; -+ -+ -+def : LSXPat<(and v16i8:$vj, (xor (shl vsplat_imm_eq_1, v16i8:$vk), -+ (vsplati8 imm_mask))), -+ (VBITCLR_B v16i8:$vj, v16i8:$vk)>; -+ -+def : LSXPat<(and v8i16:$vj, (xor (shl vsplat_imm_eq_1, v8i16:$vk), -+ (vsplati16 imm_mask))), -+ (VBITCLR_H v8i16:$vj, v8i16:$vk)>; -+ -+def : LSXPat<(and v4i32:$vj, (xor (shl vsplat_imm_eq_1, v4i32:$vk), -+ (vsplati32 imm_mask))), -+ (VBITCLR_W v4i32:$vj, v4i32:$vk)>; -+ -+def : LSXPat<(and v2i64:$vj, (xor (shl vsplat_imm_eq_1, v2i64:$vk), -+ (vsplati64 imm_mask_64))), -+ (VBITCLR_D v2i64:$vj, v2i64:$vk)>; -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp -index 488c66f47..bf70b09d4 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp -@@ -1,4 +1,4 @@ --//=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=// -+//===- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to MCInst ----------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,86 +6,337 @@ - // - //===----------------------------------------------------------------------===// - // --// This file contains code to lower LoongArch MachineInstrs to their --// corresponding MCInst records. -+// This file contains code to lower LoongArch MachineInstrs to their corresponding -+// MCInst records. - // - //===----------------------------------------------------------------------===// - --#include "LoongArch.h" --#include "LoongArchSubtarget.h" --#include "llvm/CodeGen/AsmPrinter.h" -+#include "LoongArchMCInstLower.h" -+#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" -+#include "LoongArchAsmPrinter.h" - #include "llvm/CodeGen/MachineBasicBlock.h" - #include "llvm/CodeGen/MachineInstr.h" --#include "llvm/MC/MCAsmInfo.h" --#include "llvm/MC/MCContext.h" --#include "llvm/Support/raw_ostream.h" -+#include "llvm/CodeGen/MachineOperand.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/MC/MCInst.h" -+#include "llvm/Support/ErrorHandling.h" -+#include - - using namespace llvm; - --static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, -- const AsmPrinter &AP) { -- MCContext &Ctx = AP.OutContext; -+LoongArchMCInstLower::LoongArchMCInstLower(LoongArchAsmPrinter &asmprinter) -+ : AsmPrinter(asmprinter) {} - -- // TODO: Processing target flags. -+void LoongArchMCInstLower::Initialize(MCContext *C) { -+ Ctx = C; -+} - -- const MCExpr *ME = -- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); -+MCOperand LoongArchMCInstLower::LowerSymbolOperand(const MachineOperand &MO, -+ MachineOperandType MOTy, -+ unsigned Offset) const { -+ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; -+ LoongArchMCExpr::LoongArchExprKind TargetKind = LoongArchMCExpr::MEK_None; -+ const MCSymbol *Symbol; - -- if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) -- ME = MCBinaryExpr::createAdd( -- ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); -+ switch(MO.getTargetFlags()) { -+ default: -+ llvm_unreachable("Invalid target flag!"); -+ case LoongArchII::MO_NO_FLAG: -+ break; -+ case LoongArchII::MO_GOT_HI: -+ TargetKind = LoongArchMCExpr::MEK_GOT_HI; -+ break; -+ case LoongArchII::MO_GOT_LO: -+ TargetKind = LoongArchMCExpr::MEK_GOT_LO; -+ break; -+ case LoongArchII::MO_GOT_RRHI: -+ TargetKind = LoongArchMCExpr::MEK_GOT_RRHI; -+ break; -+ case LoongArchII::MO_GOT_RRHIGHER: -+ TargetKind = LoongArchMCExpr::MEK_GOT_RRHIGHER; -+ break; -+ case LoongArchII::MO_GOT_RRHIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_GOT_RRHIGHEST; -+ break; -+ case LoongArchII::MO_GOT_RRLO: -+ TargetKind = LoongArchMCExpr::MEK_GOT_RRLO; -+ break; -+ case LoongArchII::MO_PCREL_HI: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_HI; -+ break; -+ case LoongArchII::MO_PCREL_LO: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_LO; -+ break; -+ case LoongArchII::MO_PCREL_RRHI: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHI; -+ break; -+ case LoongArchII::MO_PCREL_RRHIGHER: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHIGHER; -+ break; -+ case LoongArchII::MO_PCREL_RRHIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHIGHEST; -+ break; -+ case LoongArchII::MO_PCREL_RRLO: -+ TargetKind = LoongArchMCExpr::MEK_PCREL_RRLO; -+ break; -+ case LoongArchII::MO_TLSIE_HI: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_HI; -+ break; -+ case LoongArchII::MO_TLSIE_LO: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_LO; -+ break; -+ case LoongArchII::MO_TLSIE_RRHI: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHI; -+ break; -+ case LoongArchII::MO_TLSIE_RRHIGHER: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHIGHER; -+ break; -+ case LoongArchII::MO_TLSIE_RRHIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHIGHEST; -+ break; -+ case LoongArchII::MO_TLSIE_RRLO: -+ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRLO; -+ break; -+ case LoongArchII::MO_TLSLE_HI: -+ TargetKind = LoongArchMCExpr::MEK_TLSLE_HI; -+ break; -+ case LoongArchII::MO_TLSLE_HIGHER: -+ TargetKind = LoongArchMCExpr::MEK_TLSLE_HIGHER; -+ break; -+ case LoongArchII::MO_TLSLE_HIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_TLSLE_HIGHEST; -+ break; -+ case LoongArchII::MO_TLSLE_LO: -+ TargetKind = LoongArchMCExpr::MEK_TLSLE_LO; -+ break; -+ case LoongArchII::MO_TLSGD_HI: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_HI; -+ break; -+ case LoongArchII::MO_TLSGD_LO: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_LO; -+ break; -+ case LoongArchII::MO_TLSGD_RRHI: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHI; -+ break; -+ case LoongArchII::MO_TLSGD_RRHIGHER: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHIGHER; -+ break; -+ case LoongArchII::MO_TLSGD_RRHIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHIGHEST; -+ break; -+ case LoongArchII::MO_TLSGD_RRLO: -+ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRLO; -+ break; -+ case LoongArchII::MO_ABS_HI: -+ TargetKind = LoongArchMCExpr::MEK_ABS_HI; -+ break; -+ case LoongArchII::MO_ABS_HIGHER: -+ TargetKind = LoongArchMCExpr::MEK_ABS_HIGHER; -+ break; -+ case LoongArchII::MO_ABS_HIGHEST: -+ TargetKind = LoongArchMCExpr::MEK_ABS_HIGHEST; -+ break; -+ case LoongArchII::MO_ABS_LO: -+ TargetKind = LoongArchMCExpr::MEK_ABS_LO; -+ break; -+ case LoongArchII::MO_CALL_HI: -+ TargetKind = LoongArchMCExpr::MEK_CALL_HI; -+ break; -+ case LoongArchII::MO_CALL_LO: -+ TargetKind = LoongArchMCExpr::MEK_CALL_LO; -+ break; -+ } - -- return MCOperand::createExpr(ME); --} -+ switch (MOTy) { -+ case MachineOperand::MO_MachineBasicBlock: -+ Symbol = MO.getMBB()->getSymbol(); -+ break; -+ -+ case MachineOperand::MO_GlobalAddress: -+ Symbol = AsmPrinter.getSymbol(MO.getGlobal()); -+ Offset += MO.getOffset(); -+ break; -+ -+ case MachineOperand::MO_BlockAddress: -+ Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); -+ Offset += MO.getOffset(); -+ break; -+ -+ case MachineOperand::MO_ExternalSymbol: -+ Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); -+ Offset += MO.getOffset(); -+ break; -+ -+ case MachineOperand::MO_MCSymbol: -+ Symbol = MO.getMCSymbol(); -+ Offset += MO.getOffset(); -+ break; -+ -+ case MachineOperand::MO_JumpTableIndex: -+ Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); -+ break; -+ -+ case MachineOperand::MO_ConstantPoolIndex: -+ Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); -+ Offset += MO.getOffset(); -+ break; - --bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, -- MCOperand &MCOp, -- const AsmPrinter &AP) { -- switch (MO.getType()) { - default: -- report_fatal_error( -- "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); -+ llvm_unreachable(""); -+ } -+ -+ const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); -+ -+ if (Offset) { -+ // Assume offset is never negative. -+ assert(Offset > 0); -+ -+ Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), -+ *Ctx); -+ } -+ -+ if (TargetKind != LoongArchMCExpr::MEK_None) -+ Expr = LoongArchMCExpr::create(TargetKind, Expr, *Ctx); -+ -+ return MCOperand::createExpr(Expr); -+} -+ -+MCOperand LoongArchMCInstLower::LowerOperand(const MachineOperand &MO, -+ unsigned offset) const { -+ MachineOperandType MOTy = MO.getType(); -+ -+ switch (MOTy) { -+ default: llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. -- if (MO.isImplicit()) -- return false; -- MCOp = MCOperand::createReg(MO.getReg()); -- break; -- case MachineOperand::MO_RegisterMask: -- // Regmasks are like implicit defs. -- return false; -+ if (MO.isImplicit()) break; -+ return MCOperand::createReg(MO.getReg()); - case MachineOperand::MO_Immediate: -- MCOp = MCOperand::createImm(MO.getImm()); -- break; -+ return MCOperand::createImm(MO.getImm() + offset); -+ case MachineOperand::MO_MachineBasicBlock: -+ case MachineOperand::MO_GlobalAddress: -+ case MachineOperand::MO_ExternalSymbol: -+ case MachineOperand::MO_MCSymbol: -+ case MachineOperand::MO_JumpTableIndex: - case MachineOperand::MO_ConstantPoolIndex: -- MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); -+ case MachineOperand::MO_BlockAddress: -+ return LowerSymbolOperand(MO, MOTy, offset); -+ case MachineOperand::MO_RegisterMask: - break; -- case MachineOperand::MO_GlobalAddress: -- MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); -+ } -+ -+ return MCOperand(); -+} -+ -+MCOperand LoongArchMCInstLower::createSub(MachineBasicBlock *BB1, -+ MachineBasicBlock *BB2, -+ LoongArchMCExpr::LoongArchExprKind Kind) const { -+ const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); -+ const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); -+ const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); -+ -+ return MCOperand::createExpr(LoongArchMCExpr::create(Kind, Sub, *Ctx)); -+} -+ -+void LoongArchMCInstLower::lowerLongBranchADDI(const MachineInstr *MI, -+ MCInst &OutMI, int Opcode) const { -+ OutMI.setOpcode(Opcode); -+ -+ LoongArchMCExpr::LoongArchExprKind Kind; -+ unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); -+ switch (TargetFlags) { -+ case LoongArchII::MO_ABS_HIGHEST: -+ Kind = LoongArchMCExpr::MEK_ABS_HIGHEST; - break; -- case MachineOperand::MO_MachineBasicBlock: -- MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); -+ case LoongArchII::MO_ABS_HIGHER: -+ Kind = LoongArchMCExpr::MEK_ABS_HIGHER; - break; -- case MachineOperand::MO_ExternalSymbol: -- MCOp = lowerSymbolOperand( -- MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); -+ case LoongArchII::MO_ABS_HI: -+ Kind = LoongArchMCExpr::MEK_ABS_HI; - break; -- // TODO: lower special operands -- case MachineOperand::MO_BlockAddress: -- case MachineOperand::MO_JumpTableIndex: -+ case LoongArchII::MO_ABS_LO: -+ Kind = LoongArchMCExpr::MEK_ABS_LO; - break; -+ default: -+ report_fatal_error("Unexpected flags for lowerLongBranchADDI"); -+ } -+ -+ // Lower two register operands. -+ for (unsigned I = 0, E = 2; I != E; ++I) { -+ const MachineOperand &MO = MI->getOperand(I); -+ OutMI.addOperand(LowerOperand(MO)); -+ } -+ -+ if (MI->getNumOperands() == 3) { -+ // Lower register operand. -+ const MCExpr *Expr = -+ MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); -+ const LoongArchMCExpr *LoongArchExpr = LoongArchMCExpr::create(Kind, Expr, *Ctx); -+ OutMI.addOperand(MCOperand::createExpr(LoongArchExpr)); -+ } else if (MI->getNumOperands() == 4) { -+ // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). -+ OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), -+ MI->getOperand(3).getMBB(), Kind)); - } -- return true; - } - --bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, -- MCInst &OutMI, AsmPrinter &AP) { -+void LoongArchMCInstLower::lowerLongBranchPCADDU12I(const MachineInstr *MI, -+ MCInst &OutMI, int Opcode) const { -+ OutMI.setOpcode(Opcode); -+ -+ LoongArchMCExpr::LoongArchExprKind Kind; -+ unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); -+ switch (TargetFlags) { -+ case LoongArchII::MO_PCREL_HI: -+ Kind = LoongArchMCExpr::MEK_PCREL_HI; -+ break; -+ case LoongArchII::MO_PCREL_LO: -+ Kind = LoongArchMCExpr::MEK_PCREL_LO; -+ break; -+ default: -+ report_fatal_error("Unexpected flags for lowerLongBranchADDI"); -+ } -+ -+ // Lower one register operands. -+ const MachineOperand &MO = MI->getOperand(0); -+ OutMI.addOperand(LowerOperand(MO)); -+ -+ const MCExpr *Expr = -+ MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); -+ const LoongArchMCExpr *LoongArchExpr = LoongArchMCExpr::create(Kind, Expr, *Ctx); -+ OutMI.addOperand(MCOperand::createExpr(LoongArchExpr)); -+} -+bool LoongArchMCInstLower::lowerLongBranch(const MachineInstr *MI, -+ MCInst &OutMI) const { -+ switch (MI->getOpcode()) { -+ default: -+ return false; -+ case LoongArch::LONG_BRANCH_ADDIW: -+ case LoongArch::LONG_BRANCH_ADDIW2Op: -+ lowerLongBranchADDI(MI, OutMI, LoongArch::ADDI_W); -+ return true; -+ case LoongArch::LONG_BRANCH_ADDID: -+ case LoongArch::LONG_BRANCH_ADDID2Op: -+ lowerLongBranchADDI(MI, OutMI, LoongArch::ADDI_D); -+ return true; -+ case LoongArch::LONG_BRANCH_PCADDU12I: -+ lowerLongBranchPCADDU12I(MI, OutMI, LoongArch::PCADDU12I); -+ return true; -+ } -+} -+ -+void LoongArchMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { -+ if (lowerLongBranch(MI, OutMI)) -+ return; -+ - OutMI.setOpcode(MI->getOpcode()); - -- for (const MachineOperand &MO : MI->operands()) { -- MCOperand MCOp; -- if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) -+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { -+ const MachineOperand &MO = MI->getOperand(i); -+ MCOperand MCOp = LowerOperand(MO); -+ -+ if (MCOp.isValid()) - OutMI.addOperand(MCOp); - } -- return false; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h -new file mode 100644 -index 000000000..6463a7b64 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h -@@ -0,0 +1,55 @@ -+//===- LoongArchMCInstLower.h - Lower MachineInstr to MCInst --------*- C++ -*--===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H -+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H -+ -+#include "MCTargetDesc/LoongArchMCExpr.h" -+#include "llvm/CodeGen/MachineOperand.h" -+#include "llvm/Support/Compiler.h" -+ -+namespace llvm { -+ -+class MachineBasicBlock; -+class MachineInstr; -+class MCContext; -+class MCInst; -+class MCOperand; -+class LoongArchAsmPrinter; -+ -+/// LoongArchMCInstLower - This class is used to lower an MachineInstr into an -+/// MCInst. -+class LLVM_LIBRARY_VISIBILITY LoongArchMCInstLower { -+ using MachineOperandType = MachineOperand::MachineOperandType; -+ -+ MCContext *Ctx; -+ LoongArchAsmPrinter &AsmPrinter; -+ -+public: -+ LoongArchMCInstLower(LoongArchAsmPrinter &asmprinter); -+ -+ void Initialize(MCContext *C); -+ void Lower(const MachineInstr *MI, MCInst &OutMI) const; -+ MCOperand LowerOperand(const MachineOperand& MO, unsigned offset = 0) const; -+ -+private: -+ MCOperand LowerSymbolOperand(const MachineOperand &MO, -+ MachineOperandType MOTy, unsigned Offset) const; -+ MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, -+ LoongArchMCExpr::LoongArchExprKind Kind) const; -+ void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; -+ void lowerLongBranchADDI(const MachineInstr *MI, MCInst &OutMI, -+ int Opcode) const; -+ void lowerLongBranchPCADDU12I(const MachineInstr *MI, MCInst &OutMI, -+ int Opcode) const; -+ bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const; -+}; -+ -+} // end namespace llvm -+ -+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp -new file mode 100644 -index 000000000..a9c52cbb1 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp -@@ -0,0 +1,58 @@ -+//===-- LoongArchMachineFunctionInfo.cpp - Private data used for LoongArch ----------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchMachineFunction.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "LoongArchSubtarget.h" -+#include "LoongArchTargetMachine.h" -+#include "llvm/CodeGen/MachineFrameInfo.h" -+#include "llvm/CodeGen/MachineRegisterInfo.h" -+#include "llvm/CodeGen/PseudoSourceValue.h" -+#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "llvm/Support/CommandLine.h" -+ -+using namespace llvm; -+ -+LoongArchFunctionInfo::~LoongArchFunctionInfo() = default; -+ -+void LoongArchFunctionInfo::createEhDataRegsFI() { -+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); -+ for (int I = 0; I < 4; ++I) { -+ const TargetRegisterClass &RC = -+ static_cast(MF.getTarget()).getABI().IsLP64() -+ ? LoongArch::GPR64RegClass -+ : LoongArch::GPR32RegClass; -+ -+ EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC), -+ TRI.getSpillAlign(RC), false); -+ } -+} -+ -+bool LoongArchFunctionInfo::isEhDataRegFI(int FI) const { -+ return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1] -+ || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]); -+} -+ -+MachinePointerInfo LoongArchFunctionInfo::callPtrInfo(const char *ES) { -+ return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)); -+} -+ -+MachinePointerInfo LoongArchFunctionInfo::callPtrInfo(const GlobalValue *GV) { -+ return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV)); -+} -+ -+int LoongArchFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { -+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); -+ if (MoveF64ViaSpillFI == -1) { -+ MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject( -+ TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false); -+ } -+ return MoveF64ViaSpillFI; -+} -+ -+void LoongArchFunctionInfo::anchor() {} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h -new file mode 100644 -index 000000000..1765013ea ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h -@@ -0,0 +1,103 @@ -+//===- LoongArchMachineFunctionInfo.h - Private data used for LoongArch ---*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file declares the LoongArch specific subclass of MachineFunctionInfo. -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H -+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H -+ -+#include "llvm/CodeGen/MachineFunction.h" -+#include "llvm/CodeGen/MachineMemOperand.h" -+#include -+ -+namespace llvm { -+ -+/// LoongArchFunctionInfo - This class is derived from MachineFunction private -+/// LoongArch target-specific information for each MachineFunction. -+class LoongArchFunctionInfo : public MachineFunctionInfo { -+public: -+ LoongArchFunctionInfo(MachineFunction &MF) : MF(MF) {} -+ -+ ~LoongArchFunctionInfo() override; -+ -+ unsigned getSRetReturnReg() const { return SRetReturnReg; } -+ void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } -+ -+ int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } -+ void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } -+ -+ unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; } -+ void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; } -+ -+ bool hasByvalArg() const { return HasByvalArg; } -+ void setFormalArgInfo(unsigned Size, bool HasByval) { -+ IncomingArgSize = Size; -+ HasByvalArg = HasByval; -+ } -+ -+ unsigned getIncomingArgSize() const { return IncomingArgSize; } -+ -+ bool callsEhReturn() const { return CallsEhReturn; } -+ void setCallsEhReturn() { CallsEhReturn = true; } -+ -+ void createEhDataRegsFI(); -+ int getEhDataRegFI(unsigned Reg) const { return EhDataRegFI[Reg]; } -+ bool isEhDataRegFI(int FI) const; -+ -+ /// Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue -+ /// object representing a GOT entry for an external function. -+ MachinePointerInfo callPtrInfo(const char *ES); -+ -+ /// Create a MachinePointerInfo that has a GlobalValuePseudoSourceValue object -+ /// representing a GOT entry for a global function. -+ MachinePointerInfo callPtrInfo(const GlobalValue *GV); -+ -+ void setSaveS2() { SaveS2 = true; } -+ bool hasSaveS2() const { return SaveS2; } -+ -+ int getMoveF64ViaSpillFI(const TargetRegisterClass *RC); -+ -+private: -+ virtual void anchor(); -+ -+ MachineFunction& MF; -+ -+ /// SRetReturnReg - Some subtargets require that sret lowering includes -+ /// returning the value of the returned struct in a register. This field -+ /// holds the virtual register into which the sret argument is passed. -+ unsigned SRetReturnReg = 0; -+ -+ /// VarArgsFrameIndex - FrameIndex for start of varargs area. -+ int VarArgsFrameIndex = 0; -+ int VarArgsSaveSize = 0; -+ -+ /// True if function has a byval argument. -+ bool HasByvalArg; -+ -+ /// Size of incoming argument area. -+ unsigned IncomingArgSize; -+ -+ /// CallsEhReturn - Whether the function calls llvm.eh.return. -+ bool CallsEhReturn = false; -+ -+ /// Frame objects for spilling eh data registers. -+ int EhDataRegFI[4]; -+ -+ // saveS2 -+ bool SaveS2 = false; -+ -+ /// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the -+ /// LP32 FPXX ABI is enabled. -1 is used to denote invalid index. -+ int MoveF64ViaSpillFI = -1; -+}; -+ -+} // end namespace llvm -+ -+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h -deleted file mode 100644 -index d4a6c884b..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h -+++ /dev/null -@@ -1,57 +0,0 @@ --//=- LoongArchMachineFunctionInfo.h - LoongArch machine function info -----===// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// --// --// This file declares LoongArch-specific per-machine-function information. --// --//===----------------------------------------------------------------------===// -- --#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H --#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H -- --#include "LoongArchSubtarget.h" --#include "llvm/CodeGen/MachineFrameInfo.h" --#include "llvm/CodeGen/MachineFunction.h" -- --namespace llvm { -- --/// LoongArchMachineFunctionInfo - This class is derived from --/// MachineFunctionInfo and contains private LoongArch-specific information for --/// each MachineFunction. --class LoongArchMachineFunctionInfo : public MachineFunctionInfo { --private: -- /// FrameIndex for start of varargs area -- int VarArgsFrameIndex = 0; -- /// Size of the save area used for varargs -- int VarArgsSaveSize = 0; -- -- /// Size of stack frame to save callee saved registers -- unsigned CalleeSavedStackSize = 0; -- --public: -- LoongArchMachineFunctionInfo(const MachineFunction &MF) {} -- -- MachineFunctionInfo * -- clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, -- const DenseMap &Src2DstMBB) -- const override { -- return DestMF.cloneInfo(*this); -- } -- -- int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } -- void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } -- -- unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; } -- void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; } -- -- unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; } -- void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; } --}; -- --} // end namespace llvm -- --#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp -new file mode 100644 -index 000000000..8dbf30f21 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp -@@ -0,0 +1,53 @@ -+//===----------------------------------------------------------------------===// -+// Instruction Selector Subtarget Control -+//===----------------------------------------------------------------------===// -+ -+//===----------------------------------------------------------------------===// -+// This file defines a pass used to change the subtarget for the -+// LoongArch Instruction selector. -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArch.h" -+#include "LoongArchTargetMachine.h" -+#include "llvm/CodeGen/TargetPassConfig.h" -+#include "llvm/CodeGen/StackProtector.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/raw_ostream.h" -+ -+using namespace llvm; -+ -+#define DEBUG_TYPE "loongarch-isel" -+ -+namespace { -+ class LoongArchModuleDAGToDAGISel : public MachineFunctionPass { -+ public: -+ static char ID; -+ -+ LoongArchModuleDAGToDAGISel() : MachineFunctionPass(ID) {} -+ -+ // Pass Name -+ StringRef getPassName() const override { -+ return "LoongArch DAG->DAG Pattern Instruction Selection"; -+ } -+ -+ void getAnalysisUsage(AnalysisUsage &AU) const override { -+ AU.addRequired(); -+ AU.addPreserved(); -+ MachineFunctionPass::getAnalysisUsage(AU); -+ } -+ -+ bool runOnMachineFunction(MachineFunction &MF) override; -+ }; -+ -+ char LoongArchModuleDAGToDAGISel::ID = 0; -+} -+ -+bool LoongArchModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { -+ LLVM_DEBUG(errs() << "In LoongArchModuleDAGToDAGISel::runMachineFunction\n"); -+ return false; -+} -+ -+llvm::FunctionPass *llvm::createLoongArchModuleISelDagPass() { -+ return new LoongArchModuleDAGToDAGISel(); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp -index 05902ebb7..4d1a3cf22 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp -@@ -1,4 +1,4 @@ --//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=// -+//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,132 +6,352 @@ - // - //===----------------------------------------------------------------------===// - // --// This file contains the LoongArch implementation of the TargetRegisterInfo --// class. -+// This file contains the LoongArch implementation of the TargetRegisterInfo class. - // - //===----------------------------------------------------------------------===// - - #include "LoongArchRegisterInfo.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" - #include "LoongArch.h" -+#include "LoongArchMachineFunction.h" - #include "LoongArchSubtarget.h" -+#include "LoongArchTargetMachine.h" -+#include "llvm/ADT/BitVector.h" -+#include "llvm/ADT/STLExtras.h" - #include "llvm/CodeGen/MachineFrameInfo.h" - #include "llvm/CodeGen/MachineFunction.h" --#include "llvm/CodeGen/MachineInstrBuilder.h" --#include "llvm/CodeGen/RegisterScavenging.h" -+#include "llvm/CodeGen/MachineInstr.h" -+#include "llvm/CodeGen/MachineRegisterInfo.h" - #include "llvm/CodeGen/TargetFrameLowering.h" --#include "llvm/CodeGen/TargetInstrInfo.h" -+#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "llvm/CodeGen/TargetSubtargetInfo.h" -+#include "llvm/IR/Function.h" -+#include "llvm/MC/MCRegisterInfo.h" -+#include "llvm/Support/Debug.h" - #include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/raw_ostream.h" -+#include - - using namespace llvm; - -+#define DEBUG_TYPE "loongarch-reg-info" -+ - #define GET_REGINFO_TARGET_DESC - #include "LoongArchGenRegisterInfo.inc" - --LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode) -- : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0, -- /*EHFlavor*/ 0, -- /*PC*/ 0, HwMode) {} -+LoongArchRegisterInfo::LoongArchRegisterInfo() : LoongArchGenRegisterInfo(LoongArch::RA) {} - --const MCPhysReg * --LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { -- auto &Subtarget = MF->getSubtarget(); -+unsigned LoongArchRegisterInfo::getPICCallReg() { return LoongArch::T8; } -+ -+const TargetRegisterClass * -+LoongArchRegisterInfo::getPointerRegClass(const MachineFunction &MF, -+ unsigned Kind) const { -+ LoongArchABIInfo ABI = MF.getSubtarget().getABI(); -+ LoongArchPtrClass PtrClassKind = static_cast(Kind); -+ -+ switch (PtrClassKind) { -+ case LoongArchPtrClass::Default: -+ return ABI.ArePtrs64bit() ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; -+ case LoongArchPtrClass::StackPointer: -+ return ABI.ArePtrs64bit() ? &LoongArch::SP64RegClass : &LoongArch::SP32RegClass; -+ } -+ -+ llvm_unreachable("Unknown pointer kind"); -+} - -- switch (Subtarget.getTargetABI()) { -+unsigned -+LoongArchRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, -+ MachineFunction &MF) const { -+ switch (RC->getID()) { - default: -- llvm_unreachable("Unrecognized ABI"); -- case LoongArchABI::ABI_ILP32S: -- case LoongArchABI::ABI_LP64S: -- return CSR_ILP32S_LP64S_SaveList; -- case LoongArchABI::ABI_ILP32F: -- case LoongArchABI::ABI_LP64F: -- return CSR_ILP32F_LP64F_SaveList; -- case LoongArchABI::ABI_ILP32D: -- case LoongArchABI::ABI_LP64D: -- return CSR_ILP32D_LP64D_SaveList; -+ return 0; -+ case LoongArch::GPR32RegClassID: -+ case LoongArch::GPR64RegClassID: -+ { -+ const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); -+ return 28 - TFI->hasFP(MF); - } -+ case LoongArch::FGR32RegClassID: -+ return 32; -+ case LoongArch::FGR64RegClassID: -+ return 32; -+ } -+} -+ -+//===----------------------------------------------------------------------===// -+// Callee Saved Registers methods -+//===----------------------------------------------------------------------===// -+ -+/// LoongArch Callee Saved Registers -+const MCPhysReg * -+LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { -+ const LoongArchSubtarget &Subtarget = MF->getSubtarget(); -+ -+ if (Subtarget.isSingleFloat()) -+ return CSR_SingleFloatOnly_SaveList; -+ -+ if (Subtarget.isABI_LP64()) -+ return CSR_LP64_SaveList; -+ -+ if (Subtarget.isABI_LPX32()) -+ return CSR_LPX32_SaveList; -+ -+ return CSR_LP32_SaveList; - } - - const uint32_t * - LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF, -- CallingConv::ID CC) const { -- auto &Subtarget = MF.getSubtarget(); -+ CallingConv::ID) const { -+ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); - -- switch (Subtarget.getTargetABI()) { -- default: -- llvm_unreachable("Unrecognized ABI"); -- case LoongArchABI::ABI_ILP32S: -- case LoongArchABI::ABI_LP64S: -- return CSR_ILP32S_LP64S_RegMask; -- case LoongArchABI::ABI_ILP32F: -- case LoongArchABI::ABI_LP64F: -- return CSR_ILP32F_LP64F_RegMask; -- case LoongArchABI::ABI_ILP32D: -- case LoongArchABI::ABI_LP64D: -- return CSR_ILP32D_LP64D_RegMask; -- } --} -+ if (Subtarget.isSingleFloat()) -+ return CSR_SingleFloatOnly_RegMask; -+ -+ if (Subtarget.isABI_LP64()) -+ return CSR_LP64_RegMask; - --const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const { -- return CSR_NoRegs_RegMask; -+ return CSR_LP32_RegMask; - } - --BitVector --LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const { -- const LoongArchFrameLowering *TFI = getFrameLowering(MF); -+BitVector LoongArchRegisterInfo:: -+getReservedRegs(const MachineFunction &MF) const { -+ static const MCPhysReg ReservedGPR32[] = { -+ LoongArch::ZERO, LoongArch::SP, LoongArch::TP, LoongArch::T9 -+ }; -+ -+ static const MCPhysReg ReservedGPR64[] = { -+ LoongArch::ZERO_64, LoongArch::SP_64, LoongArch::TP_64, LoongArch::T9_64 -+ }; -+ - BitVector Reserved(getNumRegs()); -+ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); -+ -+ for (unsigned I = 0; I < array_lengthof(ReservedGPR32); ++I) -+ Reserved.set(ReservedGPR32[I]); -+ -+ for (unsigned I = 0; I < array_lengthof(ReservedGPR64); ++I) -+ Reserved.set(ReservedGPR64[I]); -+ -+ // Reserve FP if this function should have a dedicated frame pointer register. -+ if (Subtarget.getFrameLowering()->hasFP(MF)) { -+ Reserved.set(LoongArch::FP); -+ Reserved.set(LoongArch::FP_64); -+ -+ // Reserve the base register if we need to both realign the stack and -+ // allocate variable-sized objects at runtime. This should test the -+ // same conditions as LoongArchFrameLowering::hasBP(). -+ if (hasStackRealignment(MF) && MF.getFrameInfo().hasVarSizedObjects()) { -+ Reserved.set(LoongArch::S7); -+ Reserved.set(LoongArch::S7_64); -+ } -+ } - -- // Use markSuperRegs to ensure any register aliases are also reserved -- markSuperRegs(Reserved, LoongArch::R0); // zero -- markSuperRegs(Reserved, LoongArch::R2); // tp -- markSuperRegs(Reserved, LoongArch::R3); // sp -- markSuperRegs(Reserved, LoongArch::R21); // non-allocatable -- if (TFI->hasFP(MF)) -- markSuperRegs(Reserved, LoongArch::R22); // fp -- // Reserve the base register if we need to realign the stack and allocate -- // variable-sized objects at runtime. -- if (TFI->hasBP(MF)) -- markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp -- -- assert(checkAllSuperRegsMarked(Reserved)); - return Reserved; - } - --bool LoongArchRegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { -- return PhysReg == LoongArch::R0; -+bool -+LoongArchRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { -+ return true; - } - --Register --LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const { -- const TargetFrameLowering *TFI = getFrameLowering(MF); -- return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3; -+bool LoongArchRegisterInfo:: -+requiresFrameIndexScavenging(const MachineFunction &MF) const { -+ return true; - } - --void LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, -- int SPAdj, -- unsigned FIOperandNum, -- RegScavenger *RS) const { -- // TODO: this implementation is a temporary placeholder which does just -- // enough to allow other aspects of code generation to be tested. -+bool -+LoongArchRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { -+ return true; -+} -+ -+/// Get the size of the offset supported by the given load/store/inline asm. -+/// The result includes the effects of any scale factors applied to the -+/// instruction immediate. -+static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, -+ MachineOperand MO) { -+ switch (Opcode) { -+ case LoongArch::LDPTR_W: -+ case LoongArch::LDPTR_W32: -+ case LoongArch::LDPTR_D: -+ case LoongArch::STPTR_W: -+ case LoongArch::STPTR_W32: -+ case LoongArch::STPTR_D: -+ case LoongArch::LL_W: -+ case LoongArch::LL_D: -+ case LoongArch::SC_W: -+ case LoongArch::SC_D: -+ return 14 + 2 /* scale factor */; -+ case LoongArch::INLINEASM: { -+ unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); -+ switch (ConstraintID) { -+ case InlineAsm::Constraint_ZC: { -+ return 14 + 2 /* scale factor */; -+ } -+ default: -+ return 12; -+ } -+ } -+ default: -+ return 12; -+ } -+} - -- assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); -+/// Get the scale factor applied to the immediate in the given load/store. -+static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) { -+ switch (Opcode) { -+ case LoongArch::LDPTR_W: -+ case LoongArch::LDPTR_W32: -+ case LoongArch::LDPTR_D: -+ case LoongArch::STPTR_W: -+ case LoongArch::STPTR_W32: -+ case LoongArch::STPTR_D: -+ case LoongArch::LL_W: -+ case LoongArch::LL_D: -+ case LoongArch::SC_W: -+ case LoongArch::SC_D: -+ return 4; -+ default: -+ return 1; -+ } -+} - -+// FrameIndex represent objects inside a abstract stack. -+// We must replace FrameIndex with an stack/frame pointer -+// direct reference. -+void LoongArchRegisterInfo:: -+eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, -+ unsigned FIOperandNum, RegScavenger *RS) const { - MachineInstr &MI = *II; - MachineFunction &MF = *MI.getParent()->getParent(); -- const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); -- DebugLoc DL = MI.getDebugLoc(); -+ const LoongArchFrameLowering *TFI = getFrameLowering(MF); -+ -+ LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; -+ errs() << "<--------->\n" -+ << MI); - - int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); -+ uint64_t stackSize = MF.getFrameInfo().getStackSize(); -+ int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); -+ -+ LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" -+ << "spOffset : " << spOffset << "\n" -+ << "stackSize : " << stackSize << "\n" -+ << "SPAdj : " << SPAdj << "\n" -+ << "alignment : " -+ << DebugStr(MF.getFrameInfo().getObjectAlign(FrameIndex)) -+ << "\n"); -+ -+ LoongArchABIInfo ABI = -+ static_cast(MF.getTarget()).getABI(); -+ -+ // Everything else is referenced relative to whatever register -+ // getFrameIndexReference() returns. - Register FrameReg; - StackOffset Offset = - TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) + - StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm()); - -- // Offsets must be encodable with a 12-bit immediate field. -- if (!isInt<12>(Offset.getFixed())) { -- report_fatal_error("Frame offsets outside of the signed 12-bit range is " -- "not supported currently"); -+ LLVM_DEBUG(errs() << "Location : " -+ << "FrameReg<" << FrameReg << "> + " << Offset.getFixed() -+ << "\n<--------->\n"); -+ -+ MachineBasicBlock &MBB = *MI.getParent(); -+ DebugLoc DL = II->getDebugLoc(); -+ bool IsKill = false; -+ -+ if (!MI.isDebugValue()) { -+ // Make sure Offset fits within the field available. -+ // For ldptr/stptr/ll/sc instructions, this is a 14-bit signed immediate -+ // (scaled by 2), otherwise it is a 12-bit signed immediate. -+ unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits( -+ MI.getOpcode(), MI.getOperand(FIOperandNum - 1)); -+ const Align OffsetAlign(getLoadStoreOffsetAlign(MI.getOpcode())); -+ -+ if (OffsetBitSize == 16 && isInt<12>(Offset.getFixed()) && -+ !isAligned(OffsetAlign, Offset.getFixed())) { -+ // If we have an offset that needs to fit into a signed n-bit immediate -+ // (where n == 16) and doesn't aligned and does fit into 12-bits -+ // then use an ADDI -+ const TargetRegisterClass *PtrRC = ABI.ArePtrs64bit() -+ ? &LoongArch::GPR64RegClass -+ : &LoongArch::GPR32RegClass; -+ MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); -+ unsigned Reg = RegInfo.createVirtualRegister(PtrRC); -+ const LoongArchInstrInfo &TII = *static_cast( -+ MBB.getParent()->getSubtarget().getInstrInfo()); -+ BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiOp()), Reg) -+ .addReg(FrameReg) -+ .addImm(Offset.getFixed()); -+ -+ FrameReg = Reg; -+ Offset = StackOffset::getFixed(0); -+ IsKill = true; -+ } else if (!isInt<12>(Offset.getFixed())) { -+ // Otherwise split the offset into several pieces and add it in multiple -+ // instructions. -+ const LoongArchInstrInfo &TII = *static_cast( -+ MBB.getParent()->getSubtarget().getInstrInfo()); -+ unsigned Reg = TII.loadImmediate(Offset.getFixed(), MBB, II, DL); -+ BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddOp()), Reg) -+ .addReg(FrameReg) -+ .addReg(Reg, RegState::Kill); -+ -+ FrameReg = Reg; -+ Offset = StackOffset::getFixed(0); -+ IsKill = true; -+ } - } - -- MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); -+ MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed()); - } -+ -+Register LoongArchRegisterInfo:: -+getFrameRegister(const MachineFunction &MF) const { -+ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); -+ const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); -+ bool IsLP64 = -+ static_cast(MF.getTarget()).getABI().IsLP64(); -+ -+ return TFI->hasFP(MF) ? (IsLP64 ? LoongArch::FP_64 : LoongArch::FP) : -+ (IsLP64 ? LoongArch::SP_64 : LoongArch::SP); -+} -+ -+const TargetRegisterClass * -+LoongArchRegisterInfo::intRegClass(unsigned Size) const { -+ if (Size == 4) -+ return &LoongArch::GPR32RegClass; -+ -+ assert(Size == 8); -+ return &LoongArch::GPR64RegClass; -+} -+ -+bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const { -+ // Avoid realigning functions that explicitly do not want to be realigned. -+ // Normally, we should report an error when a function should be dynamically -+ // realigned but also has the attribute no-realign-stack. Unfortunately, -+ // with this attribute, MachineFrameInfo clamps each new object's alignment -+ // to that of the stack's alignment as specified by the ABI. As a result, -+ // the information of whether we have objects with larger alignment -+ // requirement than the stack's alignment is already lost at this point. -+ if (!TargetRegisterInfo::canRealignStack(MF)) -+ return false; -+ -+ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); -+ unsigned FP = Subtarget.is64Bit() ? LoongArch::FP_64 : LoongArch::FP; -+ unsigned BP = Subtarget.is64Bit() ? LoongArch::S7_64 : LoongArch::S7; -+ -+ // We can't perform dynamic stack realignment if we can't reserve the -+ // frame pointer register. -+ if (!MF.getRegInfo().canReserveReg(FP)) -+ return false; -+ -+ // We can realign the stack if we know the maximum call frame size and we -+ // don't have variable sized objects. -+ if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF)) -+ return true; -+ -+ // We have to reserve the base pointer register in the presence of variable -+ // sized objects. -+ return MF.getRegInfo().canReserveReg(BP); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h -index cca130c3b..dd3be916a 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h -@@ -1,4 +1,4 @@ --//= LoongArchRegisterInfo.h - LoongArch Register Information Impl -*- C++ -*-=// -+//===- LoongArchRegisterInfo.h - LoongArch Register Information Impl ------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,45 +6,75 @@ - // - //===----------------------------------------------------------------------===// - // --// This file contains the LoongArch implementation of the TargetRegisterInfo --// class. -+// This file contains the LoongArch implementation of the TargetRegisterInfo class. - // - //===----------------------------------------------------------------------===// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H - --#include "llvm/CodeGen/TargetRegisterInfo.h" -+#include "LoongArch.h" -+#include "llvm/CodeGen/MachineBasicBlock.h" -+#include - - #define GET_REGINFO_HEADER - #include "LoongArchGenRegisterInfo.inc" - - namespace llvm { - --struct LoongArchRegisterInfo : public LoongArchGenRegisterInfo { -+class TargetRegisterClass; - -- LoongArchRegisterInfo(unsigned HwMode); -+class LoongArchRegisterInfo : public LoongArchGenRegisterInfo { -+public: -+ enum class LoongArchPtrClass { -+ /// The default register class for integer values. -+ Default = 0, -+ /// The stack pointer only. -+ StackPointer = 1, -+ }; - -+ LoongArchRegisterInfo(); -+ -+ /// Get PIC indirect call register -+ static unsigned getPICCallReg(); -+ -+ /// Code Generation virtual methods... -+ const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, -+ unsigned Kind) const override; -+ -+ unsigned getRegPressureLimit(const TargetRegisterClass *RC, -+ MachineFunction &MF) const override; - const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; - const uint32_t *getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID) const override; -- const uint32_t *getNoPreservedMask() const override; -- - BitVector getReservedRegs(const MachineFunction &MF) const override; -- bool isConstantPhysReg(MCRegister PhysReg) const override; - -- const TargetRegisterClass * -- getPointerRegClass(const MachineFunction &MF, -- unsigned Kind = 0) const override { -- return &LoongArch::GPRRegClass; -- } -+ bool requiresRegisterScavenging(const MachineFunction &MF) const override; -+ -+ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; - -- void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, -- unsigned FIOperandNum, -+ bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override; -+ -+ /// Stack Frame Processing Methods -+ void eliminateFrameIndex(MachineBasicBlock::iterator II, -+ int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = nullptr) const override; - -+ // Stack realignment queries. -+ bool canRealignStack(const MachineFunction &MF) const override; -+ -+ /// Debug information queries. - Register getFrameRegister(const MachineFunction &MF) const override; -+ -+ /// Return GPR register class. -+ const TargetRegisterClass *intRegClass(unsigned Size) const; -+ -+private: -+ void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, -+ int FrameIndex, uint64_t StackSize, -+ int SPAdj, int64_t SPOffset) const; - }; -+ - } // end namespace llvm - - #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td -index 2d5ad99f6..96569e075 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td -@@ -1,4 +1,4 @@ --//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===// -+//===-- LoongArchRegisterInfo.td - LoongArch Register defs -----------*- tablegen -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -7,155 +7,367 @@ - //===----------------------------------------------------------------------===// - - //===----------------------------------------------------------------------===// --// Declarations that describe the LoongArch register files -+// Declarations that describe the LoongArch register file - //===----------------------------------------------------------------------===// -- - let Namespace = "LoongArch" in { --class LoongArchReg Enc, string n, list alt = []> -- : Register { -+def sub_32 : SubRegIndex<32>; -+def sub_64 : SubRegIndex<64>; -+def sub_128 : SubRegIndex<128>; -+def sub_fcsr1 : SubRegIndex<5>; -+def sub_fcsr2 : SubRegIndex<13, 16>; -+def sub_fcsr3 : SubRegIndex<2, 8>; -+def sub_lo : SubRegIndex<32>; -+def sub_hi : SubRegIndex<32, 32>; -+def PC : Register<"pc">; -+} -+ -+class Unallocatable { -+ bit isAllocatable = 0; -+} -+ -+/// We have banks of registers each. -+class LoongArchReg Enc, string n> : Register { - let HWEncoding = Enc; -- let AltNames = alt; -+ let Namespace = "LoongArch"; - } - --class LoongArchReg32 Enc, string n, list alt = []> -- : Register { -+class LoongArchRegWithSubRegs Enc, string n, list subregs> -+ : RegisterWithSubRegs { - let HWEncoding = Enc; -- let AltNames = alt; -+ let Namespace = "LoongArch"; - } - --def sub_32 : SubRegIndex<32>; --class LoongArchReg64 -- : Register<""> { -- let HWEncoding = subreg.HWEncoding; -- let SubRegs = [subreg]; -+/// LoongArch 32-bit CPU Registers. -+class LoongArch32GPR Enc, string n> : LoongArchReg; -+ -+/// LoongArch 64-bit CPU Registers. -+class LoongArch64GPR Enc, string n, list subregs> -+ : LoongArchRegWithSubRegs { - let SubRegIndices = [sub_32]; -- let AsmName = subreg.AsmName; -- let AltNames = subreg.AltNames; --} -- --let FallbackRegAltNameIndex = NoRegAltName in --def RegAliasName : RegAltNameIndex; --} // Namespace = "LoongArch" -- --// Integer registers -- --let RegAltNameIndices = [RegAliasName] in { -- def R0 : LoongArchReg<0, "r0", ["zero"]>, DwarfRegNum<[0]>; -- def R1 : LoongArchReg<1, "r1", ["ra"]>, DwarfRegNum<[1]>; -- def R2 : LoongArchReg<2, "r2", ["tp"]>, DwarfRegNum<[2]>; -- def R3 : LoongArchReg<3, "r3", ["sp"]>, DwarfRegNum<[3]>; -- def R4 : LoongArchReg<4, "r4", ["a0"]>, DwarfRegNum<[4]>; -- def R5 : LoongArchReg<5, "r5", ["a1"]>, DwarfRegNum<[5]>; -- def R6 : LoongArchReg<6, "r6", ["a2"]>, DwarfRegNum<[6]>; -- def R7 : LoongArchReg<7, "r7", ["a3"]>, DwarfRegNum<[7]>; -- def R8 : LoongArchReg<8, "r8", ["a4"]>, DwarfRegNum<[8]>; -- def R9 : LoongArchReg<9, "r9", ["a5"]>, DwarfRegNum<[9]>; -- def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>; -- def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>; -- def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>; -- def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>; -- def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>; -- def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>; -- def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>; -- def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>; -- def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>; -- def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>; -- def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>; -- def R21 : LoongArchReg<21, "r21", [""]>, DwarfRegNum<[21]>; -- def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, DwarfRegNum<[22]>; -- def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>; -- def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>; -- def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>; -- def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>; -- def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>; -- def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>; -- def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>; -- def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>; -- def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>; --} // RegAltNameIndices = [RegAliasName] -- --def GRLenVT : ValueTypeByHwMode<[LA32, LA64], -- [i32, i64]>; --def GRLenRI : RegInfoByHwMode< -- [LA32, LA64], -- [RegInfo<32,32,32>, RegInfo<64,64,64>]>; -- --// The order of registers represents the preferred allocation sequence. --// Registers are listed in the order caller-save, callee-save, specials. --def GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add -- // Argument registers (a0...a7) -- (sequence "R%u", 4, 11), -- // Temporary registers (t0...t8) -- (sequence "R%u", 12, 20), -- // Static register (s9/fp, s0...s8) -- (sequence "R%u", 22, 31), -- // Specials (r0, ra, tp, sp) -- (sequence "R%u", 0, 3), -- // Reserved (Non-allocatable) -- R21 -- )> { -- let RegInfos = GRLenRI; --} -- --// Floating point registers -- --let RegAltNameIndices = [RegAliasName] in { -- def F0 : LoongArchReg32<0, "f0", ["fa0"]>, DwarfRegNum<[32]>; -- def F1 : LoongArchReg32<1, "f1", ["fa1"]>, DwarfRegNum<[33]>; -- def F2 : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>; -- def F3 : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>; -- def F4 : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>; -- def F5 : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>; -- def F6 : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>; -- def F7 : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>; -- def F8 : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>; -- def F9 : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>; -- def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>; -- def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>; -- def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>; -- def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>; -- def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>; -- def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>; -- def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>; -- def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>; -- def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>; -- def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>; -- def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>; -- def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>; -- def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>; -- def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>; -- def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>; -- def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>; -- def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>; -- def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>; -- def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>; -- def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>; -- def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>; -- def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>; -- -- foreach I = 0-31 in { -- def F#I#_64 : LoongArchReg64("F"#I)>, -- DwarfRegNum<[!add(I, 32)]>; -- } --} -- --// The order of registers represents the preferred allocation sequence. --def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>; --def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>; -- --// Condition flag registers -+} -+ -+/// LoongArch 64-bit Floating-point Registers -+class FGR32 Enc, string n> : LoongArchReg; -+class FGR64 Enc, string n, list subregs> -+ : LoongArchRegWithSubRegs { -+ let SubRegIndices = [sub_lo]; -+} -+ -+// LoongArch 128-bit (aliased) LSX Registers -+class LSX128 Enc, string n, list subregs> -+ : LoongArchRegWithSubRegs { -+ let SubRegIndices = [sub_64]; -+} -+ -+// LoongArch 256-bit (aliased) LASX Registers -+class LASX256 Enc, string n, list subregs> -+ : LoongArchRegWithSubRegs { -+ let SubRegIndices = [sub_128]; -+} -+ -+//===----------------------------------------------------------------------===// -+// Registers -+//===----------------------------------------------------------------------===// -+ -+/// General Purpose 32-bit Registers -+def ZERO : LoongArch32GPR<0, "zero">, -+ DwarfRegNum<[0]>; -+def RA : LoongArch32GPR<1, "ra">, DwarfRegNum<[1]>; -+def TP : LoongArch32GPR<2, "tp">, DwarfRegNum<[2]>; -+def SP : LoongArch32GPR<3, "sp">, DwarfRegNum<[3]>; -+def A0 : LoongArch32GPR<4, "r4">, DwarfRegNum<[4]>; -+def A1 : LoongArch32GPR<5, "r5">, DwarfRegNum<[5]>; -+def A2 : LoongArch32GPR<6, "r6">, DwarfRegNum<[6]>; -+def A3 : LoongArch32GPR<7, "r7">, DwarfRegNum<[7]>; -+def A4 : LoongArch32GPR<8, "r8">, DwarfRegNum<[8]>; -+def A5 : LoongArch32GPR<9, "r9">, DwarfRegNum<[9]>; -+def A6 : LoongArch32GPR<10, "r10">, DwarfRegNum<[10]>; -+def A7 : LoongArch32GPR<11, "r11">, DwarfRegNum<[11]>; -+def T0 : LoongArch32GPR<12, "r12">, DwarfRegNum<[12]>; -+def T1 : LoongArch32GPR<13, "r13">, DwarfRegNum<[13]>; -+def T2 : LoongArch32GPR<14, "r14">, DwarfRegNum<[14]>; -+def T3 : LoongArch32GPR<15, "r15">, DwarfRegNum<[15]>; -+def T4 : LoongArch32GPR<16, "r16">, DwarfRegNum<[16]>; -+def T5 : LoongArch32GPR<17, "r17">, DwarfRegNum<[17]>; -+def T6 : LoongArch32GPR<18, "r18">, DwarfRegNum<[18]>; -+def T7 : LoongArch32GPR<19, "r19">, DwarfRegNum<[19]>; -+def T8 : LoongArch32GPR<20, "r20">, DwarfRegNum<[20]>; -+def T9 : LoongArch32GPR<21, "r21">, DwarfRegNum<[21]>; -+def FP : LoongArch32GPR<22, "r22">, DwarfRegNum<[22]>; -+def S0 : LoongArch32GPR<23, "r23">, DwarfRegNum<[23]>; -+def S1 : LoongArch32GPR<24, "r24">, DwarfRegNum<[24]>; -+def S2 : LoongArch32GPR<25, "r25">, DwarfRegNum<[25]>; -+def S3 : LoongArch32GPR<26, "r26">, DwarfRegNum<[26]>; -+def S4 : LoongArch32GPR<27, "r27">, DwarfRegNum<[27]>; -+def S5 : LoongArch32GPR<28, "r28">, DwarfRegNum<[28]>; -+def S6 : LoongArch32GPR<29, "r29">, DwarfRegNum<[29]>; -+def S7 : LoongArch32GPR<30, "r30">, DwarfRegNum<[30]>; -+def S8 : LoongArch32GPR<31, "r31">, DwarfRegNum<[31]>; -+ -+let SubRegIndices = [sub_32] in { -+def V0 : LoongArchRegWithSubRegs<4, "r4", [A0]>, DwarfRegNum<[4]>; -+def V1 : LoongArchRegWithSubRegs<5, "r5", [A1]>, DwarfRegNum<[5]>; -+} -+ -+/// General Purpose 64-bit Registers -+def ZERO_64 : LoongArch64GPR<0, "zero", [ZERO]>, DwarfRegNum<[0]>; -+def RA_64 : LoongArch64GPR<1, "ra", [RA]>, DwarfRegNum<[1]>; -+def TP_64 : LoongArch64GPR<2, "tp", [TP]>, DwarfRegNum<[2]>; -+def SP_64 : LoongArch64GPR<3, "sp", [SP]>, DwarfRegNum<[3]>; -+def A0_64 : LoongArch64GPR<4, "r4", [A0]>, DwarfRegNum<[4]>; -+def A1_64 : LoongArch64GPR<5, "r5", [A1]>, DwarfRegNum<[5]>; -+def A2_64 : LoongArch64GPR<6, "r6", [A2]>, DwarfRegNum<[6]>; -+def A3_64 : LoongArch64GPR<7, "r7", [A3]>, DwarfRegNum<[7]>; -+def A4_64 : LoongArch64GPR<8, "r8", [A4]>, DwarfRegNum<[8]>; -+def A5_64 : LoongArch64GPR<9, "r9", [A5]>, DwarfRegNum<[9]>; -+def A6_64 : LoongArch64GPR<10, "r10", [A6]>, DwarfRegNum<[10]>; -+def A7_64 : LoongArch64GPR<11, "r11", [A7]>, DwarfRegNum<[11]>; -+def T0_64 : LoongArch64GPR<12, "r12", [T0]>, DwarfRegNum<[12]>; -+def T1_64 : LoongArch64GPR<13, "r13", [T1]>, DwarfRegNum<[13]>; -+def T2_64 : LoongArch64GPR<14, "r14", [T2]>, DwarfRegNum<[14]>; -+def T3_64 : LoongArch64GPR<15, "r15", [T3]>, DwarfRegNum<[15]>; -+def T4_64 : LoongArch64GPR<16, "r16", [T4]>, DwarfRegNum<[16]>; -+def T5_64 : LoongArch64GPR<17, "r17", [T5]>, DwarfRegNum<[17]>; -+def T6_64 : LoongArch64GPR<18, "r18", [T6]>, DwarfRegNum<[18]>; -+def T7_64 : LoongArch64GPR<19, "r19", [T7]>, DwarfRegNum<[19]>; -+def T8_64 : LoongArch64GPR<20, "r20", [T8]>, DwarfRegNum<[20]>; -+def T9_64 : LoongArch64GPR<21, "r21", [T9]>, DwarfRegNum<[21]>; -+def FP_64 : LoongArch64GPR<22, "r22", [FP]>, DwarfRegNum<[22]>; -+def S0_64 : LoongArch64GPR<23, "r23", [S0]>, DwarfRegNum<[23]>; -+def S1_64 : LoongArch64GPR<24, "r24", [S1]>, DwarfRegNum<[24]>; -+def S2_64 : LoongArch64GPR<25, "r25", [S2]>, DwarfRegNum<[25]>; -+def S3_64 : LoongArch64GPR<26, "r26", [S3]>, DwarfRegNum<[26]>; -+def S4_64 : LoongArch64GPR<27, "r27", [S4]>, DwarfRegNum<[27]>; -+def S5_64 : LoongArch64GPR<28, "r28", [S5]>, DwarfRegNum<[28]>; -+def S6_64 : LoongArch64GPR<29, "r29", [S6]>, DwarfRegNum<[29]>; -+def S7_64 : LoongArch64GPR<30, "r30", [S7]>, DwarfRegNum<[30]>; -+def S8_64 : LoongArch64GPR<31, "r31", [S8]>, DwarfRegNum<[31]>; -+ -+let SubRegIndices = [sub_64] in { -+def V0_64 : LoongArch64GPR<4, "r4", [A0_64]>, DwarfRegNum<[4]>; -+def V1_64 : LoongArch64GPR<5, "r5", [A1_64]>, DwarfRegNum<[5]>; -+} -+ -+/// FP registers -+foreach I = 0-31 in -+def F#I : FGR32, DwarfRegNum<[!add(I, 32)]>; -+ -+foreach I = 0-31 in -+def F#I#_64 : FGR64("F"#I)]>, DwarfRegNum<[!add(I, 32)]>; - -+/// FP Condition Flag 0~7 - foreach I = 0-7 in - def FCC#I : LoongArchReg; - --def CFR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "FCC%u", 0, 7)> { -- let RegInfos = GRLenRI; -+/// FP Control and Status Registers, FCSR 1~3 -+foreach I = 1-3 in -+def FCSR#I : LoongArchReg; -+ -+class FCSRReg Enc, string n, list subregs> : -+ RegisterWithSubRegs { -+// field bits<2> chan_encoding = 0; -+ let Namespace = "LoongArch"; -+ let SubRegIndices = [sub_fcsr1, sub_fcsr2, sub_fcsr3]; -+// let HWEncoding{8-0} = encoding{8-0}; -+// let HWEncoding{10-9} = chan_encoding; - } - --// Control and status registers -+def FCSR0 : FCSRReg<0, "fcsr0", [FCSR1, FCSR2, FCSR3]>; - --foreach I = 0-3 in --def FCSR#I : LoongArchReg; -+/// PC register -+//let NameSpace = "LoongArch" in -+//def PC : Register<"pc">; -+ -+//===----------------------------------------------------------------------===// -+// Register Classes -+//===----------------------------------------------------------------------===// -+ -+def GPR32 : RegisterClass<"LoongArch", [i32], 32, (add -+ // Reserved -+ ZERO, -+ // Return Values and Arguments -+ A0, A1, A2, A3, A4, A5, A6, A7, -+ // Not preserved across procedure calls -+ T0, T1, T2, T3, T4, T5, T6, T7, T8, -+ // Callee save -+ S0, S1, S2, S3, S4, S5, S6, S7, S8, -+ // Reserved -+ RA, TP, SP, -+ // Reserved -+ T9, FP)>; -+ -+def GPR64 : RegisterClass<"LoongArch", [i64], 64, (add -+ // Reserved -+ ZERO_64, -+ // Return Values and Arguments -+ A0_64, A1_64, A2_64, A3_64, A4_64, A5_64, A6_64, A7_64, -+ // Not preserved across procedure calls -+ T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64, -+ // Callee save -+ S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64, S8_64, -+ // Reserved -+ RA_64, TP_64, SP_64, -+ // Reserved -+ T9_64, FP_64)>; -+ -+def GPRTC64 : RegisterClass<"LoongArch", [i64], 64, (add -+ // Return Values and Arguments -+ A0_64, A1_64, A2_64, A3_64, A4_64, A5_64, A6_64, A7_64, -+ // Not preserved across procedure calls -+ T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64)>; -+ -+/// FP Registers. -+def FGR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>; -+def FGR32 : RegisterClass<"LoongArch", [f32], 64, (sequence "F%u", 0, 31)>; -+ -+/// FP condition Flag registers. -+def FCFR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCC%u", 0, 7)>, -+ Unallocatable; -+ -+def SP32 : RegisterClass<"LoongArch", [i32], 32, (add SP)>, Unallocatable; -+def SP64 : RegisterClass<"LoongArch", [i64], 64, (add SP_64)>, Unallocatable; -+def TP32 : RegisterClass<"LoongArch", [i32], 32, (add TP)>, Unallocatable; -+def TP64 : RegisterClass<"LoongArch", [i64], 64, (add TP_64)>, Unallocatable; -+ -+/// FP control and Status registers. -+def FCSR : RegisterClass<"LoongArch", [i32], 4, (sequence "FCSR%u", 0, 3)>, -+ Unallocatable; -+ -+//LSX -+foreach I = 0-31 in -+def VR#I : LSX128("F"#I#"_64")]>, -+ DwarfRegNum<[!add(I, 32)]>; -+ -+//LASX -+foreach I = 0-31 in -+def XR#I : LASX256("VR"#I)]>, -+ DwarfRegNum<[!add(I, 32)]>; -+ -+def LSX128B: RegisterClass<"LoongArch", [v16i8], 128, -+ (sequence "VR%u", 0, 31)>; -+ -+def LSX128H: RegisterClass<"LoongArch", [v8i16], 128, -+ (sequence "VR%u", 0, 31)>; -+ -+def LSX128W: RegisterClass<"LoongArch", [v4i32, v4f32], 128, -+ (sequence "VR%u", 0, 31)>; -+ -+def LSX128D: RegisterClass<"LoongArch", [v2i64, v2f64], 128, -+ (sequence "VR%u", 0, 31)>; -+ -+def LASX256B: RegisterClass<"LoongArch", [v32i8], 256, -+ (sequence "XR%u", 0, 31)>; -+def LASX256H: RegisterClass<"LoongArch", [v16i16], 256, -+ (sequence "XR%u", 0, 31)>; -+def LASX256W: RegisterClass<"LoongArch", [v8i32, v8f32], 256, -+ (sequence "XR%u", 0, 31)>; -+def LASX256D: RegisterClass<"LoongArch", [v4i64, v4f64], 256, -+ (sequence "XR%u", 0, 31)>; -+ -+//===----------------------------------------------------------------------===// -+// Register Operands. -+//===----------------------------------------------------------------------===// - --let isAllocatable = false in --def FCSR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCSR%u", 0, 3)>; -+class LoongArchAsmRegOperand : AsmOperandClass { -+ let ParserMethod = "parseAnyRegister"; -+} -+ -+def GPR32AsmOperand : LoongArchAsmRegOperand { -+ let Name = "GPR32AsmReg"; -+ let PredicateMethod = "isGPRAsmReg"; -+} -+ -+def GPR64AsmOperand : LoongArchAsmRegOperand { -+ let Name = "GPR64AsmReg"; -+ let PredicateMethod = "isGPRAsmReg"; -+} -+ -+def FGR32AsmOperand : LoongArchAsmRegOperand { -+ let Name = "FGR32AsmReg"; -+ let PredicateMethod = "isFGRAsmReg"; -+} -+ -+def FGR64AsmOperand : LoongArchAsmRegOperand { -+ let Name = "FGR64AsmReg"; -+ let PredicateMethod = "isFGRAsmReg"; -+} -+ -+def FCSRAsmOperand : LoongArchAsmRegOperand { -+ let Name = "FCSRAsmReg"; -+} -+ -+def FCFRAsmOperand : LoongArchAsmRegOperand { -+ let Name = "FCFRAsmReg"; -+} -+ -+//LSX -+def LSX128AsmOperand : LoongArchAsmRegOperand { -+ let Name = "LSX128AsmReg"; -+} -+ -+//LASX -+def LASX256AsmOperand : LoongArchAsmRegOperand { -+ let Name = "LASX256AsmReg"; -+} -+ -+def GPR32Opnd : RegisterOperand { -+ let ParserMatchClass = GPR32AsmOperand; -+} -+ -+def GPR64Opnd : RegisterOperand { -+ let ParserMatchClass = GPR64AsmOperand; -+} -+ -+def GPRTC64Opnd : RegisterOperand { -+ let ParserMatchClass = GPR64AsmOperand; -+} -+ -+def FGR32Opnd : RegisterOperand { -+ let ParserMatchClass = FGR32AsmOperand; -+} -+ -+def FGR64Opnd : RegisterOperand { -+ let ParserMatchClass = FGR64AsmOperand; -+} -+ -+def FCSROpnd : RegisterOperand { -+ let ParserMatchClass = FCSRAsmOperand; -+} -+ -+def FCFROpnd : RegisterOperand { -+ let ParserMatchClass = FCFRAsmOperand; -+} -+ -+//LSX -+def LSX128BOpnd : RegisterOperand { -+ let ParserMatchClass = LSX128AsmOperand; -+} -+ -+def LSX128HOpnd : RegisterOperand { -+ let ParserMatchClass = LSX128AsmOperand; -+} -+ -+def LSX128WOpnd : RegisterOperand { -+ let ParserMatchClass = LSX128AsmOperand; -+} -+ -+def LSX128DOpnd : RegisterOperand { -+ let ParserMatchClass = LSX128AsmOperand; -+} -+ -+//LASX -+def LASX256BOpnd : RegisterOperand { -+ let ParserMatchClass = LASX256AsmOperand; -+} -+ -+def LASX256HOpnd : RegisterOperand { -+ let ParserMatchClass = LASX256AsmOperand; -+} -+ -+def LASX256WOpnd : RegisterOperand { -+ let ParserMatchClass = LASX256AsmOperand; -+} -+ -+def LASX256DOpnd : RegisterOperand { -+ let ParserMatchClass = LASX256AsmOperand; -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp -index ff84e7c8c..ef990ae09 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information -*- C++ -*--=// -+//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information --------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,7 +11,16 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchSubtarget.h" --#include "LoongArchFrameLowering.h" -+#include "LoongArch.h" -+#include "LoongArchMachineFunction.h" -+#include "LoongArchRegisterInfo.h" -+#include "LoongArchTargetMachine.h" -+#include "llvm/IR/Attributes.h" -+#include "llvm/IR/Function.h" -+#include "llvm/Support/CommandLine.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/MC/TargetRegistry.h" -+#include "llvm/Support/raw_ostream.h" - - using namespace llvm; - -@@ -23,32 +32,74 @@ using namespace llvm; - - void LoongArchSubtarget::anchor() {} - --LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies( -- const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, -- StringRef ABIName) { -- bool Is64Bit = TT.isArch64Bit(); -- if (CPU.empty()) -- CPU = Is64Bit ? "generic-la64" : "generic-la32"; -+LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, -+ StringRef FS, -+ const LoongArchTargetMachine &TM, -+ MaybeAlign StackAlignOverride) -+ : LoongArchGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), HasLA64(false), -+ IsSoftFloat(false), IsSingleFloat(false), IsFP64bit(false), HasLSX(false), -+ HasLASX(false), UnalignedAccess(false), -+ StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), -+ TSInfo(), InstrInfo(initializeSubtargetDependencies(CPU, FS, TM)), -+ FrameLowering(*this), TLInfo(TM, *this) { -+ -+ // Check if Architecture and ABI are compatible. -+ assert(((!is64Bit() && isABI_LP32()) || -+ (is64Bit() && (isABI_LPX32() || isABI_LP64()))) && -+ "Invalid Arch & ABI pair."); -+ -+ if (hasLSX() && !isFP64bit()) -+ report_fatal_error("LSX requires 64-bit floating point register." -+ "See -mattr=+fp64.", -+ false); -+ -+ assert(isFP64bit()); -+} -+ -+bool LoongArchSubtarget::isPositionIndependent() const { -+ return TM.isPositionIndependent(); -+} -+ -+/// This overrides the PostRAScheduler bit in the SchedModel for any CPU. -+bool LoongArchSubtarget::enablePostRAScheduler() const { return true; } - -- if (TuneCPU.empty()) -- TuneCPU = CPU; -+void LoongArchSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { -+ CriticalPathRCs.clear(); -+ CriticalPathRCs.push_back(is64Bit() ? &LoongArch::GPR64RegClass -+ : &LoongArch::GPR32RegClass); -+} -+ -+CodeGenOpt::Level LoongArchSubtarget::getOptLevelToEnablePostRAScheduler() const { -+ return CodeGenOpt::Aggressive; -+} -+ -+LoongArchSubtarget & -+LoongArchSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, -+ const TargetMachine &TM) { -+ StringRef CPUName = LoongArch_MC::selectLoongArchCPU(TM.getTargetTriple(), CPU); - -- ParseSubtargetFeatures(CPU, TuneCPU, FS); -- if (Is64Bit) { -- GRLenVT = MVT::i64; -- GRLen = 64; -+ // Parse features string. -+ ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS); -+ // Initialize scheduling itinerary for the specified CPU. -+ InstrItins = getInstrItineraryForCPU(CPUName); -+ -+ if (StackAlignOverride) -+ stackAlignment = *StackAlignOverride; -+ else if (isABI_LPX32() || isABI_LP64()) -+ stackAlignment = Align(16); -+ else { -+ assert(isABI_LP32() && "Unknown ABI for stack alignment!"); -+ stackAlignment = Align(8); - } - -- // TODO: ILP32{S,F} LP64{S,F} -- TargetABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D; - return *this; - } - --LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, -- StringRef TuneCPU, StringRef FS, -- StringRef ABIName, -- const TargetMachine &TM) -- : LoongArchGenSubtargetInfo(TT, CPU, TuneCPU, FS), -- FrameLowering( -- initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), -- InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {} -+Reloc::Model LoongArchSubtarget::getRelocationModel() const { -+ return TM.getRelocationModel(); -+} -+ -+bool LoongArchSubtarget::isABI_LP64() const { return getABI().IsLP64(); } -+bool LoongArchSubtarget::isABI_LPX32() const { return getABI().IsLPX32(); } -+bool LoongArchSubtarget::isABI_LP32() const { return getABI().IsLP32(); } -+const LoongArchABIInfo &LoongArchSubtarget::getABI() const { return TM.getABI(); } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h -index fbe7a176b..588d9f46b 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h -@@ -1,4 +1,4 @@ --//===- LoongArchSubtarget.h - Define Subtarget for the LoongArch -*- C++ -*-==// -+//===-- LoongArchSubtarget.h - Define Subtarget for the LoongArch ---------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -13,15 +13,16 @@ - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H - -+#include "MCTargetDesc/LoongArchABIInfo.h" - #include "LoongArchFrameLowering.h" - #include "LoongArchISelLowering.h" - #include "LoongArchInstrInfo.h" --#include "LoongArchRegisterInfo.h" --#include "MCTargetDesc/LoongArchBaseInfo.h" - #include "llvm/CodeGen/SelectionDAGTargetInfo.h" - #include "llvm/CodeGen/TargetSubtargetInfo.h" - #include "llvm/IR/DataLayout.h" --#include "llvm/Target/TargetMachine.h" -+#include "llvm/MC/MCInstrItineraries.h" -+#include "llvm/Support/ErrorHandling.h" -+#include - - #define GET_SUBTARGETINFO_HEADER - #include "LoongArchGenSubtargetInfo.inc" -@@ -29,61 +30,114 @@ - namespace llvm { - class StringRef; - -+class LoongArchTargetMachine; -+ - class LoongArchSubtarget : public LoongArchGenSubtargetInfo { - virtual void anchor(); -- bool HasLA64 = false; -- bool HasBasicF = false; -- bool HasBasicD = false; -- bool HasExtLSX = false; -- bool HasExtLASX = false; -- bool HasExtLVZ = false; -- bool HasExtLBT = false; -- unsigned GRLen = 32; -- MVT GRLenVT = MVT::i32; -- LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown; -- LoongArchFrameLowering FrameLowering; -- LoongArchInstrInfo InstrInfo; -- LoongArchRegisterInfo RegInfo; -- LoongArchTargetLowering TLInfo; -- -- /// Initializes using the passed in CPU and feature strings so that we can -- /// use initializer lists for subtarget initialization. -- LoongArchSubtarget &initializeSubtargetDependencies(const Triple &TT, -- StringRef CPU, -- StringRef TuneCPU, -- StringRef FS, -- StringRef ABIName); -+ -+ // HasLA64 - The target processor has LA64 ISA support. -+ bool HasLA64; -+ -+ // IsSoftFloat - The target does not support any floating point instructions. -+ bool IsSoftFloat; -+ -+ // IsSingleFloat - The target only supports single precision float -+ // point operations. This enable the target to use all 32 32-bit -+ // floating point registers instead of only using even ones. -+ bool IsSingleFloat; -+ -+ // IsFP64bit - The target processor has 64-bit floating point registers. -+ bool IsFP64bit; -+ -+ /// Features related to the presence of specific instructions. -+ -+ // HasLSX - Supports LSX. -+ bool HasLSX; -+ -+ // HasLASX - Supports LASX. -+ bool HasLASX; -+ -+ /// The minimum alignment known to hold of the stack frame on -+ /// entry to the function and which must be maintained by every function. -+ Align stackAlignment; -+ -+ // Allow unaligned memory accesses. -+ bool UnalignedAccess; -+ -+ /// The overridden stack alignment. -+ MaybeAlign StackAlignOverride; -+ -+ InstrItineraryData InstrItins; -+ -+ const LoongArchTargetMachine &TM; -+ -+ Triple TargetTriple; -+ -+ const SelectionDAGTargetInfo TSInfo; -+ const LoongArchInstrInfo InstrInfo; -+ const LoongArchFrameLowering FrameLowering; -+ const LoongArchTargetLowering TLInfo; - - public: -- // Initializes the data members to match that of the specified triple. -- LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, -- StringRef FS, StringRef ABIName, const TargetMachine &TM); -+ bool isPositionIndependent() const; -+ /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. -+ bool enablePostRAScheduler() const override; -+ void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; -+ CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; -+ -+ bool isABI_LP64() const; -+ bool isABI_LPX32() const; -+ bool isABI_LP32() const; -+ const LoongArchABIInfo &getABI() const; - -- // Parses features string setting specified subtarget options. The -- // definition of this function is auto-generated by tblgen. -+ /// This constructor initializes the data members to match that -+ /// of the specified triple. -+ LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef FS, -+ const LoongArchTargetMachine &TM, MaybeAlign StackAlignOverride); -+ -+ /// ParseSubtargetFeatures - Parses features string setting specified -+ /// subtarget options. Definition of function is auto generated by tblgen. - void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); - -- const LoongArchFrameLowering *getFrameLowering() const override { -+ bool is64Bit() const { return HasLA64; } -+ bool isFP64bit() const { return IsFP64bit; } -+ unsigned getGPRSizeInBytes() const { return is64Bit() ? 8 : 4; } -+ bool isSingleFloat() const { return IsSingleFloat; } -+ bool hasLSX() const { return HasLSX; } -+ bool hasLASX() const { return HasLASX; } -+ bool useSoftFloat() const { return IsSoftFloat; } -+ -+ bool allowUnalignedAccess() const { return UnalignedAccess; } -+ -+ bool isXRaySupported() const override { return true; } -+ -+ Align getStackAlignment() const { return stackAlignment; } -+ -+ // Grab relocation model -+ Reloc::Model getRelocationModel() const; -+ -+ LoongArchSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, -+ const TargetMachine &TM); -+ -+ const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { -+ return &TSInfo; -+ } -+ const LoongArchInstrInfo *getInstrInfo() const override { -+ return &InstrInfo; -+ } -+ const TargetFrameLowering *getFrameLowering() const override { - return &FrameLowering; - } -- const LoongArchInstrInfo *getInstrInfo() const override { return &InstrInfo; } - const LoongArchRegisterInfo *getRegisterInfo() const override { -- return &RegInfo; -+ return &InstrInfo.getRegisterInfo(); - } - const LoongArchTargetLowering *getTargetLowering() const override { - return &TLInfo; - } -- bool is64Bit() const { return HasLA64; } -- bool hasBasicF() const { return HasBasicF; } -- bool hasBasicD() const { return HasBasicD; } -- bool hasExtLSX() const { return HasExtLSX; } -- bool hasExtLASX() const { return HasExtLASX; } -- bool hasExtLVZ() const { return HasExtLVZ; } -- bool hasExtLBT() const { return HasExtLBT; } -- MVT getGRLenVT() const { return GRLenVT; } -- unsigned getGRLen() const { return GRLen; } -- LoongArchABI::ABI getTargetABI() const { return TargetABI; } -+ const InstrItineraryData *getInstrItineraryData() const override { -+ return &InstrItins; -+ } - }; --} // end namespace llvm -+} // End llvm namespace - --#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp -index 7ba5848e0..f8a1dc5fa 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// -+//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch -------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -12,12 +12,29 @@ - - #include "LoongArchTargetMachine.h" - #include "LoongArch.h" --#include "MCTargetDesc/LoongArchBaseInfo.h" --#include "TargetInfo/LoongArchTargetInfo.h" -+#include "LoongArchISelDAGToDAG.h" -+#include "LoongArchSubtarget.h" -+#include "LoongArchTargetObjectFile.h" -+#include "LoongArchTargetTransformInfo.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/ADT/Optional.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/Analysis/TargetTransformInfo.h" -+#include "llvm/CodeGen/BasicTTIImpl.h" -+#include "llvm/CodeGen/MachineFunction.h" - #include "llvm/CodeGen/Passes.h" --#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" - #include "llvm/CodeGen/TargetPassConfig.h" -+#include "llvm/IR/Attributes.h" -+#include "llvm/IR/Function.h" - #include "llvm/MC/TargetRegistry.h" -+#include "llvm/Support/CodeGen.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/raw_ostream.h" -+#include "llvm/Target/TargetOptions.h" -+#include -+#include - - using namespace llvm; - -@@ -26,29 +43,63 @@ using namespace llvm; - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { - // Register the target. - RegisterTargetMachine X(getTheLoongArch32Target()); -- RegisterTargetMachine Y(getTheLoongArch64Target()); -+ RegisterTargetMachine A(getTheLoongArch64Target()); - } - --static std::string computeDataLayout(const Triple &TT) { -- if (TT.isArch64Bit()) -- return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; -- assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); -- return "e-m:e-p:32:32-i64:64-n32-S128"; -+static std::string computeDataLayout(const Triple &TT, StringRef CPU, -+ const TargetOptions &Options) { -+ std::string Ret; -+ LoongArchABIInfo ABI = LoongArchABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); -+ -+ Ret += "e"; -+ -+ if (ABI.IsLP32()) -+ Ret += "-m:m"; -+ else -+ Ret += "-m:e"; -+ -+ // Pointers are 32 bit on some ABIs. -+ if (!ABI.IsLP64()) -+ Ret += "-p:32:32"; -+ -+ // 8 and 16 bit integers only need to have natural alignment, but try to -+ // align them to 32 bits. 64 bit integers have natural alignment. -+ Ret += "-i8:8:32-i16:16:32-i64:64"; -+ -+ // 32 bit registers are always available and the stack is at least 64 bit -+ // aligned. On LP64 64 bit registers are also available and the stack is -+ // 128 bit aligned. -+ if (ABI.IsLP64() || ABI.IsLPX32()) -+ Ret += "-n32:64-S128"; -+ else -+ Ret += "-n32-S64"; -+ -+ return Ret; - } - --static Reloc::Model getEffectiveRelocModel(const Triple &TT, -+static Reloc::Model getEffectiveRelocModel(bool JIT, - Optional RM) { -- return RM.value_or(Reloc::Static); -+ if (!RM.hasValue() || JIT) -+ return Reloc::Static; -+ return *RM; - } - --LoongArchTargetMachine::LoongArchTargetMachine( -- const Target &T, const Triple &TT, StringRef CPU, StringRef FS, -- const TargetOptions &Options, Optional RM, -- Optional CM, CodeGenOpt::Level OL, bool JIT) -- : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, -- getEffectiveRelocModel(TT, RM), -+// On function prologue, the stack is created by decrementing -+// its pointer. Once decremented, all references are done with positive -+// offset from the stack/frame pointer, using StackGrowsUp enables -+// an easier handling. -+// Using CodeModel::Large enables different CALL behavior. -+LoongArchTargetMachine::LoongArchTargetMachine(const Target &T, const Triple &TT, -+ StringRef CPU, StringRef FS, -+ const TargetOptions &Options, -+ Optional RM, -+ Optional CM, -+ CodeGenOpt::Level OL, bool JIT) -+ : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, -+ CPU, FS, Options, getEffectiveRelocModel(JIT, RM), - getEffectiveCodeModel(CM, CodeModel::Small), OL), -- TLOF(std::make_unique()) { -+ TLOF(std::make_unique()), -+ ABI(LoongArchABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)) { - initAsmInfo(); - } - -@@ -57,44 +108,45 @@ LoongArchTargetMachine::~LoongArchTargetMachine() = default; - const LoongArchSubtarget * - LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { - Attribute CPUAttr = F.getFnAttribute("target-cpu"); -- Attribute TuneAttr = F.getFnAttribute("tune-cpu"); - Attribute FSAttr = F.getFnAttribute("target-features"); - -- std::string CPU = -- CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; -- std::string TuneCPU = -- TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; -- std::string FS = -- FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; -+ std::string CPU = !CPUAttr.hasAttribute(Attribute::None) -+ ? CPUAttr.getValueAsString().str() -+ : TargetCPU; -+ std::string FS = !FSAttr.hasAttribute(Attribute::None) -+ ? FSAttr.getValueAsString().str() -+ : TargetFS; -+ -+ // FIXME: This is related to the code below to reset the target options, -+ // we need to know whether or not the soft float flag is set on the -+ // function, so we can enable it as a subtarget feature. -+ bool softFloat = -+ F.hasFnAttribute("use-soft-float") && -+ F.getFnAttribute("use-soft-float").getValueAsString() == "true"; -+ -+ if (softFloat) -+ FS += FS.empty() ? "+soft-float" : ",+soft-float"; - -- std::string Key = CPU + TuneCPU + FS; -- auto &I = SubtargetMap[Key]; -+ auto &I = SubtargetMap[CPU + FS]; - if (!I) { - // This needs to be done before we create a new subtarget since any - // creation will depend on the TM and the code generation flags on the - // function that reside in TargetOptions. - resetTargetOptions(F); -- auto ABIName = Options.MCOptions.getABIName(); -- if (const MDString *ModuleTargetABI = dyn_cast_or_null( -- F.getParent()->getModuleFlag("target-abi"))) { -- auto TargetABI = LoongArchABI::getTargetABI(ABIName); -- if (TargetABI != LoongArchABI::ABI_Unknown && -- ModuleTargetABI->getString() != ABIName) { -- report_fatal_error("-target-abi option != target-abi module flag"); -- } -- ABIName = ModuleTargetABI->getString(); -- } -- I = std::make_unique(TargetTriple, CPU, TuneCPU, FS, -- ABIName, *this); -+ I = std::make_unique(TargetTriple, CPU, FS, *this, -+ MaybeAlign(F.getParent()->getOverrideStackAlignment())); - } - return I.get(); - } - - namespace { -+ -+/// LoongArch Code Generator Pass Configuration Options. - class LoongArchPassConfig : public TargetPassConfig { - public: - LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) -- : TargetPassConfig(TM, PM) {} -+ : TargetPassConfig(TM, PM) { -+ } - - LoongArchTargetMachine &getLoongArchTargetMachine() const { - return getTM(); -@@ -102,22 +154,42 @@ public: - - void addIRPasses() override; - bool addInstSelector() override; -+ void addPreEmitPass() override; - }; --} // end namespace - --TargetPassConfig * --LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { -+} // end anonymous namespace -+ -+TargetPassConfig *LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { - return new LoongArchPassConfig(*this, PM); - } - - void LoongArchPassConfig::addIRPasses() { -- addPass(createAtomicExpandPass()); -- - TargetPassConfig::addIRPasses(); -+ addPass(createAtomicExpandPass()); - } -- -+// Install an instruction selector pass using -+// the ISelDag to gen LoongArch code. - bool LoongArchPassConfig::addInstSelector() { -- addPass(createLoongArchISelDag(getLoongArchTargetMachine())); -- -+ addPass(createLoongArchModuleISelDagPass()); -+ addPass(createLoongArchISelDag(getLoongArchTargetMachine(), getOptLevel())); - return false; - } -+ -+TargetTransformInfo -+LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const { -+ LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); -+ return TargetTransformInfo(BasicTTIImpl(this, F)); -+} -+ -+// Implemented by targets that want to run passes immediately before -+// machine code is emitted. return true if -print-machineinstrs should -+// print out the code after the passes. -+void LoongArchPassConfig::addPreEmitPass() { -+ // Expand pseudo instructions that are sensitive to register allocation. -+ addPass(createLoongArchExpandPseudoPass()); -+ -+ // Relax conditional branch instructions if they're otherwise out of -+ // range of their destination. -+ // This pass must be run after any pseudo instruction expansion -+ addPass(&BranchRelaxationPassID); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h -index cbd872031..8e395d183 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h -@@ -1,4 +1,4 @@ --//=- LoongArchTargetMachine.h - Define TargetMachine for LoongArch -*- C++ -*-// -+//===- LoongArchTargetMachine.h - Define TargetMachine for LoongArch ------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -13,25 +13,33 @@ - #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H - #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H - -+#include "MCTargetDesc/LoongArchABIInfo.h" - #include "LoongArchSubtarget.h" -+#include "llvm/ADT/Optional.h" -+#include "llvm/ADT/StringMap.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/Support/CodeGen.h" - #include "llvm/Target/TargetMachine.h" -+#include - - namespace llvm { - - class LoongArchTargetMachine : public LLVMTargetMachine { - std::unique_ptr TLOF; -+ // Selected ABI -+ LoongArchABIInfo ABI; -+ - mutable StringMap> SubtargetMap; - - public: - LoongArchTargetMachine(const Target &T, const Triple &TT, StringRef CPU, -- StringRef FS, const TargetOptions &Options, -- Optional RM, -- Optional CM, CodeGenOpt::Level OL, -- bool JIT); -+ StringRef FS, const TargetOptions &Options, -+ Optional RM, Optional CM, -+ CodeGenOpt::Level OL, bool JIT); - ~LoongArchTargetMachine() override; - -+ TargetTransformInfo getTargetTransformInfo(const Function &F) const override; - const LoongArchSubtarget *getSubtargetImpl(const Function &F) const override; -- const LoongArchSubtarget *getSubtargetImpl() const = delete; - - // Pass Pipeline Configuration - TargetPassConfig *createPassConfig(PassManagerBase &PM) override; -@@ -39,6 +47,20 @@ public: - TargetLoweringObjectFile *getObjFileLowering() const override { - return TLOF.get(); - } -+ -+ /// Returns true if a cast between SrcAS and DestAS is a noop. -+ bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override { -+ // Mips doesn't have any special address spaces so we just reserve -+ // the first 256 for software use (e.g. OpenCL) and treat casts -+ // between them as noops. -+ return SrcAS < 256 && DestAS < 256; -+ } -+ -+ const LoongArchABIInfo &getABI() const { return ABI; } -+ -+ bool isMachineVerifierClean() const override { -+ return false; -+ } - }; - - } // end namespace llvm -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp -new file mode 100644 -index 000000000..9c6250d28 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp -@@ -0,0 +1,26 @@ -+//===-- LoongArchTargetObjectFile.cpp - LoongArch Object Files ----------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchTargetObjectFile.h" -+#include "LoongArchSubtarget.h" -+#include "LoongArchTargetMachine.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" -+#include "llvm/BinaryFormat/ELF.h" -+#include "llvm/IR/DataLayout.h" -+#include "llvm/IR/DerivedTypes.h" -+#include "llvm/IR/GlobalVariable.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCSectionELF.h" -+#include "llvm/Support/CommandLine.h" -+#include "llvm/Target/TargetMachine.h" -+using namespace llvm; -+ -+void LoongArchTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ -+ TargetLoweringObjectFileELF::Initialize(Ctx, TM); -+ InitializeELF(TM.Options.UseInitArray); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h -new file mode 100644 -index 000000000..a50c57171 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h -@@ -0,0 +1,24 @@ -+//===-- llvm/Target/LoongArchTargetObjectFile.h - LoongArch Object Info ---*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETOBJECTFILE_H -+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETOBJECTFILE_H -+ -+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -+ -+namespace llvm { -+class LoongArchTargetMachine; -+ class LoongArchTargetObjectFile : public TargetLoweringObjectFileELF { -+ -+ public: -+ -+ void Initialize(MCContext &Ctx, const TargetMachine &TM) override; -+ }; -+} // end namespace llvm -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h -new file mode 100644 -index 000000000..a9adc32d0 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h -@@ -0,0 +1,130 @@ -+//===-- LoongArchTargetStreamer.h - LoongArch Target Streamer ------------*- C++ -*--===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETSTREAMER_H -+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETSTREAMER_H -+ -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "llvm/ADT/Optional.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/MC/MCELFStreamer.h" -+#include "llvm/MC/MCRegisterInfo.h" -+#include "llvm/MC/MCStreamer.h" -+ -+namespace llvm { -+ -+class formatted_raw_ostream; -+ -+struct LoongArchFPABIInfo; -+ -+class LoongArchTargetStreamer : public MCTargetStreamer { -+public: -+ LoongArchTargetStreamer(MCStreamer &S); -+ -+ virtual void setPic(bool Value) {} -+ -+ virtual void emitDirectiveOptionPic0(); -+ virtual void emitDirectiveOptionPic2(); -+ -+ virtual void emitDirectiveSetArch(StringRef Arch); -+ virtual void emitDirectiveSetLoongArch32(); -+ virtual void emitDirectiveSetloongarch64(); -+ -+ void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitRXX(unsigned Opcode, unsigned Reg0, MCOperand Op1, MCOperand Op2, -+ SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, -+ SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, -+ SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int32_t Imm, -+ SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitRRXX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, -+ MCOperand Op3, SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0, -+ int16_t Imm1, int16_t Imm2, SMLoc IDLoc, -+ const MCSubtargetInfo *STI); -+ void emitAdd(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit, -+ const MCSubtargetInfo *STI); -+ void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, -+ SMLoc IDLoc, const MCSubtargetInfo *STI); -+ void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI); -+ -+ void forbidModuleDirective() { ModuleDirectiveAllowed = false; } -+ void reallowModuleDirective() { ModuleDirectiveAllowed = true; } -+ bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } -+ -+ template -+ void updateABIInfo(const PredicateLibrary &P) { -+ ABI = P.getABI(); -+ } -+ -+ const LoongArchABIInfo &getABI() const { -+ assert(ABI.hasValue() && "ABI hasn't been set!"); -+ return *ABI; -+ } -+ -+protected: -+ llvm::Optional ABI; -+ -+ bool GPRInfoSet; -+ -+ bool FPRInfoSet; -+ -+ bool FrameInfoSet; -+ int FrameOffset; -+ unsigned FrameReg; -+ unsigned ReturnReg; -+ -+private: -+ bool ModuleDirectiveAllowed; -+}; -+ -+// This part is for ascii assembly output -+class LoongArchTargetAsmStreamer : public LoongArchTargetStreamer { -+ formatted_raw_ostream &OS; -+ -+public: -+ LoongArchTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); -+ -+ void emitDirectiveOptionPic0() override; -+ void emitDirectiveOptionPic2() override; -+ -+ void emitDirectiveSetArch(StringRef Arch) override; -+ void emitDirectiveSetLoongArch32() override; -+ void emitDirectiveSetloongarch64() override; -+}; -+ -+// This part is for ELF object output -+class LoongArchTargetELFStreamer : public LoongArchTargetStreamer { -+ const MCSubtargetInfo &STI; -+ bool Pic; -+ -+public: -+ MCELFStreamer &getStreamer(); -+ LoongArchTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); -+ -+ void setPic(bool Value) override { Pic = Value; } -+ -+ void emitLabel(MCSymbol *Symbol) override; -+ void finish() override; -+ -+ void emitDirectiveOptionPic0() override; -+ void emitDirectiveOptionPic2() override; -+}; -+} -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp -new file mode 100644 -index 000000000..9510dc027 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp -@@ -0,0 +1,325 @@ -+//===-- LoongArchTargetTransformInfo.cpp - LoongArch specific TTI pass -+//----------------===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+/// \file -+/// This file implements a TargetTransformInfo analysis pass specific to the -+/// LoongArch target machine. It uses the target's detailed information to -+/// provide more precise answers to certain TTI queries, while letting the -+/// target independent and default TTI implementations handle the rest. -+/// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchTargetTransformInfo.h" -+#include "llvm/Analysis/TargetTransformInfo.h" -+#include "llvm/CodeGen/BasicTTIImpl.h" -+#include "llvm/CodeGen/CostTable.h" -+#include "llvm/CodeGen/TargetLowering.h" -+#include "llvm/IR/IntrinsicInst.h" -+#include "llvm/Support/Debug.h" -+ -+using namespace llvm; -+ -+#define DEBUG_TYPE "LoongArchtti" -+ -+//===----------------------------------------------------------------------===// -+// -+// LoongArch cost model. -+// -+//===----------------------------------------------------------------------===// -+ -+bool LoongArchTTIImpl::areInlineCompatible(const Function *Caller, -+ const Function *Callee) const { -+ const TargetMachine &TM = getTLI()->getTargetMachine(); -+ -+ const FeatureBitset &CallerBits = -+ TM.getSubtargetImpl(*Caller)->getFeatureBits(); -+ const FeatureBitset &CalleeBits = -+ TM.getSubtargetImpl(*Callee)->getFeatureBits(); -+ -+ // Inline a callee if its target-features are a subset of the callers -+ // target-features. -+ return (CallerBits & CalleeBits) == CalleeBits; -+} -+ -+TargetTransformInfo::PopcntSupportKind -+LoongArchTTIImpl::getPopcntSupport(unsigned TyWidth) { -+ assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); -+ if (TyWidth == 32 || TyWidth == 64) -+ return TTI::PSK_FastHardware; -+ return TTI::PSK_Software; -+} -+ -+unsigned LoongArchTTIImpl::getNumberOfRegisters(bool Vector) { -+ if (Vector && !ST->hasLSX()) -+ return 0; -+ -+ return 32; -+} -+ -+unsigned LoongArchTTIImpl::getRegisterBitWidth(bool Vector) const { -+ if (Vector) { -+ if (ST->hasLASX()) -+ return 256; -+ -+ if (ST->hasLSX()) -+ return 128; -+ -+ return 0; -+ } -+ return 64; -+} -+ -+unsigned LoongArchTTIImpl::getMaxInterleaveFactor(unsigned VF) { -+ if (VF == 1) -+ return 1; -+ return 2; -+} -+ -+InstructionCost LoongArchTTIImpl::getArithmeticInstrCost( -+ unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, -+ TTI::OperandValueKind Op1Info, TTI::OperandValueKind Op2Info, -+ TTI::OperandValueProperties Opd1PropInfo, -+ TTI::OperandValueProperties Opd2PropInfo, ArrayRef Args, -+ const Instruction *CxtI) { -+ -+ std::pair LT = TLI->getTypeLegalizationCost(DL, Ty); -+ -+ int ISD = TLI->InstructionOpcodeToISD(Opcode); -+ assert(ISD && "Invalid opcode"); -+ -+ static const CostTblEntry LASXCostTable[] = { -+ -+ {ISD::SHL, MVT::v32i8, 1}, -+ {ISD::SHL, MVT::v16i16, 1}, -+ {ISD::SHL, MVT::v8i32, 1}, -+ {ISD::SHL, MVT::v4i64, 1}, -+ -+ {ISD::SRL, MVT::v32i8, 1}, -+ {ISD::SRL, MVT::v16i16, 1}, -+ {ISD::SRL, MVT::v8i32, 1}, -+ {ISD::SRL, MVT::v4i64, 1}, -+ -+ {ISD::SRA, MVT::v32i8, 1}, -+ {ISD::SRA, MVT::v16i16, 1}, -+ {ISD::SRA, MVT::v8i32, 1}, -+ {ISD::SRA, MVT::v4i64, 1}, -+ -+ {ISD::SUB, MVT::v32i8, 1}, -+ {ISD::SUB, MVT::v16i16, 1}, -+ {ISD::SUB, MVT::v8i32, 1}, -+ {ISD::SUB, MVT::v4i64, 1}, -+ -+ {ISD::ADD, MVT::v32i8, 1}, -+ {ISD::ADD, MVT::v16i16, 1}, -+ {ISD::ADD, MVT::v8i32, 1}, -+ {ISD::ADD, MVT::v4i64, 1}, -+ -+ {ISD::MUL, MVT::v32i8, 1}, -+ {ISD::MUL, MVT::v16i16, 1}, -+ {ISD::MUL, MVT::v8i32, 1}, -+ {ISD::MUL, MVT::v4i64, 1}, -+ -+ {ISD::SDIV, MVT::v32i8, 29}, -+ {ISD::SDIV, MVT::v16i16, 19}, -+ {ISD::SDIV, MVT::v8i32, 14}, -+ {ISD::SDIV, MVT::v4i64, 13}, -+ -+ {ISD::UDIV, MVT::v32i8, 29}, -+ {ISD::UDIV, MVT::v16i16, 19}, -+ {ISD::UDIV, MVT::v8i32, 14}, -+ {ISD::UDIV, MVT::v4i64, 13}, -+ -+ {ISD::SREM, MVT::v32i8, 33}, -+ {ISD::SREM, MVT::v16i16, 21}, -+ {ISD::SREM, MVT::v8i32, 15}, -+ {ISD::SREM, MVT::v4i64, 13}, -+ -+ {ISD::UREM, MVT::v32i8, 29}, -+ {ISD::UREM, MVT::v16i16, 19}, -+ {ISD::UREM, MVT::v8i32, 14}, -+ {ISD::UREM, MVT::v4i64, 13}, -+ -+ {ISD::FADD, MVT::f64, 1}, -+ {ISD::FADD, MVT::f32, 1}, -+ {ISD::FADD, MVT::v4f64, 1}, -+ {ISD::FADD, MVT::v8f32, 1}, -+ -+ {ISD::FSUB, MVT::f64, 1}, -+ {ISD::FSUB, MVT::f32, 1}, -+ {ISD::FSUB, MVT::v4f64, 1}, -+ {ISD::FSUB, MVT::v8f32, 1}, -+ -+ {ISD::FMUL, MVT::f64, 1}, -+ {ISD::FMUL, MVT::f32, 1}, -+ {ISD::FMUL, MVT::v4f64, 1}, -+ {ISD::FMUL, MVT::v8f32, 1}, -+ -+ {ISD::FDIV, MVT::f32, 12}, -+ {ISD::FDIV, MVT::f64, 10}, -+ {ISD::FDIV, MVT::v8f32, 12}, -+ {ISD::FDIV, MVT::v4f64, 10} -+ -+ }; -+ -+ if (ST->hasLASX()) -+ if (const auto *Entry = CostTableLookup(LASXCostTable, ISD, LT.second)) -+ return LT.first * Entry->Cost; -+ -+ static const CostTblEntry LSXCostTable[] = { -+ -+ {ISD::SHL, MVT::v16i8, 1}, -+ {ISD::SHL, MVT::v8i16, 1}, -+ {ISD::SHL, MVT::v4i32, 1}, -+ {ISD::SHL, MVT::v2i64, 1}, -+ -+ {ISD::SRL, MVT::v16i8, 1}, -+ {ISD::SRL, MVT::v8i16, 1}, -+ {ISD::SRL, MVT::v4i32, 1}, -+ {ISD::SRL, MVT::v2i64, 1}, -+ -+ {ISD::SRA, MVT::v16i8, 1}, -+ {ISD::SRA, MVT::v8i16, 1}, -+ {ISD::SRA, MVT::v4i32, 1}, -+ {ISD::SRA, MVT::v2i64, 1}, -+ -+ {ISD::SUB, MVT::v16i8, 1}, -+ {ISD::SUB, MVT::v8i16, 1}, -+ {ISD::SUB, MVT::v4i32, 1}, -+ {ISD::SUB, MVT::v2i64, 1}, -+ -+ {ISD::ADD, MVT::v16i8, 1}, -+ {ISD::ADD, MVT::v8i16, 1}, -+ {ISD::ADD, MVT::v4i32, 1}, -+ {ISD::ADD, MVT::v2i64, 1}, -+ -+ {ISD::MUL, MVT::v16i8, 1}, -+ {ISD::MUL, MVT::v8i16, 1}, -+ {ISD::MUL, MVT::v4i32, 1}, -+ {ISD::MUL, MVT::v2i64, 1}, -+ -+ {ISD::SDIV, MVT::v16i8, 29}, -+ {ISD::SDIV, MVT::v8i16, 19}, -+ {ISD::SDIV, MVT::v4i32, 14}, -+ {ISD::SDIV, MVT::v2i64, 13}, -+ -+ {ISD::UDIV, MVT::v16i8, 29}, -+ {ISD::UDIV, MVT::v8i16, 19}, -+ {ISD::UDIV, MVT::v4i32, 14}, -+ {ISD::UDIV, MVT::v2i64, 13}, -+ -+ {ISD::SREM, MVT::v16i8, 33}, -+ {ISD::SREM, MVT::v8i16, 21}, -+ {ISD::SREM, MVT::v4i32, 15}, -+ {ISD::SREM, MVT::v2i64, 13}, -+ -+ {ISD::UREM, MVT::v16i8, 29}, -+ {ISD::UREM, MVT::v8i16, 19}, -+ {ISD::UREM, MVT::v4i32, 14}, -+ {ISD::UREM, MVT::v2i64, 13}, -+ -+ {ISD::FADD, MVT::f64, 1}, -+ {ISD::FADD, MVT::f32, 1}, -+ {ISD::FADD, MVT::v2f64, 1}, -+ {ISD::FADD, MVT::v4f32, 1}, -+ -+ {ISD::FSUB, MVT::f64, 1}, -+ {ISD::FSUB, MVT::f32, 1}, -+ {ISD::FSUB, MVT::v2f64, 1}, -+ {ISD::FSUB, MVT::v4f32, 1}, -+ -+ {ISD::FMUL, MVT::f64, 1}, -+ {ISD::FMUL, MVT::f32, 1}, -+ {ISD::FMUL, MVT::v2f64, 1}, -+ {ISD::FMUL, MVT::v4f32, 1}, -+ -+ {ISD::FDIV, MVT::f32, 12}, -+ {ISD::FDIV, MVT::f64, 10}, -+ {ISD::FDIV, MVT::v4f32, 12}, -+ {ISD::FDIV, MVT::v2f64, 10} -+ -+ }; -+ -+ if (ST->hasLSX()) -+ if (const auto *Entry = CostTableLookup(LSXCostTable, ISD, LT.second)) -+ return LT.first * Entry->Cost; -+ -+ // Fallback to the default implementation. -+ return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info); -+} -+ -+InstructionCost LoongArchTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, -+ unsigned Index) { -+ assert(Val->isVectorTy() && "This must be a vector type"); -+ -+ Type *ScalarType = Val->getScalarType(); -+ -+ if (Index != -1U) { -+ // Legalize the type. -+ std::pair LT = TLI->getTypeLegalizationCost(DL, Val); -+ -+ // This type is legalized to a scalar type. -+ if (!LT.second.isVector()) -+ return 0; -+ -+ // The type may be split. Normalize the index to the new type. -+ unsigned Width = LT.second.getVectorNumElements(); -+ Index = Index % Width; -+ -+ // The element at index zero is already inside the vector. -+ if (Index == 0) // if (ScalarType->isFloatingPointTy() && Index == 0) -+ return 0; -+ } -+ -+ // Add to the base cost if we know that the extracted element of a vector is -+ // destined to be moved to and used in the integer register file. -+ int RegisterFileMoveCost = 0; -+ if (Opcode == Instruction::ExtractElement && ScalarType->isPointerTy()) -+ RegisterFileMoveCost = 1; -+ -+ return BaseT::getVectorInstrCost(Opcode, Val, Index) + RegisterFileMoveCost; -+} -+ -+unsigned LoongArchTTIImpl::getLoadStoreVecRegBitWidth(unsigned) const { -+ return getRegisterBitWidth(true); -+} -+ -+InstructionCost LoongArchTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, -+ Type *Src, -+ TTI::CastContextHint CCH, -+ TTI::TargetCostKind CostKind, -+ const Instruction *I) { -+ int ISD = TLI->InstructionOpcodeToISD(Opcode); -+ assert(ISD && "Invalid opcode"); -+ -+ static const TypeConversionCostTblEntry LASXConversionTbl[] = { -+ -+ // TODO:The cost requires more granular testing -+ {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 3}, -+ {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 3}, -+ {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 3}, -+ {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 3}, -+ {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 3}, -+ {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 3}, -+ -+ }; -+ -+ EVT SrcTy = TLI->getValueType(DL, Src); -+ EVT DstTy = TLI->getValueType(DL, Dst); -+ -+ if (!SrcTy.isSimple() || !DstTy.isSimple()) -+ return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); -+ -+ if (ST->hasLASX()) { -+ if (const auto *Entry = ConvertCostTableLookup( -+ LASXConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT())) -+ return Entry->Cost; -+ } -+ -+ return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h -new file mode 100644 -index 000000000..3a93fc8ec ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h -@@ -0,0 +1,91 @@ -+//===-- LoongArchTargetTransformInfo.h - LoongArch specific TTI -------------*- -+// C++ -*-===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+// \file -+// This file a TargetTransformInfo::Concept conforming object specific to the -+// LoongArch target machine. It uses the target's detailed information to -+// provide more precise answers to certain TTI queries, while letting the -+// target independent and default TTI implementations handle the rest. -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LoongArch_LoongArchTARGETTRANSFORMINFO_H -+#define LLVM_LIB_TARGET_LoongArch_LoongArchTARGETTRANSFORMINFO_H -+ -+#include "LoongArch.h" -+#include "LoongArchSubtarget.h" -+#include "LoongArchTargetMachine.h" -+#include "llvm/Analysis/TargetTransformInfo.h" -+#include "llvm/CodeGen/BasicTTIImpl.h" -+#include "llvm/CodeGen/TargetLowering.h" -+ -+namespace llvm { -+ -+class LoongArchTTIImpl : public BasicTTIImplBase { -+ typedef BasicTTIImplBase BaseT; -+ typedef TargetTransformInfo TTI; -+ friend BaseT; -+ -+ const LoongArchSubtarget *ST; -+ const LoongArchTargetLowering *TLI; -+ -+ const LoongArchSubtarget *getST() const { return ST; } -+ const LoongArchTargetLowering *getTLI() const { return TLI; } -+ -+public: -+ explicit LoongArchTTIImpl(const LoongArchTargetMachine *TM, const Function &F) -+ : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), -+ TLI(ST->getTargetLowering()) {} -+ -+ bool areInlineCompatible(const Function *Caller, -+ const Function *Callee) const; -+ -+ /// \name Scalar TTI Implementations -+ // /// @{ -+ -+ TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth); -+ -+ /// @} -+ -+ /// \name Vector TTI Implementations -+ /// @{ -+ -+ bool enableInterleavedAccessVectorization() { return true; } -+ -+ unsigned getNumberOfRegisters(bool Vector); -+ -+ unsigned getRegisterBitWidth(bool Vector) const; -+ -+ unsigned getMaxInterleaveFactor(unsigned VF); -+ -+ InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, -+ unsigned Index); -+ -+ InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, -+ TTI::CastContextHint CCH, -+ TTI::TargetCostKind CostKind, -+ const Instruction *I = nullptr); -+ -+ unsigned getLoadStoreVecRegBitWidth(unsigned AS) const; -+ -+ InstructionCost getArithmeticInstrCost( -+ unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, -+ TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, -+ TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, -+ TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, -+ TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, -+ ArrayRef Args = ArrayRef(), -+ const Instruction *CxtI = nullptr); -+ -+ /// @} -+}; -+ -+} // end namespace llvm -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt -index 2e1ca69a3..927fa7d5b 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt -@@ -1,12 +1,15 @@ --add_llvm_component_library(LLVMLoongArchDesc -+ add_llvm_component_library(LLVMLoongArchDesc -+ LoongArchABIInfo.cpp -+ LoongArchAnalyzeImmediate.cpp - LoongArchAsmBackend.cpp -- LoongArchBaseInfo.cpp - LoongArchELFObjectWriter.cpp -+ LoongArchELFStreamer.cpp - LoongArchInstPrinter.cpp - LoongArchMCAsmInfo.cpp -- LoongArchMCTargetDesc.cpp - LoongArchMCCodeEmitter.cpp -- LoongArchMatInt.cpp -+ LoongArchMCExpr.cpp -+ LoongArchMCTargetDesc.cpp -+ LoongArchTargetStreamer.cpp - - LINK_COMPONENTS - MC -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp -new file mode 100644 -index 000000000..18b67961a ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp -@@ -0,0 +1,106 @@ -+//===---- LoongArchABIInfo.cpp - Information about LoongArch ABI's ------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchABIInfo.h" -+#include "LoongArchRegisterInfo.h" -+#include "llvm/ADT/StringRef.h" -+#include "llvm/ADT/StringSwitch.h" -+#include "llvm/MC/MCTargetOptions.h" -+ -+using namespace llvm; -+ -+namespace { -+static const MCPhysReg LP32IntRegs[4] = {LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3}; -+ -+static const MCPhysReg LoongArch64IntRegs[8] = { -+ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64, -+ LoongArch::A4_64, LoongArch::A5_64, LoongArch::A6_64, LoongArch::A7_64}; -+} -+ -+ArrayRef LoongArchABIInfo::GetByValArgRegs() const { -+ if (IsLP32()) -+ return makeArrayRef(LP32IntRegs); -+ if (IsLPX32() || IsLP64()) -+ return makeArrayRef(LoongArch64IntRegs); -+ llvm_unreachable("Unhandled ABI"); -+} -+ -+ArrayRef LoongArchABIInfo::GetVarArgRegs() const { -+ if (IsLP32()) -+ return makeArrayRef(LP32IntRegs); -+ if (IsLPX32() || IsLP64()) -+ return makeArrayRef(LoongArch64IntRegs); -+ llvm_unreachable("Unhandled ABI"); -+} -+ -+LoongArchABIInfo LoongArchABIInfo::computeTargetABI(const Triple &TT, StringRef CPU, -+ const MCTargetOptions &Options) { -+ if (Options.getABIName().startswith("lp32")) -+ return LoongArchABIInfo::LP32(); -+ if (Options.getABIName().startswith("lpx32")) -+ return LoongArchABIInfo::LPX32(); -+ if (Options.getABIName().startswith("lp64")) -+ return LoongArchABIInfo::LP64(); -+ assert(Options.getABIName().empty() && "Unknown ABI option for LoongArch"); -+ -+ if (TT.isLoongArch64()) -+ return LoongArchABIInfo::LP64(); -+ return LoongArchABIInfo::LP32(); -+} -+ -+unsigned LoongArchABIInfo::GetStackPtr() const { -+ return ArePtrs64bit() ? LoongArch::SP_64 : LoongArch::SP; -+} -+ -+unsigned LoongArchABIInfo::GetFramePtr() const { -+ return ArePtrs64bit() ? LoongArch::FP_64 : LoongArch::FP; -+} -+ -+unsigned LoongArchABIInfo::GetBasePtr() const { -+ return ArePtrs64bit() ? LoongArch::S7_64 : LoongArch::S7; -+} -+ -+unsigned LoongArchABIInfo::GetNullPtr() const { -+ return ArePtrs64bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; -+} -+ -+unsigned LoongArchABIInfo::GetZeroReg() const { -+ return AreGprs64bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; -+} -+ -+unsigned LoongArchABIInfo::GetPtrAddOp() const { -+ return ArePtrs64bit() ? LoongArch::ADD_D : LoongArch::ADD_W; -+} -+ -+unsigned LoongArchABIInfo::GetPtrAddiOp() const { -+ return ArePtrs64bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; -+} -+ -+unsigned LoongArchABIInfo::GetPtrSubOp() const { -+ return ArePtrs64bit() ? LoongArch::SUB_D : LoongArch::SUB_W; -+} -+ -+unsigned LoongArchABIInfo::GetPtrAndOp() const { -+ return ArePtrs64bit() ? LoongArch::AND : LoongArch::AND32; -+} -+ -+unsigned LoongArchABIInfo::GetGPRMoveOp() const { -+ return ArePtrs64bit() ? LoongArch::OR : LoongArch::OR32; -+} -+ -+unsigned LoongArchABIInfo::GetEhDataReg(unsigned I) const { -+ static const unsigned EhDataReg[] = { -+ LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3 -+ }; -+ static const unsigned EhDataReg64[] = { -+ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64 -+ }; -+ -+ return IsLP64() ? EhDataReg64[I] : EhDataReg[I]; -+} -+ -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h -new file mode 100644 -index 000000000..334ee80ea ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h -@@ -0,0 +1,76 @@ -+//===---- LoongArchABIInfo.h - Information about LoongArch ABI's --------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHABIINFO_H -+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHABIINFO_H -+ -+#include "llvm/ADT/Triple.h" -+#include "llvm/IR/CallingConv.h" -+#include "llvm/MC/MCRegisterInfo.h" -+ -+namespace llvm { -+ -+template class ArrayRef; -+class MCTargetOptions; -+class StringRef; -+class TargetRegisterClass; -+ -+class LoongArchABIInfo { -+public: -+ enum class ABI { Unknown, LP32, LPX32, LP64 }; -+ -+protected: -+ ABI ThisABI; -+ -+public: -+ LoongArchABIInfo(ABI ThisABI) : ThisABI(ThisABI) {} -+ -+ static LoongArchABIInfo Unknown() { return LoongArchABIInfo(ABI::Unknown); } -+ static LoongArchABIInfo LP32() { return LoongArchABIInfo(ABI::LP32); } -+ static LoongArchABIInfo LPX32() { return LoongArchABIInfo(ABI::LPX32); } -+ static LoongArchABIInfo LP64() { return LoongArchABIInfo(ABI::LP64); } -+ static LoongArchABIInfo computeTargetABI(const Triple &TT, StringRef CPU, -+ const MCTargetOptions &Options); -+ -+ bool IsKnown() const { return ThisABI != ABI::Unknown; } -+ bool IsLP32() const { return ThisABI == ABI::LP32; } -+ bool IsLPX32() const { return ThisABI == ABI::LPX32; } -+ bool IsLP64() const { return ThisABI == ABI::LP64; } -+ ABI GetEnumValue() const { return ThisABI; } -+ -+ /// The registers to use for byval arguments. -+ ArrayRef GetByValArgRegs() const; -+ -+ /// The registers to use for the variable argument list. -+ ArrayRef GetVarArgRegs() const; -+ -+ /// Ordering of ABI's -+ /// LoongArchGenSubtargetInfo.inc will use this to resolve conflicts when given -+ /// multiple ABI options. -+ bool operator<(const LoongArchABIInfo Other) const { -+ return ThisABI < Other.GetEnumValue(); -+ } -+ -+ unsigned GetStackPtr() const; -+ unsigned GetFramePtr() const; -+ unsigned GetBasePtr() const; -+ unsigned GetNullPtr() const; -+ unsigned GetZeroReg() const; -+ unsigned GetPtrAddOp() const; -+ unsigned GetPtrAddiOp() const; -+ unsigned GetPtrSubOp() const; -+ unsigned GetPtrAndOp() const; -+ unsigned GetGPRMoveOp() const; -+ inline bool ArePtrs64bit() const { return IsLP64(); } -+ inline bool AreGprs64bit() const { return IsLPX32() || IsLP64(); } -+ -+ unsigned GetEhDataReg(unsigned I) const; -+}; -+} -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp -new file mode 100644 -index 000000000..96e43b2d3 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp -@@ -0,0 +1,64 @@ -+//===- LoongArchAnalyzeImmediate.cpp - Analyze Immediates -----------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchAnalyzeImmediate.h" -+#include "LoongArch.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/Support/MathExtras.h" -+ -+using namespace llvm; -+ -+LoongArchAnalyzeImmediate::InstSeq -+LoongArchAnalyzeImmediate::generateInstSeq(int64_t Val, bool Is64Bit) { -+ // Val: -+ // | hi32 | lo32 | -+ // +------------+------------------+------------------+-----------+ -+ // | Bits_52_63 | Bits_32_51 | Bits_12_31 | Bits_0_11 | -+ // +------------+------------------+------------------+-----------+ -+ // 63 52 51 32 31 12 11 0 -+ unsigned ORIOp = Is64Bit ? LoongArch::ORI : LoongArch::ORI32; -+ unsigned LU12IOp = Is64Bit ? LoongArch::LU12I_W : LoongArch::LU12I_W32; -+ unsigned ADDIOp = Is64Bit ? LoongArch::ADDI_W64 : LoongArch::ADDI_W; -+ unsigned LU32IOp = LoongArch::LU32I_D_R2; -+ unsigned LU52IOp = LoongArch::LU52I_D; -+ -+ int64_t Bits_52_63 = Val >> 52 & 0xFFF; -+ int64_t Bits_32_51 = Val >> 32 & 0xFFFFF; -+ int64_t Bits_12_31 = Val >> 12 & 0xFFFFF; -+ int64_t Bits_0_11 = Val & 0xFFF; -+ -+ InstSeq Insts; -+ -+ if (isInt<12>(Val) && Is64Bit) { -+ Insts.push_back(Inst(LoongArch::ADDI_D, SignExtend64<12>(Bits_0_11))); -+ return Insts; -+ } -+ -+ if (Bits_52_63 != 0 && SignExtend64<52>(Val) == 0) { -+ Insts.push_back(Inst(LU52IOp, SignExtend64<12>(Bits_52_63))); -+ return Insts; -+ } -+ -+ if (Bits_12_31 == 0) -+ Insts.push_back(Inst(ORIOp, Bits_0_11)); -+ else if (SignExtend32<1>(Bits_0_11 >> 11) == SignExtend32<20>(Bits_12_31)) -+ Insts.push_back(Inst(ADDIOp, SignExtend64<12>(Bits_0_11))); -+ else { -+ Insts.push_back(Inst(LU12IOp, SignExtend64<20>(Bits_12_31))); -+ if (Bits_0_11 != 0) -+ Insts.push_back(Inst(ORIOp, Bits_0_11)); -+ } -+ -+ if (SignExtend32<1>(Bits_12_31 >> 19) != SignExtend32<20>(Bits_32_51)) -+ Insts.push_back(Inst(LU32IOp, SignExtend64<20>(Bits_32_51))); -+ -+ if (SignExtend32<1>(Bits_32_51 >> 19) != SignExtend32<12>(Bits_52_63)) -+ Insts.push_back(Inst(LU52IOp, SignExtend64<12>(Bits_52_63))); -+ -+ return Insts; -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h -similarity index 62% -rename from src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h -rename to src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h -index be1b42589..3ff00f254 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h -@@ -1,4 +1,4 @@ --//===- LoongArchMatInt.h - Immediate materialisation - --------*- C++ -*--===// -+//===- LoongArchAnalyzeImmediate.h - Analyze Immediates --------*- C++ -*--===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,14 +6,13 @@ - // - //===----------------------------------------------------------------------===// - --#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_MATINT_H --#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_MATINT_H -+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H -+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H - - #include "llvm/ADT/SmallVector.h" --#include - - namespace llvm { --namespace LoongArchMatInt { -+namespace LoongArchAnalyzeImmediate { - struct Inst { - unsigned Opc; - int64_t Imm; -@@ -23,8 +22,8 @@ using InstSeq = SmallVector; - - // Helper to generate an instruction sequence that will materialise the given - // immediate value into a register. --InstSeq generateInstSeq(int64_t Val); --} // end namespace LoongArchMatInt -+InstSeq generateInstSeq(int64_t Val, bool Is64Bit); -+} // end namespace LoongArchAnalyzeImmediate - } // end namespace llvm - --#endif -+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp -index 94a068897..b9ba9e536 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchAsmBackend.cpp - LoongArch Assembler Backend -*- C++ -*---===// -+//===-- LoongArchAsmBackend.cpp - LoongArch Asm Backend ----------------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -9,41 +9,158 @@ - // This file implements the LoongArchAsmBackend class. - // - //===----------------------------------------------------------------------===// -+// - --#include "LoongArchAsmBackend.h" --#include "llvm/MC/MCAsmLayout.h" -+#include "MCTargetDesc/LoongArchAsmBackend.h" -+#include "MCTargetDesc/LoongArchABIInfo.h" -+#include "MCTargetDesc/LoongArchFixupKinds.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/MC/MCAsmBackend.h" - #include "llvm/MC/MCAssembler.h" - #include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCDirectives.h" - #include "llvm/MC/MCELFObjectWriter.h" --#include "llvm/Support/Endian.h" -+#include "llvm/MC/MCFixupKindInfo.h" -+#include "llvm/MC/MCObjectWriter.h" -+#include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/MC/MCTargetOptions.h" -+#include "llvm/MC/MCValue.h" - #include "llvm/Support/EndianStream.h" -- --#define DEBUG_TYPE "loongarch-asmbackend" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/Format.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Support/raw_ostream.h" - - using namespace llvm; - --void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, -- const MCFixup &Fixup, -- const MCValue &Target, -- MutableArrayRef Data, uint64_t Value, -- bool IsResolved, -- const MCSubtargetInfo *STI) const { -- // TODO: Apply the Value for given Fixup into the provided data fragment. -- return; -+std::unique_ptr -+LoongArchAsmBackend::createObjectTargetWriter() const { -+ return createLoongArchELFObjectWriter(TheTriple, IsLPX32); - } - --bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, -- const MCFixup &Fixup, -- const MCValue &Target) { -- // TODO: Determine which relocation require special processing at linking -- // time. -- return false; -+/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided -+/// data fragment, at the offset specified by the fixup and following the -+/// fixup kind as appropriate. -+void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, -+ const MCValue &Target, -+ MutableArrayRef Data, uint64_t Value, -+ bool IsResolved, -+ const MCSubtargetInfo *STI) const { -+ MCFixupKind Kind = Fixup.getKind(); -+ if (Kind > FirstTargetFixupKind) -+ return; -+ -+ if (!Value) -+ return; // Doesn't change encoding. -+ -+ // Where do we start in the object -+ unsigned Offset = Fixup.getOffset(); -+ // Number of bytes we need to fixup -+ unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; -+ -+ -+ // Grab current value, if any, from bits. -+ uint64_t CurVal = 0; -+ -+ for (unsigned i = 0; i != NumBytes; ++i) -+ CurVal |= (uint64_t)((uint8_t)Data[Offset + i]) << (i*8); -+ -+ uint64_t Mask = ((uint64_t)(-1) >> -+ (64 - getFixupKindInfo(Kind).TargetSize)); -+ CurVal |= Value & Mask; -+ -+ // Write out the fixed up bytes back to the code/data bits. -+ for (unsigned i = 0; i != NumBytes; ++i) -+ Data[Offset + i] = (uint8_t)((CurVal >> (i*8)) & 0xff); - } - -+Optional LoongArchAsmBackend::getFixupKind(StringRef Name) const { -+ return StringSwitch>(Name) -+ .Case("R_LARCH_NONE", (MCFixupKind)LoongArch::fixup_LARCH_NONE) -+ .Case("R_LARCH_32", FK_Data_4) -+ .Case("R_LARCH_64", FK_Data_8) -+ .Default(MCAsmBackend::getFixupKind(Name)); -+} -+ -+const MCFixupKindInfo &LoongArchAsmBackend:: -+getFixupKindInfo(MCFixupKind Kind) const { -+ const static MCFixupKindInfo Infos[] = { -+ // This table *must* be in same the order of fixup_* kinds in -+ // LoongArchFixupKinds.h. -+ // -+ // name offset bits flags -+ { "fixup_LARCH_NONE", 0, 0, 0 }, -+ { "fixup_LARCH_SOP_PUSH_ABSOLUTE", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_PCREL", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_GPREL", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_TLS_TPREL", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_TLS_GOT", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_TLS_GD", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_PLT_PCREL", 0, 0, 0}, -+ { "fixup_LARCH_32", 0, 0, 0}, -+ { "fixup_LARCH_64", 0, 0, 0}, -+ { "fixup_LARCH_RELATIVE", 0, 0, 0}, -+ { "fixup_LARCH_COPY", 0, 0, 0}, -+ { "fixup_LARCH_JUMP_SLOT", 0, 0, 0}, -+ { "fixup_LARCH_TLS_DTPMOD32", 0, 0, 0}, -+ { "fixup_LARCH_TLS_DTPMOD64", 0, 0, 0}, -+ { "fixup_LARCH_TLS_DTPREL32", 0, 0, 0}, -+ { "fixup_LARCH_TLS_DTPREL64", 0, 0, 0}, -+ { "fixup_LARCH_TLS_TPREL32", 0, 0, 0}, -+ { "fixup_LARCH_TLS_TPREL64", 0, 0, 0}, -+ { "fixup_LARCH_IRELATIVE", 0, 0, 0}, -+ { "fixup_LARCH_MARK_LA", 0, 0, 0}, -+ { "fixup_LARCH_MARK_PCREL", 0, 0, 0}, -+ { "fixup_LARCH_SOP_PUSH_DUP", 0, 0, 0}, -+ { "fixup_LARCH_SOP_ASSERT", 0, 0, 0}, -+ { "fixup_LARCH_SOP_NOT", 0, 0, 0}, -+ { "fixup_LARCH_SOP_SUB", 0, 0, 0}, -+ { "fixup_LARCH_SOP_SL", 0, 0, 0}, -+ { "fixup_LARCH_SOP_SR", 0, 0, 0}, -+ { "fixup_LARCH_SOP_ADD", 0, 0, 0}, -+ { "fixup_LARCH_SOP_AND", 0, 0, 0}, -+ { "fixup_LARCH_SOP_IF_ELSE", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_10_5", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_U_10_12", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_10_12", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_10_16", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_10_16_S2", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_5_20", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2", 0, 0, 0}, -+ { "fixup_LARCH_SOP_POP_32_U", 0, 0, 0}, -+ { "fixup_LARCH_ADD8", 0, 0, 0}, -+ { "fixup_LARCH_ADD16", 0, 0, 0}, -+ { "fixup_LARCH_ADD24", 0, 0, 0}, -+ { "fixup_LARCH_ADD32", 0, 0, 0}, -+ { "fixup_LARCH_ADD64", 0, 0, 0}, -+ { "fixup_LARCH_SUB8", 0, 0, 0}, -+ { "fixup_LARCH_SUB16", 0, 0, 0}, -+ { "fixup_LARCH_SUB24", 0, 0, 0}, -+ { "fixup_LARCH_SUB32", 0, 0, 0}, -+ { "fixup_LARCH_SUB64", 0, 0, 0}, -+ }; -+ -+ if (Kind < FirstTargetFixupKind) -+ return MCAsmBackend::getFixupKindInfo(Kind); -+ -+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && -+ "Invalid kind!"); -+ -+ return Infos[Kind - FirstTargetFixupKind]; -+} -+ -+/// WriteNopData - Write an (optimal) nop sequence of Count bytes -+/// to the given output. If the target cannot generate such a sequence, -+/// it should return an error. -+/// -+/// \return - True on success. - bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, - const MCSubtargetInfo *STI) const { -- // Check for byte count not multiple of instruction word size -- if (Count % 4 != 0) -+ // Check for a less than instruction size number of bytes -+ if ((Count % 4) != 0) - return false; - - // The nop on LoongArch is andi r0, r0, 0. -@@ -53,16 +170,45 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, - return true; - } - --std::unique_ptr --LoongArchAsmBackend::createObjectTargetWriter() const { -- return createLoongArchELFObjectWriter(OSABI, Is64Bit); -+bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, -+ const MCFixup &Fixup, -+ const MCValue &Target) { -+ const unsigned FixupKind = Fixup.getKind(); -+ switch (FixupKind) { -+ default: -+ return false; -+ // All these relocations require special processing -+ // at linking time. Delegate this work to a linker. -+ case LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL: -+ case LoongArch::fixup_LARCH_SOP_PUSH_PCREL: -+ case LoongArch::fixup_LARCH_SOP_PUSH_GPREL: -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD: -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT: -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL: -+ case LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE: -+ case LoongArch::fixup_LARCH_SOP_IF_ELSE: -+ case LoongArch::fixup_LARCH_SOP_ADD: -+ case LoongArch::fixup_LARCH_SOP_SUB: -+ case LoongArch::fixup_LARCH_SOP_AND: -+ case LoongArch::fixup_LARCH_SOP_SL: -+ case LoongArch::fixup_LARCH_SOP_SR: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_5: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_5_20: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_12: -+ case LoongArch::fixup_LARCH_SOP_POP_32_U_10_12: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ return true; -+ } - } - - MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T, - const MCSubtargetInfo &STI, - const MCRegisterInfo &MRI, - const MCTargetOptions &Options) { -- const Triple &TT = STI.getTargetTriple(); -- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); -- return new LoongArchAsmBackend(STI, OSABI, TT.isArch64Bit()); -+ LoongArchABIInfo ABI = LoongArchABIInfo::computeTargetABI( -+ STI.getTargetTriple(), STI.getCPU(), Options); -+ return new LoongArchAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), -+ ABI.IsLPX32()); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h -index a5f0b816c..45ae6af44 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h -@@ -1,4 +1,4 @@ --//===-- LoongArchAsmBackend.h - LoongArch Assembler Backend ---*- C++ -*---===// -+//===-- LoongArchAsmBackend.h - LoongArch Asm Backend ------------------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -9,55 +9,83 @@ - // This file defines the LoongArchAsmBackend class. - // - //===----------------------------------------------------------------------===// -+// - - #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H - #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H - --#include "MCTargetDesc/LoongArchBaseInfo.h" --#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "MCTargetDesc/LoongArchFixupKinds.h" -+#include "llvm/ADT/Triple.h" - #include "llvm/MC/MCAsmBackend.h" --#include "llvm/MC/MCFixupKindInfo.h" --#include "llvm/MC/MCSubtargetInfo.h" - - namespace llvm { - -+class MCAssembler; -+struct MCFixupKindInfo; -+class MCObjectWriter; -+class MCRegisterInfo; -+class MCSymbolELF; -+class Target; -+ - class LoongArchAsmBackend : public MCAsmBackend { -- uint8_t OSABI; -- bool Is64Bit; -+ Triple TheTriple; -+ bool IsLPX32; - - public: -- LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit) -- : MCAsmBackend(support::little), OSABI(OSABI), Is64Bit(Is64Bit) {} -- ~LoongArchAsmBackend() override {} -+ LoongArchAsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TT, -+ StringRef CPU, bool LPX32) -+ : MCAsmBackend(support::little), -+ TheTriple(TT), IsLPX32(LPX32) { -+ assert(TT.isLittleEndian()); -+ } -+ -+ std::unique_ptr -+ createObjectTargetWriter() const override; - - void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved, - const MCSubtargetInfo *STI) const override; - -- bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, -- const MCValue &Target) override; -+ Optional getFixupKind(StringRef Name) const override; -+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; -+ -+ unsigned getNumFixupKinds() const override { -+ return LoongArch::NumTargetFixupKinds; -+ } -+ -+ /// @name Target Relaxation Interfaces -+ /// @{ - -- bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, -- const MCRelaxableFragment *DF, -- const MCAsmLayout &Layout) const override { -+ /// MayNeedRelaxation - Check whether the given instruction may need -+ /// relaxation. -+ /// -+ /// \param Inst - The instruction to test. -+ bool mayNeedRelaxation(const MCInst &Inst, -+ const MCSubtargetInfo &STI) const override { - return false; - } - -- unsigned getNumFixupKinds() const override { -- // FIXME: Implement this when we define fixup kind -- return 0; -+ /// fixupNeedsRelaxation - Target specific predicate for whether a given -+ /// fixup requires the associated instruction to be relaxed. -+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, -+ const MCRelaxableFragment *DF, -+ const MCAsmLayout &Layout) const override { -+ // FIXME. -+ llvm_unreachable("RelaxInstruction() unimplemented"); -+ return false; - } - -- void relaxInstruction(MCInst &Inst, -- const MCSubtargetInfo &STI) const override {} -+ /// @} - - bool writeNopData(raw_ostream &OS, uint64_t Count, - const MCSubtargetInfo *STI) const override; - -- std::unique_ptr -- createObjectTargetWriter() const override; --}; --} // end namespace llvm -+ bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, -+ const MCValue &Target) override; -+ -+}; // class LoongArchAsmBackend -+ -+} // namespace - --#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp -deleted file mode 100644 -index de2ba2833..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp -+++ /dev/null -@@ -1,40 +0,0 @@ --//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- C++ -*-// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// --// --// This file implements helper functions for the LoongArch target useful for the --// compiler back-end and the MC libraries. --// --//===----------------------------------------------------------------------===// -- --#include "LoongArchBaseInfo.h" --#include "llvm/ADT/ArrayRef.h" --#include "llvm/ADT/Triple.h" --#include "llvm/MC/MCSubtargetInfo.h" -- --namespace llvm { -- --namespace LoongArchABI { -- --ABI getTargetABI(StringRef ABIName) { -- auto TargetABI = StringSwitch(ABIName) -- .Case("ilp32s", ABI_ILP32S) -- .Case("ilp32f", ABI_ILP32F) -- .Case("ilp32d", ABI_ILP32D) -- .Case("lp64s", ABI_LP64S) -- .Case("lp64f", ABI_LP64F) -- .Case("lp64d", ABI_LP64D) -- .Default(ABI_Unknown); -- return TargetABI; --} -- --// FIXME: other register? --MCRegister getBPReg() { return LoongArch::R31; } -- --} // end namespace LoongArchABI -- --} // end namespace llvm -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h -index fee247a0c..707333c18 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h -@@ -1,4 +1,4 @@ --//=- LoongArchBaseInfo.h - Top level definitions for LoongArch MC -*- C++ -*-=// -+//===-- LoongArchBaseInfo.h - Top level definitions for LoongArch MC ------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,39 +6,123 @@ - // - //===----------------------------------------------------------------------===// - // --// This file contains small standalone enum definitions and helper function --// definitions for the LoongArch target useful for the compiler back-end and the --// MC libraries. -+// This file contains small standalone helper functions and enum definitions for -+// the LoongArch target useful for the compiler back-end and the MC libraries. - // - //===----------------------------------------------------------------------===// - #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H - #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H - --#include "MCTargetDesc/LoongArchMCTargetDesc.h" --#include "llvm/ADT/StringRef.h" --#include "llvm/ADT/StringSwitch.h" --#include "llvm/MC/MCInstrDesc.h" --#include "llvm/MC/SubtargetFeature.h" -+#include "LoongArchFixupKinds.h" -+#include "LoongArchMCTargetDesc.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/Support/DataTypes.h" -+#include "llvm/Support/ErrorHandling.h" - - namespace llvm { - --namespace LoongArchABI { --enum ABI { -- ABI_ILP32S, -- ABI_ILP32F, -- ABI_ILP32D, -- ABI_LP64S, -- ABI_LP64F, -- ABI_LP64D, -- ABI_Unknown --}; -+/// LoongArchII - This namespace holds all of the target specific flags that -+/// instruction info tracks. -+/// -+namespace LoongArchII { -+ /// Target Operand Flag enum. -+ enum TOF { -+ //===------------------------------------------------------------------===// -+ // LoongArch Specific MachineOperand flags. - --ABI getTargetABI(StringRef ABIName); -+ MO_NO_FLAG, - --// Returns the register used to hold the stack pointer after realignment. --MCRegister getBPReg(); --} // end namespace LoongArchABI -+ /// MO_ABS_XXX - Represents the hi or low part of an absolute symbol -+ /// address. -+ MO_ABS_HI, -+ MO_ABS_LO, -+ MO_ABS_HIGHER, -+ MO_ABS_HIGHEST, - --} // end namespace llvm -+ /// MO_PCREL_XXX - Represents the hi or low part of an pc relative symbol -+ /// address. -+ MO_PCREL_HI, -+ MO_PCREL_LO, -+ // with tmp reg -+ MO_PCREL_RRHI, -+ MO_PCREL_RRLO, -+ MO_PCREL_RRHIGHER, -+ MO_PCREL_RRHIGHEST, - --#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H -+ // LArch Tls gd and ld -+ MO_TLSGD_HI, -+ MO_TLSGD_LO, -+ // with tmp reg -+ MO_TLSGD_RRHI, -+ MO_TLSGD_RRLO, -+ MO_TLSGD_RRHIGHER, -+ MO_TLSGD_RRHIGHEST, -+ -+ // LArch thread tprel (ie/le) -+ // LArch Tls ie -+ MO_TLSIE_HI, -+ MO_TLSIE_LO, -+ // with tmp reg -+ MO_TLSIE_RRHI, -+ MO_TLSIE_RRLO, -+ MO_TLSIE_RRHIGHER, -+ MO_TLSIE_RRHIGHEST, -+ // LArch Tls le -+ MO_TLSLE_HI, -+ MO_TLSLE_LO, -+ MO_TLSLE_HIGHER, -+ MO_TLSLE_HIGHEST, -+ -+ // Loongarch got -+ MO_GOT_HI, -+ MO_GOT_LO, -+ // with tmp reg -+ MO_GOT_RRHI, -+ MO_GOT_RRLO, -+ MO_GOT_RRHIGHER, -+ MO_GOT_RRHIGHEST, -+ -+ MO_CALL_HI, -+ MO_CALL_LO, -+ }; -+ -+ enum { -+ //===------------------------------------------------------------------===// -+ // Instruction encodings. These are the standard/most common forms for -+ // LoongArch instructions. -+ // -+ -+ // Pseudo - This represents an instruction that is a pseudo instruction -+ // or one that has not been implemented yet. It is illegal to code generate -+ // it, but tolerated for intermediate implementation stages. -+ Pseudo = 0, -+ -+ /// FrmR - This form is for instructions of the format R. -+ FrmR = 1, -+ /// FrmI - This form is for instructions of the format I. -+ FrmI = 2, -+ /// FrmJ - This form is for instructions of the format J. -+ FrmJ = 3, -+ /// FrmFR - This form is for instructions of the format FR. -+ FrmFR = 4, -+ /// FrmFI - This form is for instructions of the format FI. -+ FrmFI = 5, -+ /// FrmOther - This form is for instructions that have no specific format. -+ FrmOther = 6, -+ -+ FormMask = 15, -+ /// IsCTI - Instruction is a Control Transfer Instruction. -+ IsCTI = 1 << 4, -+ /// HasForbiddenSlot - Instruction has a forbidden slot. -+ HasForbiddenSlot = 1 << 5, -+ /// IsPCRelativeLoad - A Load instruction with implicit source register -+ /// ($pc) with explicit offset and destination register -+ IsPCRelativeLoad = 1 << 6, -+ /// HasFCCRegOperand - Instruction uses an $fcc register. -+ HasFCCRegOperand = 1 << 7 -+ -+ }; -+} -+} -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp -index 1850b0d8a..e00b9af9d 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer ---*- C++ -*---===// -+//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer -------------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -6,59 +6,181 @@ - // - //===----------------------------------------------------------------------===// - -+#include "MCTargetDesc/LoongArchFixupKinds.h" - #include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/ADT/STLExtras.h" -+#include "llvm/BinaryFormat/ELF.h" - #include "llvm/MC/MCContext.h" - #include "llvm/MC/MCELFObjectWriter.h" - #include "llvm/MC/MCFixup.h" - #include "llvm/MC/MCObjectWriter.h" -+#include "llvm/MC/MCSymbolELF.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/Compiler.h" -+#include "llvm/Support/Debug.h" - #include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Support/raw_ostream.h" -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DEBUG_TYPE "loongarch-elf-object-writer" - - using namespace llvm; - - namespace { -+ - class LoongArchELFObjectWriter : public MCELFObjectTargetWriter { - public: -- LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); -+ LoongArchELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64); - -- ~LoongArchELFObjectWriter() override; -+ ~LoongArchELFObjectWriter() override = default; - -- // Return true if the given relocation must be with a symbol rather than -- // section plus offset. -+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target, -+ const MCFixup &Fixup, bool IsPCRel) const override; - bool needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const override { - return true; - } -- --protected: -- unsigned getRelocType(MCContext &Ctx, const MCValue &Target, -- const MCFixup &Fixup, bool IsPCRel) const override; - }; --} // end namespace - --LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) -- : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH, -- /*HasRelocationAddend*/ true) {} -+} // end anonymous namespace - --LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {} -+LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, -+ bool HasRelocationAddend, bool Is64) -+ : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_LOONGARCH, HasRelocationAddend) {} - - unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx, -- const MCValue &Target, -- const MCFixup &Fixup, -- bool IsPCRel) const { -- // Determine the type of the relocation -- unsigned Kind = Fixup.getTargetKind(); -- -- if (Kind >= FirstLiteralRelocationKind) -- return Kind - FirstLiteralRelocationKind; -+ const MCValue &Target, -+ const MCFixup &Fixup, -+ bool IsPCRel) const { -+ // Determine the type of the relocation. -+ ///XXX:Reloc -+ unsigned Kind = (unsigned)Fixup.getKind(); - - switch (Kind) { -- // TODO: Implement this when we defined fixup kind. -- default: -- return ELF::R_LARCH_NONE; -+ default: -+ return ELF::R_LARCH_NONE; -+ //llvm_unreachable("invalid fixup kind!"); -+ case FK_Data_4: -+ case LoongArch::fixup_LARCH_32: -+ return ELF::R_LARCH_32; -+ case FK_GPRel_4: -+ case FK_Data_8: -+ case LoongArch::fixup_LARCH_64: -+ return ELF::R_LARCH_64; -+ case LoongArch::fixup_LARCH_NONE: -+ return ELF::R_LARCH_NONE; -+ case LoongArch::fixup_LARCH_RELATIVE: -+ return ELF::R_LARCH_RELATIVE; -+ case LoongArch::fixup_LARCH_COPY: -+ return ELF::R_LARCH_COPY; -+ case LoongArch::fixup_LARCH_JUMP_SLOT: -+ return ELF::R_LARCH_JUMP_SLOT; -+ case LoongArch::fixup_LARCH_TLS_DTPMOD32: -+ return ELF::R_LARCH_TLS_DTPMOD32; -+ case LoongArch::fixup_LARCH_TLS_DTPMOD64: -+ return ELF::R_LARCH_TLS_DTPMOD64; -+ case LoongArch::fixup_LARCH_TLS_DTPREL32: -+ return ELF::R_LARCH_TLS_DTPREL32; -+ case LoongArch::fixup_LARCH_TLS_DTPREL64: -+ return ELF::R_LARCH_TLS_DTPREL64; -+ case LoongArch::fixup_LARCH_TLS_TPREL32: -+ return ELF::R_LARCH_TLS_TPREL32; -+ case LoongArch::fixup_LARCH_TLS_TPREL64: -+ return ELF::R_LARCH_TLS_TPREL64; -+ case LoongArch::fixup_LARCH_IRELATIVE: -+ return ELF::R_LARCH_IRELATIVE; -+ case LoongArch::fixup_LARCH_MARK_LA: -+ return ELF::R_LARCH_MARK_LA; -+ case LoongArch::fixup_LARCH_MARK_PCREL: -+ return ELF::R_LARCH_MARK_PCREL; -+ case LoongArch::fixup_LARCH_SOP_PUSH_PCREL: -+ return ELF::R_LARCH_SOP_PUSH_PCREL; -+ case LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE: -+ return ELF::R_LARCH_SOP_PUSH_ABSOLUTE; -+ case LoongArch::fixup_LARCH_SOP_PUSH_DUP: -+ return ELF::R_LARCH_SOP_PUSH_DUP; -+ case LoongArch::fixup_LARCH_SOP_PUSH_GPREL: -+ return ELF::R_LARCH_SOP_PUSH_GPREL; -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL: -+ return ELF::R_LARCH_SOP_PUSH_TLS_TPREL; -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT: -+ return ELF::R_LARCH_SOP_PUSH_TLS_GOT; -+ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD: -+ return ELF::R_LARCH_SOP_PUSH_TLS_GD; -+ case LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL: -+ return ELF::R_LARCH_SOP_PUSH_PLT_PCREL; -+ case LoongArch::fixup_LARCH_SOP_ASSERT: -+ return ELF::R_LARCH_SOP_ASSERT; -+ case LoongArch::fixup_LARCH_SOP_NOT: -+ return ELF::R_LARCH_SOP_NOT; -+ case LoongArch::fixup_LARCH_SOP_SUB: -+ return ELF::R_LARCH_SOP_SUB; -+ case LoongArch::fixup_LARCH_SOP_SL: -+ return ELF::R_LARCH_SOP_SL; -+ case LoongArch::fixup_LARCH_SOP_SR: -+ return ELF::R_LARCH_SOP_SR; -+ case LoongArch::fixup_LARCH_SOP_ADD: -+ return ELF::R_LARCH_SOP_ADD; -+ case LoongArch::fixup_LARCH_SOP_AND: -+ return ELF::R_LARCH_SOP_AND; -+ case LoongArch::fixup_LARCH_SOP_IF_ELSE: -+ return ELF::R_LARCH_SOP_IF_ELSE; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_5: -+ return ELF::R_LARCH_SOP_POP_32_S_10_5; -+ case LoongArch::fixup_LARCH_SOP_POP_32_U_10_12: -+ return ELF::R_LARCH_SOP_POP_32_U_10_12; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_12: -+ return ELF::R_LARCH_SOP_POP_32_S_10_12; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16: -+ return ELF::R_LARCH_SOP_POP_32_S_10_16; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2: -+ return ELF::R_LARCH_SOP_POP_32_S_10_16_S2; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_5_20: -+ return ELF::R_LARCH_SOP_POP_32_S_5_20; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ return ELF::R_LARCH_SOP_POP_32_S_0_5_10_16_S2; -+ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ return ELF::R_LARCH_SOP_POP_32_S_0_10_10_16_S2; -+ case LoongArch::fixup_LARCH_SOP_POP_32_U: -+ return ELF::R_LARCH_SOP_POP_32_U; -+ case LoongArch::fixup_LARCH_ADD8: -+ return ELF::R_LARCH_ADD8; -+ case LoongArch::fixup_LARCH_ADD16: -+ return ELF::R_LARCH_ADD16; -+ case LoongArch::fixup_LARCH_ADD24: -+ return ELF::R_LARCH_ADD24; -+ case LoongArch::fixup_LARCH_ADD32: -+ return ELF::R_LARCH_ADD32; -+ case LoongArch::fixup_LARCH_ADD64: -+ return ELF::R_LARCH_ADD64; -+ case LoongArch::fixup_LARCH_SUB8: -+ return ELF::R_LARCH_SUB8; -+ case LoongArch::fixup_LARCH_SUB16: -+ return ELF::R_LARCH_SUB16; -+ case LoongArch::fixup_LARCH_SUB24: -+ return ELF::R_LARCH_SUB24; -+ case LoongArch::fixup_LARCH_SUB32: -+ return ELF::R_LARCH_SUB32; -+ case LoongArch::fixup_LARCH_SUB64: -+ return ELF::R_LARCH_SUB64; -+ case LoongArch::fixup_LARCH_GNU_VTINHERIT: -+ return ELF::R_LARCH_GNU_VTINHERIT; -+ case LoongArch::fixup_LARCH_GNU_VTENTRY: -+ return ELF::R_LARCH_GNU_VTENTRY; - } - } - - std::unique_ptr --llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { -- return std::make_unique(OSABI, Is64Bit); -+llvm::createLoongArchELFObjectWriter(const Triple &TT, bool IsLPX32) { -+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); -+ bool IsLP64 = TT.isArch64Bit() && !IsLPX32; -+ bool HasRelocationAddend = TT.isArch64Bit(); -+ return std::make_unique(OSABI, HasRelocationAddend, -+ IsLP64); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp -new file mode 100644 -index 000000000..a74fee3f8 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp -@@ -0,0 +1,138 @@ -+//===-------- LoongArchELFStreamer.cpp - ELF Object Output ---------------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchELFStreamer.h" -+#include "LoongArchFixupKinds.h" -+#include "LoongArchTargetStreamer.h" -+#include "llvm/BinaryFormat/ELF.h" -+#include "llvm/MC/MCAsmBackend.h" -+#include "llvm/MC/MCAssembler.h" -+#include "llvm/MC/MCCodeEmitter.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCDwarf.h" -+#include "llvm/MC/MCInst.h" -+#include "llvm/MC/MCObjectWriter.h" -+#include "llvm/MC/MCSymbolELF.h" -+#include "llvm/MC/MCValue.h" -+#include "llvm/Support/Casting.h" -+ -+using namespace llvm; -+ -+static std::pair getRelocPairForSize(unsigned Size) { -+ switch (Size) { -+ default: -+ llvm_unreachable("unsupported fixup size"); -+ case 1: -+ return std::make_pair(LoongArch::fixup_LARCH_ADD8, -+ LoongArch::fixup_LARCH_SUB8); -+ case 2: -+ return std::make_pair(LoongArch::fixup_LARCH_ADD16, -+ LoongArch::fixup_LARCH_SUB16); -+ case 4: -+ return std::make_pair(LoongArch::fixup_LARCH_ADD32, -+ LoongArch::fixup_LARCH_SUB32); -+ case 8: -+ return std::make_pair(LoongArch::fixup_LARCH_ADD64, -+ LoongArch::fixup_LARCH_SUB64); -+ } -+} -+ -+static bool requiresFixups(MCContext &C, const MCExpr *Value, -+ const MCExpr *&LHS, const MCExpr *&RHS, -+ LoongArchELFStreamer *MCS) { -+ const auto *MBE = dyn_cast(Value); -+ if (MBE == nullptr) -+ return false; -+ -+ MCValue E; -+ if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) -+ return false; -+ if (E.getSymA() == nullptr || E.getSymB() == nullptr) -+ return false; -+ -+ const auto &A = E.getSymA()->getSymbol(); -+ const auto &B = E.getSymB()->getSymbol(); -+ -+ if (A.getName().empty() && B.getName().empty()) -+ return false; -+ -+ if (!A.isInSection() && !B.isInSection() && -+ !A.getName().empty() && !B.getName().empty()) -+ return false; -+ -+ LHS = -+ MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), -+ MCConstantExpr::create(E.getConstant(), C), C); -+ RHS = E.getSymB(); -+ -+ bool isCheckInstr = -+ StringSwitch(MCS->getCurrentSectionOnly()->getName()) -+ .Case(".debug_aranges", true) -+ .Default(false); -+ -+ return (A.isInSection() -+ ? (isCheckInstr ? A.getSection().hasInstructions() : true) -+ : !A.getName().empty()) || -+ (B.isInSection() ? B.getSection().hasInstructions() -+ : !B.getName().empty()); -+} -+ -+LoongArchELFStreamer::LoongArchELFStreamer(MCContext &Context, -+ std::unique_ptr MAB, -+ std::unique_ptr OW, -+ std::unique_ptr Emitter) -+ : MCELFStreamer(Context, std::move(MAB), std::move(OW), -+ std::move(Emitter)) { -+ } -+ -+void LoongArchELFStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { -+ Frame.Begin = getContext().createTempSymbol(); -+ MCELFStreamer::emitLabel(Frame.Begin); -+} -+ -+MCSymbol *LoongArchELFStreamer::emitCFILabel() { -+ MCSymbol *Label = getContext().createTempSymbol("cfi", true); -+ MCELFStreamer::emitLabel(Label); -+ return Label; -+} -+ -+void LoongArchELFStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { -+ Frame.End = getContext().createTempSymbol(); -+ MCELFStreamer::emitLabel(Frame.End); -+} -+ -+void LoongArchELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, -+ SMLoc Loc) { -+ const MCExpr *A, *B; -+ if (!requiresFixups(getContext(), Value, A, B, this)) -+ return MCELFStreamer::emitValueImpl(Value, Size, Loc); -+ -+ MCStreamer::emitValueImpl(Value, Size, Loc); -+ -+ MCDataFragment *DF = getOrCreateDataFragment(); -+ flushPendingLabels(DF, DF->getContents().size()); -+ MCDwarfLineEntry::make(this, getCurrentSectionOnly()); -+ -+ unsigned Add, Sub; -+ std::tie(Add, Sub) = getRelocPairForSize(Size); -+ -+ DF->getFixups().push_back(MCFixup::create( -+ DF->getContents().size(), A, static_cast(Add), Loc)); -+ DF->getFixups().push_back(MCFixup::create( -+ DF->getContents().size(), B, static_cast(Sub), Loc)); -+ -+ DF->getContents().resize(DF->getContents().size() + Size, 0); -+} -+ -+MCELFStreamer *llvm::createLoongArchELFStreamer( -+ MCContext &Context, std::unique_ptr MAB, -+ std::unique_ptr OW, std::unique_ptr Emitter, -+ bool RelaxAll) { -+ return new LoongArchELFStreamer(Context, std::move(MAB), std::move(OW), -+ std::move(Emitter)); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h -new file mode 100644 -index 000000000..875cebcb7 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h -@@ -0,0 +1,53 @@ -+//===- LoongArchELFStreamer.h - ELF Object Output --------------------*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This is a custom MCELFStreamer which allows us to insert some hooks before -+// emitting data into an actual object file. -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H -+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H -+ -+#include "llvm/ADT/SmallVector.h" -+#include "llvm/MC/MCELFStreamer.h" -+#include -+ -+namespace llvm { -+ -+class MCAsmBackend; -+class MCCodeEmitter; -+class MCContext; -+class MCSubtargetInfo; -+struct MCDwarfFrameInfo; -+ -+class LoongArchELFStreamer : public MCELFStreamer { -+ -+public: -+ LoongArchELFStreamer(MCContext &Context, std::unique_ptr MAB, -+ std::unique_ptr OW, -+ std::unique_ptr Emitter); -+ -+ /// Overriding these functions allows us to dismiss all labels. -+ void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; -+ -+ // Overriding these functions allows us to avoid recording of these labels -+ // in emitLabel. -+ void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; -+ void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; -+ MCSymbol *emitCFILabel() override; -+}; -+ -+MCELFStreamer *createLoongArchELFStreamer(MCContext &Context, -+ std::unique_ptr MAB, -+ std::unique_ptr OW, -+ std::unique_ptr Emitter, -+ bool RelaxAll); -+} // end namespace llvm -+ -+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h -new file mode 100644 -index 000000000..e0e1200d8 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h -@@ -0,0 +1,90 @@ -+//===-- LoongArchFixupKinds.h - LoongArch Specific Fixup Entries ----------*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H -+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H -+ -+#include "llvm/MC/MCFixup.h" -+ -+namespace llvm { -+namespace LoongArch { -+ // Although most of the current fixup types reflect a unique relocation -+ // one can have multiple fixup types for a given relocation and thus need -+ // to be uniquely named. -+ // -+ // This table *must* be in the same order of -+ // MCFixupKindInfo Infos[LoongArch::NumTargetFixupKinds] -+ // in LoongArchAsmBackend.cpp. -+ // -+ enum Fixups { -+ // R_LARCH_NONE. -+ fixup_LARCH_NONE = FirstTargetFixupKind, -+ -+ // reloc_hint -+ fixup_LARCH_SOP_PUSH_ABSOLUTE, -+ fixup_LARCH_SOP_PUSH_PCREL, -+ fixup_LARCH_SOP_PUSH_GPREL, -+ fixup_LARCH_SOP_PUSH_TLS_TPREL, -+ fixup_LARCH_SOP_PUSH_TLS_GOT, -+ fixup_LARCH_SOP_PUSH_TLS_GD, -+ fixup_LARCH_SOP_PUSH_PLT_PCREL, -+ // fixup methods -+ fixup_LARCH_32, -+ fixup_LARCH_64, -+ fixup_LARCH_RELATIVE, -+ fixup_LARCH_COPY, -+ fixup_LARCH_JUMP_SLOT, -+ fixup_LARCH_TLS_DTPMOD32, -+ fixup_LARCH_TLS_DTPMOD64, -+ fixup_LARCH_TLS_DTPREL32, -+ fixup_LARCH_TLS_DTPREL64, -+ fixup_LARCH_TLS_TPREL32, -+ fixup_LARCH_TLS_TPREL64, -+ fixup_LARCH_IRELATIVE, -+ fixup_LARCH_MARK_LA, -+ fixup_LARCH_MARK_PCREL, -+ fixup_LARCH_SOP_PUSH_DUP, -+ fixup_LARCH_SOP_ASSERT, -+ fixup_LARCH_SOP_NOT, -+ fixup_LARCH_SOP_SUB, -+ fixup_LARCH_SOP_SL, -+ fixup_LARCH_SOP_SR, -+ fixup_LARCH_SOP_ADD, -+ fixup_LARCH_SOP_AND, -+ fixup_LARCH_SOP_IF_ELSE, -+ fixup_LARCH_SOP_POP_32_S_10_5, -+ fixup_LARCH_SOP_POP_32_U_10_12, -+ fixup_LARCH_SOP_POP_32_S_10_12, -+ fixup_LARCH_SOP_POP_32_S_10_16, -+ fixup_LARCH_SOP_POP_32_S_10_16_S2, -+ fixup_LARCH_SOP_POP_32_S_5_20, -+ fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2, -+ fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2, -+ fixup_LARCH_SOP_POP_32_U, -+ fixup_LARCH_ADD8, -+ fixup_LARCH_ADD16, -+ fixup_LARCH_ADD24, -+ fixup_LARCH_ADD32, -+ fixup_LARCH_ADD64, -+ fixup_LARCH_SUB8, -+ fixup_LARCH_SUB16, -+ fixup_LARCH_SUB24, -+ fixup_LARCH_SUB32, -+ fixup_LARCH_SUB64, -+ fixup_LARCH_GNU_VTINHERIT, -+ fixup_LARCH_GNU_VTENTRY, -+ -+ // Marker -+ LastTargetFixupKind, -+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind -+ }; -+} // namespace LoongArch -+} // namespace llvm -+ -+ -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp -index 66183868f..065020ad4 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp -@@ -1,4 +1,4 @@ --//===- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to asm syntax --===// -+//===-- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to assembly syntax ------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,53 +11,242 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchInstPrinter.h" --#include "LoongArchBaseInfo.h" --#include "llvm/MC/MCAsmInfo.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" -+#include "LoongArchInstrInfo.h" -+#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#include "llvm/ADT/StringExtras.h" -+#include "llvm/MC/MCExpr.h" - #include "llvm/MC/MCInst.h" --#include "llvm/MC/MCRegisterInfo.h" --#include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/MC/MCInstrInfo.h" - #include "llvm/MC/MCSymbol.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/raw_ostream.h" - using namespace llvm; - --#define DEBUG_TYPE "loongarch-asm-printer" -+#define DEBUG_TYPE "asm-printer" - --// Include the auto-generated portion of the assembly writer. - #define PRINT_ALIAS_INSTR - #include "LoongArchGenAsmWriter.inc" - -+template -+static bool isReg(const MCInst &MI, unsigned OpNo) { -+ assert(MI.getOperand(OpNo).isReg() && "Register operand expected."); -+ return MI.getOperand(OpNo).getReg() == R; -+} -+ -+const char* LoongArch::LoongArchFCCToString(LoongArch::CondCode CC) { -+ switch (CC) { -+ case FCOND_T: -+ case FCOND_F: return "caf"; -+ case FCOND_OR: -+ case FCOND_UN: return "cun"; -+ case FCOND_UNE: -+ case FCOND_OEQ: return "ceq"; -+ case FCOND_ONE: -+ case FCOND_UEQ: return "cueq"; -+ case FCOND_UGE: -+ case FCOND_OLT: return "clt"; -+ case FCOND_OGE: -+ case FCOND_ULT: return "cult"; -+ case FCOND_UGT: -+ case FCOND_OLE: return "cle"; -+ case FCOND_OGT: -+ case FCOND_ULE: return "cule"; -+ case FCOND_ST: -+ case FCOND_SF: return "saf"; -+ case FCOND_GLE: -+ case FCOND_NGLE:return "sun"; -+ case FCOND_SEQ: return "seq"; -+ case FCOND_SNE: return "sne"; -+ case FCOND_GL: -+ case FCOND_NGL: return "sueq"; -+ case FCOND_NLT: -+ case FCOND_LT: return "slt"; -+ case FCOND_GE: -+ case FCOND_NGE: return "sult"; -+ case FCOND_NLE: -+ case FCOND_LE: return "sle"; -+ case FCOND_GT: -+ case FCOND_NGT: return "sule"; -+ case FCOND_CNE: return "cne"; -+ case FCOND_COR: return "cor"; -+ case FCOND_SOR: return "sor"; -+ case FCOND_CUNE: return "cune"; -+ case FCOND_SUNE: return "sune"; -+ } -+ llvm_unreachable("Impossible condition code!"); -+} -+ -+void LoongArchInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { -+ OS << '$' << StringRef(getRegisterName(RegNo)).lower(); -+} -+ - void LoongArchInstPrinter::printInst(const MCInst *MI, uint64_t Address, - StringRef Annot, - const MCSubtargetInfo &STI, - raw_ostream &O) { -- if (!printAliasInstr(MI, Address, STI, O)) -- printInstruction(MI, Address, STI, O); -- printAnnotation(O, Annot); --} -+ switch (MI->getOpcode()) { -+ default: -+ break; -+ case LoongArch::PCADDU12I_ri: -+ case LoongArch::PCADDU12I_rii: -+ case LoongArch::LU12I_W_ri: -+ printLoadAddr(MI, O); -+ return; -+ case LoongArch::ADD_D_rrr: -+ case LoongArch::LDX_D_rrr: -+ case LoongArch::ADDI_D_rri: -+ case LoongArch::ADDI_D_rrii: -+ case LoongArch::LD_D_rri: -+ case LoongArch::LD_D_rrii: -+ case LoongArch::ORI_rri: -+ case LoongArch::ORI_rrii: -+ case LoongArch::LU32I_D_ri: -+ case LoongArch::LU32I_D_rii: -+ case LoongArch::LU52I_D_rri: -+ case LoongArch::LU52I_D_rrii: -+ O << "\t# la expanded slot"; -+ return; -+ } - --void LoongArchInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { -- O << '$' << getRegisterName(RegNo); -+ // Try to print any aliases first. -+ if (!printAliasInstr(MI, Address, O) && !printAlias(*MI, O)) -+ printInstruction(MI, Address, O); -+ printAnnotation(O, Annot); - } - - void LoongArchInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, -- const MCSubtargetInfo &STI, -- raw_ostream &O) { -- const MCOperand &MO = MI->getOperand(OpNo); -+ raw_ostream &O) { -+ const MCOperand &Op = MI->getOperand(OpNo); -+ if (Op.isReg()) { -+ printRegName(O, Op.getReg()); -+ return; -+ } - -- if (MO.isReg()) { -- printRegName(O, MO.getReg()); -+ if (Op.isImm()) { -+ O << formatImm(Op.getImm()); - return; - } - -+ assert(Op.isExpr() && "unknown operand kind in printOperand"); -+ Op.getExpr()->print(O, &MAI, true); -+} -+ -+template -+void LoongArchInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) { -+ const MCOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) { -- O << MO.getImm(); -+ uint64_t Imm = MO.getImm(); -+ Imm -= Offset; -+ Imm &= (1 << Bits) - 1; -+ Imm += Offset; -+ O << formatImm(Imm); - return; - } - -- assert(MO.isExpr() && "Unknown operand kind in printOperand"); -- MO.getExpr()->print(O, &MAI); -+ printOperand(MI, opNum, O); -+} -+ -+void LoongArchInstPrinter:: -+printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { -+ // Load/Store memory operands -- $reg, imm -+ printOperand(MI, opNum, O); -+ O << ", "; -+ printOperand(MI, opNum+1, O); -+} -+ -+void LoongArchInstPrinter::printAMemOperand(const MCInst *MI, int opNum, -+ raw_ostream &O) { -+ // AM* instruction memory operand: "rj, 0" -+ printRegName(O, MI->getOperand(opNum).getReg()); -+ O << ", 0"; -+} -+ -+void LoongArchInstPrinter:: -+printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { -+ // when using stack locations for not load/store instructions -+ // print the same way as all normal 3 operand instructions. -+ printOperand(MI, opNum, O); -+ O << ", "; -+ printOperand(MI, opNum+1, O); -+} -+ -+void LoongArchInstPrinter:: -+printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { -+ const MCOperand& MO = MI->getOperand(opNum); -+ O << LoongArchFCCToString((LoongArch::CondCode)MO.getImm()); -+} -+ -+bool LoongArchInstPrinter::printAlias(const char *Str, const MCInst &MI, -+ unsigned OpNo, raw_ostream &OS) { -+ OS << "\t" << Str << "\t"; -+ if(MI.getOpcode() == LoongArch::JIRL) { -+ printOperand(&MI, OpNo, OS); -+ OS << "@plt"; -+ }else -+ printOperand(&MI, OpNo, OS); -+ return true; -+} -+ -+bool LoongArchInstPrinter::printAlias(const char *Str, const MCInst &MI, -+ unsigned OpNo0, unsigned OpNo1, -+ raw_ostream &OS) { -+ printAlias(Str, MI, OpNo0, OS); -+ OS << ", "; -+ printOperand(&MI, OpNo1, OS); -+ return true; -+} -+ -+bool LoongArchInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { -+ switch (MI.getOpcode()) { -+ case LoongArch::OR: -+ // or $r0, $r1, $zero => move $r0, $r1 -+ return isReg(MI, 2) && printAlias("move", MI, 0, 1, OS); -+ default: return false; -+ } -+} -+ -+void LoongArchInstPrinter:: -+printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) { -+ // - 2 because register List is always first operand of instruction and it is -+ // always followed by memory operand (base + offset). -+ for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) { -+ if (i != opNum) -+ O << ", "; -+ printRegName(O, MI->getOperand(i).getReg()); -+ } - } - --const char *LoongArchInstPrinter::getRegisterName(unsigned RegNo) { -- // Default print reg alias name -- return getRegisterName(RegNo, LoongArch::RegAliasName); -+void LoongArchInstPrinter:: -+printLoadAddr(const MCInst *MI, raw_ostream &O) { -+ const MCOperand &Op = MI->getOperand(1); -+ const MCExpr *Expr = Op.getExpr(); -+ const LoongArchMCExpr *LoongArchExpr = cast(Expr); -+ switch (LoongArchExpr->getKind()) { -+ default: -+ llvm_unreachable("invalid handled!"); -+ return; -+ case LoongArchMCExpr::MEK_ABS_HI: -+ O << "\tla.abs\t"; -+ break; -+ case LoongArchMCExpr::MEK_GOT_HI: -+ O << "\tla.got\t"; -+ break; -+ case LoongArchMCExpr::MEK_PCREL_HI: -+ O << "\tla.pcrel\t"; -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_HI: -+ O << "\tla.tls.gd\t"; -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_HI: -+ O << "\tla.tls.ie\t"; -+ break; -+ case LoongArchMCExpr::MEK_TLSLE_HI: -+ O << "\tla.tls.le\t"; -+ break; -+ } -+ printRegName(O, MI->getOperand(0).getReg()); -+ O << ", "; -+ Expr->print(O, nullptr); -+ return; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h -index 0cbb3d73c..050dcc137 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h -@@ -1,4 +1,4 @@ --//===-- LoongArchInstPrinter.h - Convert LoongArch MCInst to asm syntax ---===// -+//=== LoongArchInstPrinter.h - Convert LoongArch MCInst to assembly syntax -*- C++ -*-==// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -10,40 +10,110 @@ - // - //===----------------------------------------------------------------------===// - --#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H --#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H -- --#include "MCTargetDesc/LoongArchMCTargetDesc.h" -+#ifndef LLVM_LIB_TARGET_LOONGARCH_INSTPRINTER_LOONGARCHINSTPRINTER_H -+#define LLVM_LIB_TARGET_LOONGARCH_INSTPRINTER_LOONGARCHINSTPRINTER_H - #include "llvm/MC/MCInstPrinter.h" - - namespace llvm { - -+namespace LoongArch { -+// LoongArch Branch Codes -+enum FPBranchCode { -+ BRANCH_F, -+ BRANCH_T, -+ BRANCH_INVALID -+}; -+ -+// LoongArch Condition Codes -+enum CondCode { -+ FCOND_F = 0x0, -+ FCOND_SF, -+ FCOND_OLT, -+ FCOND_LT, -+ FCOND_OEQ, -+ FCOND_SEQ, -+ FCOND_OLE, -+ FCOND_LE, -+ FCOND_UN, -+ FCOND_NGLE, -+ FCOND_ULT, -+ FCOND_NGE, -+ FCOND_UEQ, -+ FCOND_NGL, -+ FCOND_ULE, -+ FCOND_NGT, -+ FCOND_CNE, -+ FCOND_SNE, -+ FCOND_COR = 0x14, -+ FCOND_SOR = 0x15, -+ FCOND_CUNE = 0x18, -+ FCOND_SUNE = 0x19, -+ -+ // To be used with float branch False -+ // This conditions have the same mnemonic as the -+ // above ones, but are used with a branch False; -+ FCOND_T, -+ FCOND_UNE, -+ FCOND_ST, -+ FCOND_UGE, -+ FCOND_NLT, -+ FCOND_UGT, -+ FCOND_NLE, -+ FCOND_OR, -+ FCOND_GLE, -+ FCOND_OGE, -+ FCOND_GE, -+ FCOND_ONE, -+ FCOND_GL, -+ FCOND_OGT, -+ FCOND_GT -+}; -+ -+const char *LoongArchFCCToString(LoongArch::CondCode CC); -+} // end namespace LoongArch -+ - class LoongArchInstPrinter : public MCInstPrinter { - public: - LoongArchInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, -- const MCRegisterInfo &MRI) -- : MCInstPrinter(MAI, MII, MRI) {} -+ const MCRegisterInfo &MRI) -+ : MCInstPrinter(MAI, MII, MRI) {} - -+ // Autogenerated by tblgen. -+ std::pair getMnemonic(const MCInst *MI) override; -+ void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O); -+ static const char *getRegisterName(unsigned RegNo); -+ -+ void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, - const MCSubtargetInfo &STI, raw_ostream &O) override; -- void printRegName(raw_ostream &O, unsigned RegNo) const override; - -- // Autogenerated by tblgen. -- std::pair getMnemonic(const MCInst *MI) override; -- void printInstruction(const MCInst *MI, uint64_t Address, -- const MCSubtargetInfo &STI, raw_ostream &O); -- bool printAliasInstr(const MCInst *MI, uint64_t Address, -- const MCSubtargetInfo &STI, raw_ostream &O); -+ bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS); - void printCustomAliasOperand(const MCInst *MI, uint64_t Address, - unsigned OpIdx, unsigned PrintMethodIdx, -- const MCSubtargetInfo &STI, raw_ostream &O); -- static const char *getRegisterName(unsigned RegNo); -- static const char *getRegisterName(unsigned RegNo, unsigned AltIdx); -+ raw_ostream &O); - - private: -- void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, -- raw_ostream &O); -+ void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); -+ void printOperand(const MCInst *MI, uint64_t /*Address*/, unsigned OpNum, -+ raw_ostream &O) { -+ printOperand(MI, OpNum, O); -+ } -+ template -+ void printUImm(const MCInst *MI, int opNum, raw_ostream &O); -+ void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); -+ void printAMemOperand(const MCInst *MI, int opNum, raw_ostream &O); -+ void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); -+ void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); -+ -+ bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, -+ raw_ostream &OS); -+ bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo0, -+ unsigned OpNo1, raw_ostream &OS); -+ bool printAlias(const MCInst &MI, raw_ostream &OS); -+ void printSaveRestore(const MCInst *MI, raw_ostream &O); -+ void printRegisterList(const MCInst *MI, int opNum, raw_ostream &O); -+ void printLoadAddr(const MCInst *MI, raw_ostream &O); - }; - } // end namespace llvm - --#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp -index bc946db2f..b3091a107 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm properties ------*- C++ -*--===// -+//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm Properties ---------------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -12,23 +12,28 @@ - - #include "LoongArchMCAsmInfo.h" - #include "llvm/ADT/Triple.h" --#include "llvm/BinaryFormat/Dwarf.h" --#include "llvm/MC/MCStreamer.h" - - using namespace llvm; - --void LoongArchMCAsmInfo::anchor() {} -+void LoongArchMCAsmInfo::anchor() { } - --LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) { -- CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; -- AlignmentIsInBytes = false; -- Data8bitsDirective = "\t.byte\t"; -- Data16bitsDirective = "\t.half\t"; -- Data32bitsDirective = "\t.word\t"; -- Data64bitsDirective = "\t.dword\t"; -- ZeroDirective = "\t.space\t"; -- CommentString = "#"; -+LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TheTriple, -+ const MCTargetOptions &Options) { -+ -+ if (TheTriple.isLoongArch64() -+ && TheTriple.getEnvironment() != Triple::GNUABILPX32) -+ CodePointerSize = CalleeSaveStackSlotSize = 8; -+ -+ AlignmentIsInBytes = false; -+ Data16bitsDirective = "\t.half\t"; -+ Data32bitsDirective = "\t.word\t"; -+ Data64bitsDirective = "\t.dword\t"; -+ CommentString = "#"; -+ ZeroDirective = "\t.space\t"; - SupportsDebugInformation = true; -- DwarfRegNumForCFI = true; - ExceptionsType = ExceptionHandling::DwarfCFI; -+ DwarfRegNumForCFI = true; -+ //HasLoongArchExpressions = true; -+ UseIntegratedAssembler = true; -+ UsesELFSectionDirectiveForBSS = true; - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h -index ed1abbf46..244db58db 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h -@@ -1,4 +1,4 @@ --//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info --------------*- C++ -*--===// -+//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info ------------------------*- C++ -*--===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -22,9 +22,10 @@ class LoongArchMCAsmInfo : public MCAsmInfoELF { - void anchor() override; - - public: -- explicit LoongArchMCAsmInfo(const Triple &TargetTriple); -+ explicit LoongArchMCAsmInfo(const Triple &TheTriple, -+ const MCTargetOptions &Options); - }; - --} // end namespace llvm -+} // namespace llvm - --#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp -index 01a370a90..df4e72e90 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp -@@ -1,4 +1,4 @@ --//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// -+//===-- LoongArchMCCodeEmitter.cpp - Convert LoongArch Code to Machine Code ---------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -10,118 +10,1422 @@ - // - //===----------------------------------------------------------------------===// - --#include "MCTargetDesc/LoongArchBaseInfo.h" -+#include "LoongArchMCCodeEmitter.h" -+#include "MCTargetDesc/LoongArchFixupKinds.h" -+#include "MCTargetDesc/LoongArchMCExpr.h" - #include "MCTargetDesc/LoongArchMCTargetDesc.h" --#include "llvm/MC/MCCodeEmitter.h" -+#include "MCTargetDesc/LoongArchInstPrinter.h" -+#include "llvm/ADT/APFloat.h" -+#include "llvm/ADT/APInt.h" -+#include "llvm/ADT/SmallVector.h" - #include "llvm/MC/MCContext.h" --#include "llvm/MC/MCInstBuilder.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/MC/MCFixup.h" -+#include "llvm/MC/MCInst.h" -+#include "llvm/MC/MCInstrDesc.h" - #include "llvm/MC/MCInstrInfo.h" - #include "llvm/MC/MCRegisterInfo.h" --#include "llvm/Support/EndianStream.h" -+#include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/raw_ostream.h" -+#include -+#include - - using namespace llvm; - - #define DEBUG_TYPE "mccodeemitter" - --namespace { --class LoongArchMCCodeEmitter : public MCCodeEmitter { -- LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; -- void operator=(const LoongArchMCCodeEmitter &) = delete; -- MCContext &Ctx; -- MCInstrInfo const &MCII; -- --public: -- LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) -- : Ctx(ctx), MCII(MCII) {} -- -- ~LoongArchMCCodeEmitter() override {} -- -- void encodeInstruction(const MCInst &MI, raw_ostream &OS, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const override; -- -- /// TableGen'erated function for getting the binary encoding for an -- /// instruction. -- uint64_t getBinaryCodeForInstr(const MCInst &MI, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const; -- -- /// Return binary encoding of operand. If the machine operand requires -- /// relocation, record the relocation and return zero. -- unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const; -- -- /// Return binary encoding of an immediate operand specified by OpNo. -- /// The value returned is the value of the immediate minus 1. -- /// Note that this function is dedicated to specific immediate types, -- /// e.g. uimm2_plus1. -- unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const; -- -- /// Return binary encoding of an immediate operand specified by OpNo. -- /// The value returned is the value of the immediate shifted right -- // arithmetically by 2. -- /// Note that this function is dedicated to specific immediate types, -- /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. -- unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const; --}; --} // end namespace -+#define GET_INSTRMAP_INFO -+#include "LoongArchGenInstrInfo.inc" -+#undef GET_INSTRMAP_INFO - --unsigned --LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const { -+namespace llvm { - -- if (MO.isReg()) -- return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); -+MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, -+ MCContext &Ctx) { -+ return new LoongArchMCCodeEmitter(MCII, Ctx); -+} - -- if (MO.isImm()) -- return static_cast(MO.getImm()); -+} // end namespace llvm - -- llvm_unreachable("Unhandled expression!"); -+void LoongArchMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { -+ OS << (char)C; - } - --unsigned --LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const { -- return MI.getOperand(OpNo).getImm() - 1; -+void LoongArchMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, -+ const MCSubtargetInfo &STI, -+ raw_ostream &OS) const { -+ for (unsigned i = 0; i < Size; ++i) { -+ unsigned Shift = i * 8; -+ EmitByte((Val >> Shift) & 0xff, OS); -+ } - } - --unsigned --LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, -- SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const { -- unsigned Res = MI.getOperand(OpNo).getImm(); -- assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); -- return Res >> 2; --} -- --void LoongArchMCCodeEmitter::encodeInstruction( -- const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, -- const MCSubtargetInfo &STI) const { -- const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); -- // Get byte count of instruction. -+/// encodeInstruction - Emit the instruction. -+/// Size the instruction with Desc.getSize(). -+void LoongArchMCCodeEmitter:: -+encodeInstruction(const MCInst &MI, raw_ostream &OS, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const -+{ -+ MCInst TmpInst = MI; -+ -+ uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); -+ -+ const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); -+ -+ // Get byte count of instruction - unsigned Size = Desc.getSize(); -+ if (!Size) -+ llvm_unreachable("Desc.getSize() returns 0"); -+ -+ EmitInstruction(Binary, Size, STI, OS); -+} -+ -+/// getBranchTargetOpValue - Return binary encoding of the branch -+/// target operand. If the machine operand requires relocation, -+/// record the relocation and return zero. -+unsigned LoongArchMCCodeEmitter:: -+getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); - -- switch (Size) { -+ // If the destination is an immediate, divide by 4. -+ if (MO.isImm()) return MO.getImm() >> 2; -+ -+ assert(MO.isExpr() && -+ "getBranchTargetOpValue expects only expressions or immediates"); -+ -+ // XXX: brtarget reloc EncoderMethod. -+ const MCExpr *Expr = MO.getExpr(); -+ int64_t Value = 0x0; -+ const MCConstantExpr *tmpExpr = MCConstantExpr::create(Value, Ctx); -+ Fixups.push_back(MCFixup::create(0, Expr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_PCREL))); -+ switch (MI.getOpcode()) { - default: -- llvm_unreachable("Unhandled encodeInstruction length!"); -- case 4: { -- uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); -- support::endian::write(OS, Bits, support::little); -+ llvm_unreachable("Unhandled reloc instruction!"); -+ break; -+ case LoongArch::BEQZ: -+ case LoongArch::BEQZ32: -+ case LoongArch::BNEZ: -+ case LoongArch::BNEZ32: -+ case LoongArch::BCEQZ: -+ case LoongArch::BCNEZ: -+ Fixups.push_back(MCFixup::create(0, tmpExpr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2))); - break; -+ case LoongArch::BEQ: -+ case LoongArch::BEQ32: -+ case LoongArch::BNE: -+ case LoongArch::BNE32: -+ case LoongArch::BLT: -+ case LoongArch::BLT32: -+ case LoongArch::BGE: -+ case LoongArch::BGE32: -+ case LoongArch::BLTU: -+ case LoongArch::BLTU32: -+ case LoongArch::BGEU: -+ case LoongArch::BGEU32: -+ Fixups.push_back(MCFixup::create(0, tmpExpr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); -+ break; -+ } -+ return 0; -+} -+ -+/// getJumpTargetOpValue - Return binary encoding of the jump -+/// target operand. If the machine operand requires relocation, -+/// record the relocation and return zero. -+unsigned LoongArchMCCodeEmitter:: -+getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ // If the destination is an immediate, divide by 4. -+ if (MO.isImm()) return MO.getImm()>>2; -+ -+ assert(MO.isExpr() && -+ "getJumpTargetOpValue expects only expressions or an immediate"); -+ -+ const MCExpr *Expr = MO.getExpr(); -+ int64_t Value = 0x0; -+ const MCConstantExpr *tmpExpr = MCConstantExpr::create(Value, Ctx); -+ Fixups.push_back(MCFixup::create(0, Expr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL))); -+ if (MI.getOpcode() == LoongArch::JIRL) -+ Fixups.push_back(MCFixup::create(0, tmpExpr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); -+ else // B or BL -+ Fixups.push_back(MCFixup::create(0, tmpExpr, -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2))); -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm11Lsl1Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 1; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm10Lsl2Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 2; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm9Lsl3Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 3; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm8Lsl1Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 1; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm8Lsl2Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 2; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getSImm8Lsl3Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand &MO = MI.getOperand(OpNo); -+ if (MO.isImm()) { -+ unsigned Value = MO.getImm(); -+ return Value >> 3; -+ } -+ -+ return 0; -+} -+ -+unsigned LoongArchMCCodeEmitter:: -+getExprOpValue(const MCInst &MI, const MCExpr *Expr, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ int64_t Res; -+ -+ if (Expr->evaluateAsAbsolute(Res)) -+ return Res; -+ -+ MCExpr::ExprKind Kind = Expr->getKind(); -+ if (Kind == MCExpr::Constant) { -+ return cast(Expr)->getValue(); -+ } -+ -+ if (Kind == MCExpr::Binary) { -+ unsigned Res = getExprOpValue(MI, cast(Expr)->getLHS(), Fixups, STI); -+ Res += getExprOpValue(MI, cast(Expr)->getRHS(), Fixups, STI); -+ return Res; -+ } -+ -+ if (Kind == MCExpr::Target) { -+ int64_t Value = 0x0; -+ const LoongArchMCExpr *LoongArchExpr = cast(Expr); -+ const MCExpr *BinExpr = nullptr; -+ const MCExpr *GOTExpr = nullptr; -+ const MCSymbol *GOTSymbol = Ctx.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); -+ -+ LoongArch::Fixups FixupKind = LoongArch::Fixups(0); -+ switch (LoongArchExpr->getKind()) { -+ case LoongArchMCExpr::MEK_None: -+ case LoongArchMCExpr::MEK_Special: -+ llvm_unreachable("Unhandled fixup kind!"); -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ break; -+ case LoongArchMCExpr::MEK_PLT: -+ Value = 0x0; -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ if (MI.getOpcode() == LoongArch::JIRL) -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); -+ else // B or BL -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2))); -+ break; -+ case LoongArchMCExpr::MEK_CALL_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ -+ Value = 0x20000; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x12; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ -+ break; -+ case LoongArchMCExpr::MEK_CALL_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ -+ Value = 0x4; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x20004; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x12; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x12; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x800; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x804; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_RRHI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000000; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_RRLO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000004; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_RRHIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x80000008; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_GOT_RRHIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x8000000c; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_ABS_HI: -+ FixupKind = LoongArch::fixup_LARCH_MARK_LA; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_ABS_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_ABS_HIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_ABS_HIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x800; -+ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x804; -+ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_RRHI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000000; -+ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_RRLO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000004; -+ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_RRHIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000008; -+ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_PCREL_RRHIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x8000000c; -+ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x800; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x804; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_RRHI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000000; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_RRLO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000004; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_RRHIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x80000008; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSGD_RRHIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x8000000c; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x800; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x804; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_RRHI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000000; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_RRLO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x4; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ Value = 0x80000004; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_RRHIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x80000008; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSIE_RRHIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; -+ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, -+ MCSymbolRefExpr::VK_None, Ctx); -+ Value = 0x8000000c; -+ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); -+ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSLE_HI: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ -+ Value = 0x20; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSLE_LO: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0xfff; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); -+ break; -+ case LoongArchMCExpr::MEK_TLSLE_HIGHER: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0xc; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); -+ Value = 0x2c; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); -+ break; -+ case LoongArchMCExpr::MEK_TLSLE_HIGHEST: -+ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; -+ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); -+ Value = 0x34; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); -+ Value = 0x0; -+ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), -+ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); -+ break; -+ } -+ return 0; - } -+ -+ if (Kind == MCExpr::SymbolRef) { -+ LoongArch::Fixups FixupKind = LoongArch::Fixups(0); -+ -+ switch(cast(Expr)->getKind()) { -+ default: llvm_unreachable("Unknown fixup kind!"); -+ break; -+ } -+ Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); -+ return 0; -+ } -+ return 0; -+} -+ -+/// getMachineOpValue - Return binary encoding of operand. If the machine -+/// operand requires relocation, record the relocation and return zero. -+unsigned LoongArchMCCodeEmitter:: -+getMachineOpValue(const MCInst &MI, const MCOperand &MO, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ if (MO.isReg()) { -+ unsigned Reg = MO.getReg(); -+ unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); -+ return RegNo; -+ } else if (MO.isImm()) { -+ return static_cast(MO.getImm()); -+ } else if (MO.isDFPImm()) { -+ return static_cast(bit_cast(MO.getDFPImm())); - } -+ // MO must be an Expr. -+ assert(MO.isExpr()); -+ return getExprOpValue(MI, MO.getExpr(),Fixups, STI); - } - --MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, -- MCContext &Ctx) { -- return new LoongArchMCCodeEmitter(Ctx, MCII); -+/// Return binary encoding of memory related operand. -+/// If the offset operand requires relocation, record the relocation. -+template -+unsigned LoongArchMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 12; -+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); -+ -+ // Apply the scale factor if there is one. -+ OffBits >>= ShiftAmount; -+ -+ return (OffBits & 0xFFF) | RegBits; -+} -+ -+/// Return binary encoding of AM* memory related operand. -+unsigned -+LoongArchMCCodeEmitter::getAMemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 16-12, bits 11-0 are not used. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) -+ << 12; -+ return RegBits; -+} -+ -+unsigned LoongArchMCCodeEmitter::getMemEncoding10l2(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 10; -+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); -+ -+ // Apply the scale factor if there is one. -+ OffBits >>= 2; -+ -+ return (OffBits & 0x3FF) | RegBits; -+} -+ -+unsigned LoongArchMCCodeEmitter::getMemEncoding11l1(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 11; -+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); -+ -+ // Apply the scale factor if there is one. -+ OffBits >>= 1; -+ -+ return (OffBits & 0x7FF) | RegBits; -+} -+ -+unsigned LoongArchMCCodeEmitter::getMemEncoding9l3(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 9; -+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); -+ -+ // Apply the scale factor if there is one. -+ OffBits >>= 3; -+ -+ return (OffBits & 0x1FF) | RegBits; -+} -+ -+/// Return binary encoding of simm14 memory related operand. Such as LL/SC instructions. -+/// If the offset operand requires relocation, record the relocation. -+template -+unsigned LoongArchMCCodeEmitter::getSimm14MemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ // Base register is encoded in bits 18-14, offset is encoded in bits 13-0. -+ assert(MI.getOperand(OpNo).isReg()); -+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 14; -+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); -+ -+ // Apply the scale factor if there is one. -+ OffBits >>= ShiftAmount; -+ -+ return (OffBits & 0x3FFF) | RegBits; -+} -+ -+unsigned -+LoongArchMCCodeEmitter::getFCMPEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ const MCOperand& MO = MI.getOperand(OpNo); -+ switch((LoongArch::CondCode)MO.getImm()){ -+ case LoongArch::FCOND_T: -+ return 0x0; -+ case LoongArch::FCOND_OR: -+ return 0x8; -+ case LoongArch::FCOND_UNE: -+ return 0x4; -+ case LoongArch::FCOND_ONE: -+ return 0xC; -+ case LoongArch::FCOND_UGE: -+ return 0x2; -+ case LoongArch::FCOND_OGE: -+ return 0xA; -+ case LoongArch::FCOND_UGT: -+ return 0x6; -+ case LoongArch::FCOND_OGT: -+ return 0xE; -+ case LoongArch::FCOND_ST: -+ return 0x1; -+ case LoongArch::FCOND_GLE: -+ return 0x9; -+ case LoongArch::FCOND_GL: -+ return 0xD; -+ case LoongArch::FCOND_NLT: -+ return 0x3; -+ case LoongArch::FCOND_GE: -+ return 0xB; -+ case LoongArch::FCOND_NLE: -+ return 0x7; -+ case LoongArch::FCOND_GT: -+ return 0xF; -+ default: -+ return MO.getImm(); -+ } -+} -+ -+template -+unsigned -+LoongArchMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const { -+ assert(MI.getOperand(OpNo).isImm()); -+ unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); -+ Value -= Offset; -+ return Value; - } - - #include "LoongArchGenMCCodeEmitter.inc" -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h -new file mode 100644 -index 000000000..016340151 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h -@@ -0,0 +1,146 @@ -+//===- LoongArchMCCodeEmitter.h - Convert LoongArch Code to Machine Code --*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file defines the LoongArchMCCodeEmitter class. -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H -+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H -+ -+#include "llvm/MC/MCCodeEmitter.h" -+#include "llvm/ADT/StringRef.h" -+#include -+#include -+ -+namespace llvm { -+ -+class MCContext; -+class MCExpr; -+class MCFixup; -+class MCInst; -+class MCInstrInfo; -+class MCOperand; -+class MCSubtargetInfo; -+class raw_ostream; -+ -+class LoongArchMCCodeEmitter : public MCCodeEmitter { -+ const MCInstrInfo &MCII; -+ MCContext &Ctx; -+ -+public: -+ LoongArchMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_) -+ : MCII(mcii), Ctx(Ctx_) {} -+ LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; -+ LoongArchMCCodeEmitter &operator=(const LoongArchMCCodeEmitter &) = delete; -+ ~LoongArchMCCodeEmitter() override = default; -+ -+ void EmitByte(unsigned char C, raw_ostream &OS) const; -+ -+ void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, -+ raw_ostream &OS) const; -+ -+ void encodeInstruction(const MCInst &MI, raw_ostream &OS, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const override; -+ -+ // getBinaryCodeForInstr - TableGen'erated function for getting the -+ // binary encoding for an instruction. -+ uint64_t getBinaryCodeForInstr(const MCInst &MI, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ // getJumpTargetOpValue - Return binary encoding of the jump -+ // target operand. If the machine operand requires relocation, -+ // record the relocation and return zero. -+ unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ // getBranchTargetOpValue - Return binary encoding of the branch -+ // target operand. If the machine operand requires relocation, -+ // record the relocation and return zero. -+ unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ // getMachineOpValue - Return binary encoding of operand. If the machin -+ // operand requires relocation, record the relocation and return zero. -+ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ template -+ unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getAMemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getMemEncoding10l2(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getMemEncoding11l1(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getMemEncoding9l3(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ template -+ unsigned getSimm14MemEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getFCMPEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ /// Subtract Offset then encode as a N-bit unsigned integer. -+ template -+ unsigned getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm11Lsl1Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm10Lsl2Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm9Lsl3Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm8Lsl1Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm8Lsl2Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+ unsigned getSImm8Lsl3Encoding(const MCInst &MI, unsigned OpNo, -+ SmallVectorImpl &Fixups, -+ const MCSubtargetInfo &STI) const; -+ -+}; -+ -+} // end namespace llvm -+ -+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp -new file mode 100644 -index 000000000..1af027f15 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp -@@ -0,0 +1,158 @@ -+//===-- LoongArchMCExpr.cpp - LoongArch specific MC expression classes --------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchMCExpr.h" -+#include "llvm/BinaryFormat/ELF.h" -+#include "llvm/MC/MCAsmInfo.h" -+#include "llvm/MC/MCAssembler.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCStreamer.h" -+#include "llvm/MC/MCSymbolELF.h" -+#include "llvm/MC/MCValue.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/MathExtras.h" -+#include "llvm/Support/raw_ostream.h" -+#include -+ -+using namespace llvm; -+ -+#define DEBUG_TYPE "loongarchmcexpr" -+ -+const LoongArchMCExpr *LoongArchMCExpr::create(LoongArchMCExpr::LoongArchExprKind Kind, -+ const MCExpr *Expr, MCContext &Ctx) { -+ return new (Ctx) LoongArchMCExpr(Kind, Expr); -+} -+ -+void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { -+ int64_t AbsVal; -+ if (Expr->evaluateAsAbsolute(AbsVal)) -+ OS << AbsVal; -+ else -+ Expr->print(OS, MAI, true); -+} -+ -+bool -+LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res, -+ const MCAsmLayout *Layout, -+ const MCFixup *Fixup) const { -+ if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) -+ return false; -+ -+ if (Res.getRefKind() != MCSymbolRefExpr::VK_None) -+ return false; -+ -+ // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the -+ // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the -+ // caller. -+ if (Res.isAbsolute() && Fixup == nullptr) { -+ int64_t AbsVal = Res.getConstant(); -+ switch (Kind) { -+ default: -+ break; -+ case MEK_None: -+ case MEK_Special: -+ llvm_unreachable("MEK_None and MEK_Special are invalid"); -+ } -+ Res = MCValue::get(AbsVal); -+ return true; -+ } -+ -+ // We want to defer it for relocatable expressions since the constant is -+ // applied to the whole symbol value. -+ // -+ // The value of getKind() that is given to MCValue is only intended to aid -+ // debugging when inspecting MCValue objects. It shouldn't be relied upon -+ // for decision making. -+ Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); -+ -+ return true; -+} -+ -+void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const { -+ Streamer.visitUsedExpr(*getSubExpr()); -+} -+ -+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { -+ switch (Expr->getKind()) { -+ case MCExpr::Target: -+ fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); -+ break; -+ case MCExpr::Constant: -+ break; -+ case MCExpr::Binary: { -+ const MCBinaryExpr *BE = cast(Expr); -+ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); -+ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); -+ break; -+ } -+ case MCExpr::SymbolRef: { -+ // We're known to be under a TLS fixup, so any symbol should be -+ // modified. There should be only one. -+ const MCSymbolRefExpr &SymRef = *cast(Expr); -+ cast(SymRef.getSymbol()).setType(ELF::STT_TLS); -+ break; -+ } -+ case MCExpr::Unary: -+ fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); -+ break; -+ } -+} -+ -+void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { -+ switch (getKind()) { -+ default: -+ break; -+ case MEK_None: -+ case MEK_Special: -+ llvm_unreachable("MEK_None and MEK_Special are invalid"); -+ break; -+ case MEK_CALL_HI: -+ case MEK_CALL_LO: -+ case MEK_GOT_HI: -+ case MEK_GOT_LO: -+ case MEK_GOT_RRHI: -+ case MEK_GOT_RRLO: -+ case MEK_GOT_RRHIGHER: -+ case MEK_GOT_RRHIGHEST: -+ case MEK_ABS_HI: -+ case MEK_ABS_LO: -+ case MEK_ABS_HIGHER: -+ case MEK_ABS_HIGHEST: -+ case MEK_PCREL_HI: -+ case MEK_PCREL_LO: -+ case MEK_PCREL_RRHI: -+ case MEK_PCREL_RRHIGHER: -+ case MEK_PCREL_RRHIGHEST: -+ case MEK_PCREL_RRLO: -+ case MEK_PLT: -+ // If we do have nested target-specific expressions, they will be in -+ // a consecutive chain. -+ if (const LoongArchMCExpr *E = dyn_cast(getSubExpr())) -+ E->fixELFSymbolsInTLSFixups(Asm); -+ break; -+ case MEK_TLSGD_HI: -+ case MEK_TLSGD_LO: -+ case MEK_TLSGD_RRHI: -+ case MEK_TLSGD_RRHIGHER: -+ case MEK_TLSGD_RRHIGHEST: -+ case MEK_TLSGD_RRLO: -+ case MEK_TLSLE_HI: -+ case MEK_TLSLE_HIGHER: -+ case MEK_TLSLE_HIGHEST: -+ case MEK_TLSLE_LO: -+ case MEK_TLSIE_HI: -+ case MEK_TLSIE_LO: -+ case MEK_TLSIE_RRHI: -+ case MEK_TLSIE_RRHIGHER: -+ case MEK_TLSIE_RRHIGHEST: -+ case MEK_TLSIE_RRLO: -+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); -+ break; -+ } -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h -new file mode 100644 -index 000000000..7851d478e ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h -@@ -0,0 +1,97 @@ -+//===- LoongArchMCExpr.h - LoongArch specific MC expression classes -------*- C++ -*-===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+ -+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H -+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H -+ -+#include "llvm/MC/MCAsmLayout.h" -+#include "llvm/MC/MCExpr.h" -+#include "llvm/MC/MCValue.h" -+ -+namespace llvm { -+ -+class LoongArchMCExpr : public MCTargetExpr { -+public: -+ enum LoongArchExprKind { -+ MEK_None, -+ MEK_CALL_HI, -+ MEK_CALL_LO, -+ MEK_GOT_HI, -+ MEK_GOT_LO, -+ MEK_GOT_RRHI, -+ MEK_GOT_RRHIGHER, -+ MEK_GOT_RRHIGHEST, -+ MEK_GOT_RRLO, -+ MEK_ABS_HI, -+ MEK_ABS_HIGHER, -+ MEK_ABS_HIGHEST, -+ MEK_ABS_LO, -+ MEK_PCREL_HI, -+ MEK_PCREL_LO, -+ MEK_PCREL_RRHI, -+ MEK_PCREL_RRHIGHER, -+ MEK_PCREL_RRHIGHEST, -+ MEK_PCREL_RRLO, -+ MEK_TLSLE_HI, -+ MEK_TLSLE_HIGHER, -+ MEK_TLSLE_HIGHEST, -+ MEK_TLSLE_LO, -+ MEK_TLSIE_HI, -+ MEK_TLSIE_LO, -+ MEK_TLSIE_RRHI, -+ MEK_TLSIE_RRHIGHER, -+ MEK_TLSIE_RRHIGHEST, -+ MEK_TLSIE_RRLO, -+ MEK_TLSGD_HI, -+ MEK_TLSGD_LO, -+ MEK_TLSGD_RRHI, -+ MEK_TLSGD_RRHIGHER, -+ MEK_TLSGD_RRHIGHEST, -+ MEK_TLSGD_RRLO, -+ MEK_PLT, -+ MEK_Special, -+ }; -+ -+private: -+ const LoongArchExprKind Kind; -+ const MCExpr *Expr; -+ -+ explicit LoongArchMCExpr(LoongArchExprKind Kind, const MCExpr *Expr) -+ : Kind(Kind), Expr(Expr) {} -+ -+public: -+ static const LoongArchMCExpr *create(LoongArchExprKind Kind, const MCExpr *Expr, -+ MCContext &Ctx); -+ static const LoongArchMCExpr *createGpOff(LoongArchExprKind Kind, const MCExpr *Expr, -+ MCContext &Ctx); -+ -+ /// Get the kind of this expression. -+ LoongArchExprKind getKind() const { return Kind; } -+ -+ /// Get the child of this expression. -+ const MCExpr *getSubExpr() const { return Expr; } -+ -+ void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; -+ bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, -+ const MCFixup *Fixup) const override; -+ void visitUsedExpr(MCStreamer &Streamer) const override; -+ -+ MCFragment *findAssociatedFragment() const override { -+ return getSubExpr()->findAssociatedFragment(); -+ } -+ -+ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; -+ -+ static bool classof(const MCExpr *E) { -+ return E->getKind() == MCExpr::Target; -+ } -+}; -+ -+} // end namespace llvm -+ -+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp -index 8d71235f6..18e3224ab 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions ---------===// -+//===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions -------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -11,35 +11,47 @@ - //===----------------------------------------------------------------------===// - - #include "LoongArchMCTargetDesc.h" --#include "LoongArchBaseInfo.h" --#include "LoongArchInstPrinter.h" --#include "LoongArchMCAsmInfo.h" -+#include "LoongArchTargetStreamer.h" -+#include "MCTargetDesc/LoongArchAsmBackend.h" -+#include "MCTargetDesc/LoongArchELFStreamer.h" -+#include "MCTargetDesc/LoongArchInstPrinter.h" -+#include "MCTargetDesc/LoongArchMCAsmInfo.h" - #include "TargetInfo/LoongArchTargetInfo.h" --#include "llvm/MC/MCAsmInfo.h" --#include "llvm/MC/MCDwarf.h" -+#include "llvm/ADT/Triple.h" -+#include "llvm/MC/MCCodeEmitter.h" -+#include "llvm/MC/MCELFStreamer.h" - #include "llvm/MC/MCInstrAnalysis.h" - #include "llvm/MC/MCInstrInfo.h" -+#include "llvm/MC/MCObjectWriter.h" - #include "llvm/MC/MCRegisterInfo.h" - #include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/MC/MCSymbol.h" -+#include "llvm/MC/MachineLocation.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/FormattedStream.h" - #include "llvm/MC/TargetRegistry.h" --#include "llvm/Support/Compiler.h" -+ -+using namespace llvm; - - #define GET_INSTRINFO_MC_DESC --#define ENABLE_INSTR_PREDICATE_VERIFIER - #include "LoongArchGenInstrInfo.inc" - --#define GET_REGINFO_MC_DESC --#include "LoongArchGenRegisterInfo.inc" -- - #define GET_SUBTARGETINFO_MC_DESC - #include "LoongArchGenSubtargetInfo.inc" - --using namespace llvm; -+#define GET_REGINFO_MC_DESC -+#include "LoongArchGenRegisterInfo.inc" - --static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { -- MCRegisterInfo *X = new MCRegisterInfo(); -- InitLoongArchMCRegisterInfo(X, LoongArch::R1); -- return X; -+/// Select the LoongArch CPU for the given triple and cpu name. -+/// FIXME: Merge with the copy in LoongArchSubtarget.cpp -+StringRef LoongArch_MC::selectLoongArchCPU(const Triple &TT, StringRef CPU) { -+ if (CPU.empty() || CPU == "generic") { -+ if (TT.isLoongArch32()) -+ CPU = "loongarch32"; //FIXME -+ else -+ CPU = "la464"; -+ } -+ return CPU; - } - - static MCInstrInfo *createLoongArchMCInstrInfo() { -@@ -48,20 +60,24 @@ static MCInstrInfo *createLoongArchMCInstrInfo() { - return X; - } - --static MCSubtargetInfo * --createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { -- if (CPU.empty()) -- CPU = TT.isArch64Bit() ? "la464" : "generic-la32"; -+static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { -+ MCRegisterInfo *X = new MCRegisterInfo(); -+ InitLoongArchMCRegisterInfo(X, LoongArch::RA); -+ return X; -+} -+ -+static MCSubtargetInfo *createLoongArchMCSubtargetInfo(const Triple &TT, -+ StringRef CPU, StringRef FS) { -+ CPU = LoongArch_MC::selectLoongArchCPU(TT, CPU); - return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); - } - - static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TT, - const MCTargetOptions &Options) { -- MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT); -+ MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT, Options); - -- // Initial state of the frame pointer is sp(r3). -- MCRegister SP = MRI.getDwarfRegNum(LoongArch::R3, true); -+ unsigned SP = MRI.getDwarfRegNum(LoongArch::SP, true); - MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); - MAI->addInitialFrameState(Inst); - -@@ -76,40 +92,96 @@ static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T, - return new LoongArchInstPrinter(MAI, MII, MRI); - } - -+static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, -+ std::unique_ptr &&MAB, -+ std::unique_ptr &&OW, -+ std::unique_ptr &&Emitter, -+ bool RelaxAll) { -+ MCStreamer *S; -+ S = createLoongArchELFStreamer(Context, std::move(MAB), std::move(OW), -+ std::move(Emitter), RelaxAll); -+ return S; -+} -+ -+static MCTargetStreamer *createLoongArchAsmTargetStreamer(MCStreamer &S, -+ formatted_raw_ostream &OS, -+ MCInstPrinter *InstPrint, -+ bool isVerboseAsm) { -+ return new LoongArchTargetAsmStreamer(S, OS); -+} -+ -+static MCTargetStreamer *createLoongArchNullTargetStreamer(MCStreamer &S) { -+ return new LoongArchTargetStreamer(S); -+} -+ -+static MCTargetStreamer * -+createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { -+ return new LoongArchTargetELFStreamer(S, STI); -+} -+ - namespace { - - class LoongArchMCInstrAnalysis : public MCInstrAnalysis { - public: -- explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info) -- : MCInstrAnalysis(Info) {} -+ LoongArchMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, - uint64_t &Target) const override { - unsigned NumOps = Inst.getNumOperands(); -- if (isBranch(Inst) || Inst.getOpcode() == LoongArch::BL) { -+ if (NumOps == 0) -+ return false; -+ if (Info->get(Inst.getOpcode()).isBranch() || Inst.getOpcode() == LoongArch::BL) { -+ // just not jirl - Target = Addr + Inst.getOperand(NumOps - 1).getImm(); - return true; -+ } else { -+ return false; - } -- -- return false; - } - }; -+} - --} // end namespace -- --static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) { -+static MCInstrAnalysis *createLoongArchMCInstrAnalysis(const MCInstrInfo *Info) { - return new LoongArchMCInstrAnalysis(Info); - } - - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() { - for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) { -- TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); -+ // Register the MC asm info. -+ RegisterMCAsmInfoFn X(*T, createLoongArchMCAsmInfo); -+ -+ // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo); -+ -+ // Register the MC register info. -+ TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); -+ -+ // Register the elf streamer. -+ TargetRegistry::RegisterELFStreamer(*T, createMCStreamer); -+ -+ // Register the asm target streamer. -+ TargetRegistry::RegisterAsmTargetStreamer(*T, createLoongArchAsmTargetStreamer); -+ -+ TargetRegistry::RegisterNullTargetStreamer(*T, -+ createLoongArchNullTargetStreamer); -+ -+ // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo); -- TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo); -- TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); -- TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); -+ -+ // Register the MC instruction analyzer. -+ TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchMCInstrAnalysis); -+ -+ // Register the MCInstPrinter. - TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter); -- TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis); -+ -+ TargetRegistry::RegisterObjectTargetStreamer( -+ *T, createLoongArchObjectTargetStreamer); -+ -+ // Register the asm backend. -+ TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); - } -+ -+ // Register the MC Code Emitter -+ for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) -+ TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h -index ab35a0096..04a5c79e6 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h -@@ -1,4 +1,4 @@ --//===- LoongArchMCTargetDesc.h - LoongArch Target Descriptions --*- C++ -*-===// -+//===-- LoongArchMCTargetDesc.h - LoongArch Target Descriptions -----------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -13,8 +13,8 @@ - #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H - #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H - --#include "llvm/MC/MCTargetOptions.h" - #include "llvm/Support/DataTypes.h" -+ - #include - - namespace llvm { -@@ -25,7 +25,15 @@ class MCInstrInfo; - class MCObjectTargetWriter; - class MCRegisterInfo; - class MCSubtargetInfo; -+class MCTargetOptions; -+class StringRef; - class Target; -+class Triple; -+class raw_ostream; -+class raw_pwrite_stream; -+ -+Target &getTheLoongArch32Target(); -+Target &getTheLoongArch64Target(); - - MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, - MCContext &Ctx); -@@ -36,20 +44,24 @@ MCAsmBackend *createLoongArchAsmBackend(const Target &T, - const MCTargetOptions &Options); - - std::unique_ptr --createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); -+createLoongArchELFObjectWriter(const Triple &TT, bool IsLPX32); -+ -+namespace LoongArch_MC { -+StringRef selectLoongArchCPU(const Triple &TT, StringRef CPU); -+} - --} // end namespace llvm -+} // End llvm namespace - --// Defines symbolic names for LoongArch registers. -+// Defines symbolic names for LoongArch registers. This defines a mapping from -+// register name to register number. - #define GET_REGINFO_ENUM - #include "LoongArchGenRegisterInfo.inc" - --// Defines symbolic names for LoongArch instructions. -+// Defines symbolic names for the LoongArch instructions. - #define GET_INSTRINFO_ENUM --#define GET_INSTRINFO_MC_HELPER_DECLS - #include "LoongArchGenInstrInfo.inc" - - #define GET_SUBTARGETINFO_ENUM - #include "LoongArchGenSubtargetInfo.inc" - --#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H -+#endif -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp -deleted file mode 100644 -index 1509c436c..000000000 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp -+++ /dev/null -@@ -1,51 +0,0 @@ --//===- LoongArchMatInt.cpp - Immediate materialisation ---------*- C++ -*--===// --// --// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. --// See https://llvm.org/LICENSE.txt for license information. --// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --// --//===----------------------------------------------------------------------===// -- --#include "LoongArchMatInt.h" --#include "MCTargetDesc/LoongArchMCTargetDesc.h" --#include "llvm/Support/MathExtras.h" -- --using namespace llvm; -- --LoongArchMatInt::InstSeq LoongArchMatInt::generateInstSeq(int64_t Val) { -- // Val: -- // | hi32 | lo32 | -- // +-----------+------------------+------------------+-----------+ -- // | Highest12 | Higher20 | Hi20 | Lo12 | -- // +-----------+------------------+------------------+-----------+ -- // 63 52 51 32 31 12 11 0 -- // -- const int64_t Highest12 = Val >> 52 & 0xFFF; -- const int64_t Higher20 = Val >> 32 & 0xFFFFF; -- const int64_t Hi20 = Val >> 12 & 0xFFFFF; -- const int64_t Lo12 = Val & 0xFFF; -- InstSeq Insts; -- -- if (Highest12 != 0 && SignExtend64<52>(Val) == 0) { -- Insts.push_back(Inst(LoongArch::LU52I_D, SignExtend64<12>(Highest12))); -- return Insts; -- } -- -- if (Hi20 == 0) -- Insts.push_back(Inst(LoongArch::ORI, Lo12)); -- else if (SignExtend32<1>(Lo12 >> 11) == SignExtend32<20>(Hi20)) -- Insts.push_back(Inst(LoongArch::ADDI_W, SignExtend64<12>(Lo12))); -- else { -- Insts.push_back(Inst(LoongArch::LU12I_W, SignExtend64<20>(Hi20))); -- if (Lo12 != 0) -- Insts.push_back(Inst(LoongArch::ORI, Lo12)); -- } -- -- if (SignExtend32<1>(Hi20 >> 19) != SignExtend32<20>(Higher20)) -- Insts.push_back(Inst(LoongArch::LU32I_D, SignExtend64<20>(Higher20))); -- -- if (SignExtend32<1>(Higher20 >> 19) != SignExtend32<12>(Highest12)) -- Insts.push_back(Inst(LoongArch::LU52I_D, SignExtend64<12>(Highest12))); -- -- return Insts; --} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp -new file mode 100644 -index 000000000..4d0e785a3 ---- /dev/null -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp -@@ -0,0 +1,330 @@ -+//===-- LoongArchTargetStreamer.cpp - LoongArch Target Streamer Methods -------------===// -+// -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+// -+//===----------------------------------------------------------------------===// -+// -+// This file provides LoongArch specific target streamer methods. -+// -+//===----------------------------------------------------------------------===// -+ -+#include "LoongArchABIInfo.h" -+#include "LoongArchELFStreamer.h" -+#include "LoongArchInstPrinter.h" -+#include "LoongArchMCExpr.h" -+#include "LoongArchMCTargetDesc.h" -+#include "LoongArchTargetObjectFile.h" -+#include "LoongArchTargetStreamer.h" -+#include "llvm/BinaryFormat/ELF.h" -+#include "llvm/MC/MCAssembler.h" -+#include "llvm/MC/MCContext.h" -+#include "llvm/MC/MCSectionELF.h" -+#include "llvm/MC/MCSubtargetInfo.h" -+#include "llvm/MC/MCSymbolELF.h" -+#include "llvm/Support/Casting.h" -+#include "llvm/Support/CommandLine.h" -+#include "llvm/Support/ErrorHandling.h" -+#include "llvm/Support/FormattedStream.h" -+ -+using namespace llvm; -+ -+namespace { -+static cl::opt RoundSectionSizes( -+ "loongarch-round-section-sizes", cl::init(false), -+ cl::desc("Round section sizes up to the section alignment"), cl::Hidden); -+} // end anonymous namespace -+ -+LoongArchTargetStreamer::LoongArchTargetStreamer(MCStreamer &S) -+ : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { -+ GPRInfoSet = FPRInfoSet = FrameInfoSet = false; -+} -+void LoongArchTargetStreamer::emitDirectiveOptionPic0() {} -+void LoongArchTargetStreamer::emitDirectiveOptionPic2() {} -+void LoongArchTargetStreamer::emitDirectiveSetArch(StringRef Arch) { -+ forbidModuleDirective(); -+} -+void LoongArchTargetStreamer::emitDirectiveSetLoongArch32() { forbidModuleDirective(); } -+void LoongArchTargetStreamer::emitDirectiveSetloongarch64() { forbidModuleDirective(); } -+ -+void LoongArchTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRXX(unsigned Opcode, unsigned Reg0, MCOperand Op1, -+ MCOperand Op2, SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.addOperand(Op1); -+ TmpInst.addOperand(Op2); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRRXX(unsigned Opcode, unsigned Reg0, unsigned Reg1, -+ MCOperand Op2, MCOperand Op3, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.addOperand(MCOperand::createReg(Reg1)); -+ TmpInst.addOperand(Op2); -+ TmpInst.addOperand(Op3); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, -+ SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.addOperand(Op1); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, -+ SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI); -+} -+ -+void LoongArchTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, -+ SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI); -+} -+ -+void LoongArchTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, -+ SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createImm(Imm1)); -+ TmpInst.addOperand(MCOperand::createImm(Imm2)); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, -+ MCOperand Op2, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.addOperand(MCOperand::createReg(Reg1)); -+ TmpInst.addOperand(Op2); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, -+ unsigned Reg2, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); -+} -+ -+void LoongArchTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, -+ unsigned Reg1, int32_t Imm, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI); -+} -+ -+void LoongArchTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0, -+ unsigned Reg1, int16_t Imm0, int16_t Imm1, -+ int16_t Imm2, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ MCInst TmpInst; -+ TmpInst.setOpcode(Opcode); -+ TmpInst.addOperand(MCOperand::createReg(Reg0)); -+ TmpInst.addOperand(MCOperand::createReg(Reg1)); -+ TmpInst.addOperand(MCOperand::createImm(Imm0)); -+ TmpInst.addOperand(MCOperand::createImm(Imm1)); -+ TmpInst.addOperand(MCOperand::createImm(Imm2)); -+ TmpInst.setLoc(IDLoc); -+ getStreamer().emitInstruction(TmpInst, *STI); -+} -+ -+void LoongArchTargetStreamer::emitAdd(unsigned DstReg, unsigned SrcReg, -+ unsigned TrgReg, bool Is64Bit, -+ const MCSubtargetInfo *STI) { -+ emitRRR(Is64Bit ? LoongArch::ADD_D : LoongArch::ADD_W, DstReg, SrcReg, TrgReg, SMLoc(), -+ STI); -+} -+ -+void LoongArchTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg, -+ int16_t ShiftAmount, SMLoc IDLoc, -+ const MCSubtargetInfo *STI) { -+ if (ShiftAmount >= 32) { -+ emitRRI(LoongArch::SLLI_D, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI); -+ return; -+ } -+ -+ emitRRI(LoongArch::SLLI_D, DstReg, SrcReg, ShiftAmount, IDLoc, STI); -+} -+ -+void LoongArchTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { -+ emitRRI(LoongArch::ANDI, LoongArch::ZERO, LoongArch::ZERO, 0, IDLoc, STI); -+} -+ -+LoongArchTargetAsmStreamer::LoongArchTargetAsmStreamer(MCStreamer &S, -+ formatted_raw_ostream &OS) -+ : LoongArchTargetStreamer(S), OS(OS) {} -+ -+void LoongArchTargetAsmStreamer::emitDirectiveOptionPic0() { -+ OS << "\t.option\tpic0\n"; -+} -+ -+void LoongArchTargetAsmStreamer::emitDirectiveOptionPic2() { -+ OS << "\t.option\tpic2\n"; -+} -+ -+void LoongArchTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { -+ OS << "\t.set arch=" << Arch << "\n"; -+ LoongArchTargetStreamer::emitDirectiveSetArch(Arch); -+} -+ -+void LoongArchTargetAsmStreamer::emitDirectiveSetLoongArch32() { -+ //OS << "\t.set\tloongarch32\n"; -+ LoongArchTargetStreamer::emitDirectiveSetLoongArch32(); -+} -+ -+void LoongArchTargetAsmStreamer::emitDirectiveSetloongarch64() { -+ //OS << "\t.set\tloongarch64\n"; -+ LoongArchTargetStreamer::emitDirectiveSetloongarch64(); -+} -+ -+// This part is for ELF object output. -+LoongArchTargetELFStreamer::LoongArchTargetELFStreamer(MCStreamer &S, -+ const MCSubtargetInfo &STI) -+ : LoongArchTargetStreamer(S), STI(STI) { -+ MCAssembler &MCA = getStreamer().getAssembler(); -+ -+ // It's possible that MCObjectFileInfo isn't fully initialized at this point -+ // due to an initialization order problem where LLVMTargetMachine creates the -+ // target streamer before TargetLoweringObjectFile calls -+ // InitializeMCObjectFileInfo. There doesn't seem to be a single place that -+ // covers all cases so this statement covers most cases and direct object -+ // emission must call setPic() once MCObjectFileInfo has been initialized. The -+ // cases we don't handle here are covered by LoongArchAsmPrinter. -+ Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent(); -+ -+ // Set the header flags that we can in the constructor. -+ // FIXME: This is a fairly terrible hack. We set the rest -+ // of these in the destructor. The problem here is two-fold: -+ // -+ // a: Some of the eflags can be set/reset by directives. -+ // b: There aren't any usage paths that initialize the ABI -+ // pointer until after we initialize either an assembler -+ // or the target machine. -+ // We can fix this by making the target streamer construct -+ // the ABI, but this is fraught with wide ranging dependency -+ // issues as well. -+ unsigned EFlags = MCA.getELFHeaderEFlags(); -+ -+ // FIXME: Fix a dependency issue by instantiating the ABI object to some -+ // default based off the triple. The triple doesn't describe the target -+ // fully, but any external user of the API that uses the MCTargetStreamer -+ // would otherwise crash on assertion failure. -+ -+ ABI = LoongArchABIInfo( -+ STI.getTargetTriple().getArch() == Triple::ArchType::loongarch32 -+ ? LoongArchABIInfo::LP32() -+ : LoongArchABIInfo::LP64()); -+ -+ EFlags |= ELF::EF_LARCH_ABI; -+ MCA.setELFHeaderEFlags(EFlags); -+} -+ -+void LoongArchTargetELFStreamer::emitLabel(MCSymbol *S) { -+ auto *Symbol = cast(S); -+ getStreamer().getAssembler().registerSymbol(*Symbol); -+ uint8_t Type = Symbol->getType(); -+ if (Type != ELF::STT_FUNC) -+ return; -+ -+} -+ -+void LoongArchTargetELFStreamer::finish() { -+ MCAssembler &MCA = getStreamer().getAssembler(); -+ const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); -+ -+ // .bss, .text and .data are always at least 16-byte aligned. -+ MCSection &TextSection = *OFI.getTextSection(); -+ MCA.registerSection(TextSection); -+ MCSection &DataSection = *OFI.getDataSection(); -+ MCA.registerSection(DataSection); -+ MCSection &BSSSection = *OFI.getBSSSection(); -+ MCA.registerSection(BSSSection); -+ -+ TextSection.setAlignment(Align(std::max(16u, TextSection.getAlignment()))); -+ DataSection.setAlignment(Align(std::max(16u, DataSection.getAlignment()))); -+ BSSSection.setAlignment(Align(std::max(16u, BSSSection.getAlignment()))); -+ -+ if (RoundSectionSizes) { -+ // Make sections sizes a multiple of the alignment. This is useful for -+ // verifying the output of IAS against the output of other assemblers but -+ // it's not necessary to produce a correct object and increases section -+ // size. -+ MCStreamer &OS = getStreamer(); -+ for (MCSection &S : MCA) { -+ MCSectionELF &Section = static_cast(S); -+ -+ unsigned Alignment = Section.getAlignment(); -+ if (Alignment) { -+ OS.switchSection(&Section); -+ if (Section.useCodeAlign()) -+ OS.emitCodeAlignment(Alignment, &STI, Alignment); -+ else -+ OS.emitValueToAlignment(Alignment, 0, 1, Alignment); -+ } -+ } -+ } -+ -+ // Update e_header flags. See the FIXME and comment above in -+ // the constructor for a full rundown on this. -+ unsigned EFlags = MCA.getELFHeaderEFlags(); -+ -+ // ABI -+ // LP64 does not require any ABI bits. -+ if (getABI().IsLP32()) -+ EFlags |= ELF::EF_LARCH_ABI_LP32; -+ else if (getABI().IsLPX32()) -+ EFlags |= ELF::EF_LARCH_ABI_LPX32; -+ else -+ EFlags |= ELF::EF_LARCH_ABI_LP64; -+ -+ MCA.setELFHeaderEFlags(EFlags); -+} -+ -+MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() { -+ return static_cast(Streamer); -+} -+ -+void LoongArchTargetELFStreamer::emitDirectiveOptionPic0() { -+ MCAssembler &MCA = getStreamer().getAssembler(); -+ unsigned Flags = MCA.getELFHeaderEFlags(); -+ // This option overrides other PIC options like -KPIC. -+ Pic = false; -+ ///XXX:Reloc no this flags -+ //Flags &= ~ELF::EF_LOONGARCH_PIC; -+ MCA.setELFHeaderEFlags(Flags); -+} -+ -+void LoongArchTargetELFStreamer::emitDirectiveOptionPic2() { -+ MCAssembler &MCA = getStreamer().getAssembler(); -+ unsigned Flags = MCA.getELFHeaderEFlags(); -+ Pic = true; -+ // NOTE: We are following the GAS behaviour here which means the directive -+ // 'pic2' also sets the CPIC bit in the ELF header. This is different from -+ // what is stated in the SYSV ABI which consider the bits EF_LOONGARCH_PIC and -+ // EF_LOONGARCH_CPIC to be mutually exclusive. -+ ///XXX:Reloc no this flags -+ //Flags |= ELF::EF_LOONGARCH_PIC | ELF::EF_LOONGARCH_CPIC; -+ MCA.setELFHeaderEFlags(Flags); -+} -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt -index e14360ff5..f53ddba40 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt -@@ -2,7 +2,6 @@ add_llvm_component_library(LLVMLoongArchInfo - LoongArchTargetInfo.cpp - - LINK_COMPONENTS -- MC - Support - - ADD_TO_COMPONENT -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp -index 106545100..e6b845180 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp -@@ -1,4 +1,4 @@ --//===-- LoongArchTargetInfo.cpp - LoongArch Target Implementation ---------===// -+//===-- LoongArchTargetInfo.cpp - LoongArch Target Implementation -------------------===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -21,10 +21,14 @@ Target &llvm::getTheLoongArch64Target() { - } - - extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetInfo() { -- RegisterTarget X( -- getTheLoongArch32Target(), "loongarch32", "32-bit LoongArch", -- "LoongArch"); -- RegisterTarget Y( -- getTheLoongArch64Target(), "loongarch64", "64-bit LoongArch", -- "LoongArch"); -+#if 0 -+ //TODO: support it in futrue -+ RegisterTarget -+ X(getTheLoongArch32Target(), "loongarch32", "LoongArch (32-bit)", "LoongArch"); -+#endif -+ RegisterTarget -+ A(getTheLoongArch64Target(), "loongarch64", "LoongArch (64-bit)", -+ "LoongArch"); - } -diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h -index b24cf8795..7dce2497f 100644 ---- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h -+++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h -@@ -1,4 +1,4 @@ --//===-- LoongArchTargetInfo.h - LoongArch Target Implementation -*- C++ -*-===// -+//===-- LoongArchTargetInfo.h - LoongArch Target Implementation -----------*- C++ -*-===// - // - // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - // See https://llvm.org/LICENSE.txt for license information. -@@ -16,6 +16,6 @@ class Target; - Target &getTheLoongArch32Target(); - Target &getTheLoongArch64Target(); - --} // end namespace llvm -+} // namespace llvm - - #endif // LLVM_LIB_TARGET_LOONGARCH_TARGETINFO_LOONGARCHTARGETINFO_H -diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td b/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td -index e6d23f741..8afd0a7fc 100644 ---- a/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td -+++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td -@@ -125,10 +125,14 @@ def CC_Sparc64 : CallingConv<[ - def RetCC_Sparc64 : CallingConv<[ - // A single f32 return value always goes in %f0. The ABI doesn't specify what - // happens to multiple f32 return values outside a struct. -- CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, -+ CCIfType<[f32], CCCustom<"RetCC_Sparc64_Half">>, - -- // Otherwise, return values are passed exactly like arguments. -- CCDelegateTo -+ // Otherwise, return values are passed exactly like arguments, except that -+ // returns that are too big to fit into the registers is passed as an sret -+ // instead. -+ CCIfInReg>>, -+ CCIfType<[i32], CCPromoteToType>, -+ CCCustom<"RetCC_Sparc64_Full"> - ]>; - - // Callee-saved registers are handled by the register window mechanism. -diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp -index 2cb74e770..f55675089 100644 ---- a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp -+++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp -@@ -101,9 +101,9 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, - } - - // Allocate a full-sized argument for the 64-bit ABI. --static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, -- MVT &LocVT, CCValAssign::LocInfo &LocInfo, -- ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, -+ MVT &LocVT, CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { - assert((LocVT == MVT::f32 || LocVT == MVT::f128 - || LocVT.getSizeInBits() == 64) && - "Can't handle non-64 bits locations"); -@@ -133,6 +133,11 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, - return true; - } - -+ // Bail out if this is a return CC and we run out of registers to place -+ // values into. -+ if (IsReturn) -+ return false; -+ - // This argument goes on the stack in an 8-byte slot. - // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to - // the right-aligned float. The first 4 bytes of the stack slot are undefined. -@@ -146,9 +151,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, - // Allocate a half-sized argument for the 64-bit ABI. - // - // This is used when passing { float, int } structs by value in registers. --static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, -- MVT &LocVT, CCValAssign::LocInfo &LocInfo, -- ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT, -+ MVT &LocVT, CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { - assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); - unsigned Offset = State.AllocateStack(4, Align(4)); - -@@ -174,10 +179,43 @@ static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, - return true; - } - -+ // Bail out if this is a return CC and we run out of registers to place -+ // values into. -+ if (IsReturn) -+ return false; -+ - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - return true; - } - -+static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, -+ CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+ return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, -+ State); -+} -+ -+static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, -+ CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+ return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, -+ State); -+} -+ -+static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, -+ CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+ return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, -+ State); -+} -+ -+static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, -+ CCValAssign::LocInfo &LocInfo, -+ ISD::ArgFlagsTy &ArgFlags, CCState &State) { -+ return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, -+ State); -+} -+ - #include "SparcGenCallingConv.inc" - - // The calling conventions in SparcCallingConv.td are described in terms of the -@@ -191,6 +229,15 @@ static unsigned toCallerWindow(unsigned Reg) { - return Reg; - } - -+bool SparcTargetLowering::CanLowerReturn( -+ CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, -+ const SmallVectorImpl &Outs, LLVMContext &Context) const { -+ SmallVector RVLocs; -+ CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); -+ return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64 -+ : RetCC_Sparc32); -+} -+ - SDValue - SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, -@@ -1031,6 +1078,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, - - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { -+ assert(RVLocs[i].isRegLoc() && "Can only return in registers!"); - if (RVLocs[i].getLocVT() == MVT::v2i32) { - SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); - SDValue Lo = DAG.getCopyFromReg( -@@ -1346,6 +1394,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign &VA = RVLocs[i]; -+ assert(VA.isRegLoc() && "Can only return in registers!"); - unsigned Reg = toCallerWindow(VA.getLocReg()); - - // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can -diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h -index 2768bb205..16e4f2687 100644 ---- a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h -+++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h -@@ -144,6 +144,11 @@ namespace llvm { - SDValue LowerCall_64(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const; - -+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, -+ bool isVarArg, -+ const SmallVectorImpl &Outs, -+ LLVMContext &Context) const override; -+ - SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, -diff --git a/src/llvm-project/llvm/lib/Target/X86/X86.td b/src/llvm-project/llvm/lib/Target/X86/X86.td -index fa0a6bd41..f98916e81 100644 ---- a/src/llvm-project/llvm/lib/Target/X86/X86.td -+++ b/src/llvm-project/llvm/lib/Target/X86/X86.td -@@ -909,7 +909,6 @@ def ProcessorFeatures { - FeatureTSXLDTRK, - FeatureENQCMD, - FeatureSHSTK, -- FeatureVP2INTERSECT, - FeatureMOVDIRI, - FeatureMOVDIR64B, - FeatureUINTR]; -diff --git a/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp -index 6df040925..6fc7b29c5 100644 ---- a/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp -@@ -2003,7 +2003,7 @@ OptimizeFunctions(Module &M, - // FIXME: We should also hoist alloca affected by this to the entry - // block if possible. - if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) && -- !F.hasAddressTaken() && !hasMustTailCallers(&F)) { -+ !F.hasAddressTaken() && !hasMustTailCallers(&F) && !F.isVarArg()) { - RemoveAttribute(&F, Attribute::InAlloca); - Changed = true; - } -diff --git a/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp -index bc01d2ef7..52596b304 100644 ---- a/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp -@@ -3289,6 +3289,10 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) { - if (CallerPAL.hasParamAttr(i, Attribute::SwiftError)) - return false; - -+ if (CallerPAL.hasParamAttr(i, Attribute::ByVal) != -+ Callee->getAttributes().hasParamAttr(i, Attribute::ByVal)) -+ return false; // Cannot transform to or from byval. -+ - // If the parameter is passed as a byval argument, then we have to have a - // sized type and the sized type has to have the same size as the old type. - if (ParamTy != ActTy && CallerPAL.hasParamAttr(i, Attribute::ByVal)) { -diff --git a/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp -index 0d2662108..adc007dac 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp -@@ -406,6 +406,7 @@ static bool shouldApply(Function &F, ProfileSummaryInfo& PSI) { - return CHRFunctions.count(F.getName()); - } - -+ assert(PSI.hasProfileSummary() && "Empty PSI?"); - return PSI.isFunctionEntryHot(&F); - } - -diff --git a/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp b/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp -index 143a03574..644c5c82e 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp -@@ -1210,8 +1210,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) { - BasicBlock *BB = PN.getParent(); - Align MaxAlign; - uint64_t APWidth = DL.getIndexTypeSizeInBits(PN.getType()); -- APInt MaxSize(APWidth, 0); -- bool HaveLoad = false; -+ Type *LoadType = nullptr; - for (User *U : PN.users()) { - LoadInst *LI = dyn_cast(U); - if (!LI || !LI->isSimple()) -@@ -1223,21 +1222,27 @@ static bool isSafePHIToSpeculate(PHINode &PN) { - if (LI->getParent() != BB) - return false; - -+ if (LoadType) { -+ if (LoadType != LI->getType()) -+ return false; -+ } else { -+ LoadType = LI->getType(); -+ } -+ - // Ensure that there are no instructions between the PHI and the load that - // could store. - for (BasicBlock::iterator BBI(PN); &*BBI != LI; ++BBI) - if (BBI->mayWriteToMemory()) - return false; - -- uint64_t Size = DL.getTypeStoreSize(LI->getType()).getFixedSize(); - MaxAlign = std::max(MaxAlign, LI->getAlign()); -- MaxSize = MaxSize.ult(Size) ? APInt(APWidth, Size) : MaxSize; -- HaveLoad = true; - } - -- if (!HaveLoad) -+ if (!LoadType) - return false; - -+ APInt LoadSize = APInt(APWidth, DL.getTypeStoreSize(LoadType).getFixedSize()); -+ - // We can only transform this if it is safe to push the loads into the - // predecessor blocks. The only thing to watch out for is that we can't put - // a possibly trapping load in the predecessor if it is a critical edge. -@@ -1259,7 +1264,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) { - // If this pointer is always safe to load, or if we can prove that there - // is already a load in the block, then we can move the load to the pred - // block. -- if (isSafeToLoadUnconditionally(InVal, MaxAlign, MaxSize, DL, TI)) -+ if (isSafeToLoadUnconditionally(InVal, MaxAlign, LoadSize, DL, TI)) - continue; - - return false; -diff --git a/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp b/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp -index 97f29527b..6309eed79 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp -@@ -137,8 +137,10 @@ void LoopVersioning::addPHINodes( - // See if we have a single-operand PHI with the value defined by the - // original loop. - for (auto I = PHIBlock->begin(); (PN = dyn_cast(I)); ++I) { -- if (PN->getIncomingValue(0) == Inst) -+ if (PN->getIncomingValue(0) == Inst) { -+ SE->forgetValue(PN); - break; -+ } - } - // If not create it. - if (!PN) { -diff --git a/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp b/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp -index 42be67f3c..264da2187 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp -@@ -356,9 +356,9 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, - - // If this is memset, we just need to see if the offset is valid in the size - // of the memset.. -- if (MI->getIntrinsicID() == Intrinsic::memset) { -+ if (const auto *memset_inst = dyn_cast(MI)) { - if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) { -- auto *CI = dyn_cast(cast(MI)->getValue()); -+ auto *CI = dyn_cast(memset_inst->getValue()); - if (!CI || !CI->isZero()) - return -1; - } -diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp -index 2cdae028e..5fd4e45d8 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp -@@ -8154,7 +8154,7 @@ VPRecipeBase *VPRecipeBuilder::tryToOptimizeInductionPHI( - Phi, Operands[0], *II, *PSE.getSE(), - LoopVectorizationPlanner::getDecisionAndClampRange( - [&](ElementCount VF) { -- return !VF.isScalable() && CM.isScalarAfterVectorization(Phi, VF); -+ return CM.isScalarAfterVectorization(Phi, VF); - }, - Range)); - } -@@ -9338,7 +9338,7 @@ void VPWidenPointerInductionRecipe::execute(VPTransformState &State) { - auto *IVR = getParent()->getPlan()->getCanonicalIV(); - PHINode *CanonicalIV = cast(State.get(IVR, 0)); - -- if (onlyScalarsGenerated()) { -+ if (onlyScalarsGenerated(State.VF)) { - // This is the normalized GEP that starts counting at zero. - Value *PtrInd = State.Builder.CreateSExtOrTrunc( - CanonicalIV, IndDesc.getStep()->getType()); -diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp -index 0662ca883..30032dda7 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp -@@ -698,7 +698,7 @@ void VPlan::execute(VPTransformState *State) { - auto *WidenPhi = cast(&R); - // TODO: Split off the case that all users of a pointer phi are scalar - // from the VPWidenPointerInductionRecipe. -- if (WidenPhi->onlyScalarsGenerated()) -+ if (WidenPhi->onlyScalarsGenerated(State->VF)) - continue; - - auto *GEP = cast(State->get(WidenPhi, 0)); -diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h -index 329843bf9..7a6bc48e2 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h -+++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h -@@ -1220,7 +1220,7 @@ public: - void execute(VPTransformState &State) override; - - /// Returns true if only scalar values will be generated. -- bool onlyScalarsGenerated(); -+ bool onlyScalarsGenerated(ElementCount VF); - - #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - /// Print the recipe. -diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp -index f214563af..9a404640b 100644 ---- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp -+++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp -@@ -982,8 +982,9 @@ void VPCanonicalIVPHIRecipe::print(raw_ostream &O, const Twine &Indent, - } - #endif - --bool VPWidenPointerInductionRecipe::onlyScalarsGenerated() { -- return IsScalarAfterVectorization; -+bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(ElementCount VF) { -+ return IsScalarAfterVectorization && -+ (!VF.isScalable() || vputils::onlyFirstLaneUsed(this)); - } - - #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -diff --git a/src/llvm-project/llvm/test/CMakeLists.txt b/src/llvm-project/llvm/test/CMakeLists.txt -index 86ca20ada..e7dd22261 100644 ---- a/src/llvm-project/llvm/test/CMakeLists.txt -+++ b/src/llvm-project/llvm/test/CMakeLists.txt -@@ -8,6 +8,7 @@ llvm_canonicalize_cmake_booleans( - LLVM_ENABLE_CURL - LLVM_ENABLE_HTTPLIB - LLVM_ENABLE_ZLIB -+ LLVM_ENABLE_ZSTD - LLVM_ENABLE_LIBXML2 - LLVM_INCLUDE_GO_TESTS - LLVM_LINK_LLVM_DYLIB -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir -deleted file mode 100644 -index c7d74b987..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir -+++ /dev/null -@@ -1,96 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 1RI20 --# ------------------------------------------------------------------------------------------------- --# ---------------------+-----------------------------------------------------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------+-----------------------------------------------------------+--------------- --# opcode | imm20 | rd --# ---------------------+-----------------------------------------------------------+--------------- -- ----- --# CHECK-LABEL: test_LU12I_W: --# CHECK-ENC: 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 --# CHECK-ASM: lu12i.w $a0, 49 --name: test_LU12I_W --body: | -- bb.0: -- $r4 = LU12I_W 49 --... ----- --# CHECK-LABEL: test_LU32I_D: --# CHECK-ENC: 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 --# CHECK-ASM: lu32i.d $a0, 196 --name: test_LU32I_D --body: | -- bb.0: -- $r4 = LU32I_D $r4, 196 --... ----- --# CHECK-LABEL: test_PCADDI: --# CHECK-ENC: 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 0 1 0 0 --# CHECK-ASM: pcaddi $a0, 187 --name: test_PCADDI --body: | -- bb.0: -- $r4 = PCADDI 187 --... ----- --# CHECK-LABEL: test_PCALAU12I: --# CHECK-ENC: 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 0 --# CHECK-ASM: pcalau12i $a0, 89 --name: test_PCALAU12I --body: | -- bb.0: -- $r4 = PCALAU12I 89 --... ----- --# CHECK-LABEL: test_PCADDU12I: --# CHECK-ENC: 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: pcaddu12i $a0, 37 --name: test_PCADDU12I --body: | -- bb.0: -- $r4 = PCADDU12I 37 --... ----- --# CHECK-LABEL: test_PCADDU18I: --# CHECK-ENC: 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 --# CHECK-ASM: pcaddu18i $a0, 26 --name: test_PCADDU18I --body: | -- bb.0: -- $r4 = PCADDU18I 26 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 1RI21 --# ------------------------------------------------------------------------------------------------- --# ------------------+-----------------------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------+-----------------------------------------------+--------------+--------------- --# opcode | imm21{15-0} | rj | imm21{20-16} --# ------------------+-----------------------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_BEQZ: --# CHECK-ENC: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 0 --# CHECK-ASM: beqz $a0, 92 --name: test_BEQZ --body: | -- bb.0: -- BEQZ $r4, 92 --... ----- --# CHECK-LABEL: test_BNEZ: --# CHECK-ENC: 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 --# CHECK-ASM: bnez $a0, 84 --name: test_BNEZ --body: | -- bb.0: -- BNEZ $r4, 84 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir -deleted file mode 100644 -index 488944526..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir -+++ /dev/null -@@ -1,230 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2R --# ------------------------------------------------------------------------------------------------- --# ------------------------------------------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------------------------------------------+--------------+--------------- --# opcode | rj | rd --# ------------------------------------------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_CLO_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: clo.w $a0, $a1 --name: test_CLO_W --body: | -- bb.0: -- $r4 = CLO_W $r5 --... ----- --# CHECK-LABEL: test_CLZ_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: clz.w $a0, $a1 --name: test_CLZ_W --body: | -- bb.0: -- $r4 = CLZ_W $r5 --... ----- --# CHECK-LABEL: test_CTO_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: cto.w $a0, $a1 --name: test_CTO_W --body: | -- bb.0: -- $r4 = CTO_W $r5 --... ----- --# CHECK-LABEL: test_CTZ_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ctz.w $a0, $a1 --name: test_CTZ_W --body: | -- bb.0: -- $r4 = CTZ_W $r5 --... ----- --# CHECK-LABEL: test_CLO_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: clo.d $a0, $a1 --name: test_CLO_D --body: | -- bb.0: -- $r4 = CLO_D $r5 --... ----- --# CHECK-LABEL: test_CLZ_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: clz.d $a0, $a1 --name: test_CLZ_D --body: | -- bb.0: -- $r4 = CLZ_D $r5 --... ----- --# CHECK-LABEL: test_CTO_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: cto.d $a0, $a1 --name: test_CTO_D --body: | -- bb.0: -- $r4 = CTO_D $r5 --... ----- --# CHECK-LABEL: test_CTZ_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ctz.d $a0, $a1 --name: test_CTZ_D --body: | -- bb.0: -- $r4 = CTZ_D $r5 --... ----- --# CHECK-LABEL: test_REVB_2H: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revb.2h $a0, $a1 --name: test_REVB_2H --body: | -- bb.0: -- $r4 = REVB_2H $r5 --... ----- --# CHECK-LABEL: test_REVB_4H: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revb.4h $a0, $a1 --name: test_REVB_4H --body: | -- bb.0: -- $r4 = REVB_4H $r5 --... ----- --# CHECK-LABEL: test_REVB_2W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revb.2w $a0, $a1 --name: test_REVB_2W --body: | -- bb.0: -- $r4 = REVB_2W $r5 --... ----- --# CHECK-LABEL: test_REVB_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revb.d $a0, $a1 --name: test_REVB_D --body: | -- bb.0: -- $r4 = REVB_D $r5 --... ----- --# CHECK-LABEL: test_REVH_2W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revh.2w $a0, $a1 --name: test_REVH_2W --body: | -- bb.0: -- $r4 = REVH_2W $r5 --... ----- --# CHECK-LABEL: test_REVH_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: revh.d $a0, $a1 --name: test_REVH_D --body: | -- bb.0: -- $r4 = REVH_D $r5 --... ----- --# CHECK-LABEL: test_BITREV_4B: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bitrev.4b $a0, $a1 --name: test_BITREV_4B --body: | -- bb.0: -- $r4 = BITREV_4B $r5 --... ----- --# CHECK-LABEL: test_BITREV_8B: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bitrev.8b $a0, $a1 --name: test_BITREV_8B --body: | -- bb.0: -- $r4 = BITREV_8B $r5 --... ----- --# CHECK-LABEL: test_BITREV_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bitrev.w $a0, $a1 --name: test_BITREV_W --body: | -- bb.0: -- $r4 = BITREV_W $r5 --... ----- --# CHECK-LABEL: test_BITREV_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bitrev.d $a0, $a1 --name: test_BITREV_D --body: | -- bb.0: -- $r4 = BITREV_D $r5 --... ----- --# CHECK-LABEL: test_EXT_W_H: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ext.w.h $a0, $a1 --name: test_EXT_W_H --body: | -- bb.0: -- $r4 = EXT_W_H $r5 --... ----- --# CHECK-LABEL: test_EXT_W_B: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ext.w.b $a0, $a1 --name: test_EXT_W_B --body: | -- bb.0: -- $r4 = EXT_W_B $r5 --... ----- --# CHECK-LABEL: test_CPUCFG: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: cpucfg $a0, $a1 --name: test_CPUCFG --body: | -- bb.0: -- $r4 = CPUCFG $r5 --... ----- --# CHECK-LABEL: test_RDTIMEL_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rdtimel.w $a0, $a1 --name: test_RDTIMEL_W --body: | -- bb.0: -- $r4, $r5 = RDTIMEL_W --... ----- --# CHECK-LABEL: test_RDTIMEH_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rdtimeh.w $a0, $a1 --name: test_RDTIMEH_W --body: | -- bb.0: -- $r4, $r5 = RDTIMEH_W --... ----- --# CHECK-LABEL: test_RDTIME_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rdtime.d $a0, $a1 --name: test_RDTIME_D --body: | -- bb.0: -- $r4, $r5 = RDTIME_D -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir -deleted file mode 100644 -index 263fed42c..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir -+++ /dev/null -@@ -1,432 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2RI5 --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------------+--------------+--------------+--------------- --# opcode | imm5 | rj | rd --# ---------------------------------------------------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_SLLI_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: slli.w $a0, $a1, 0 --name: test_SLLI_W --body: | -- bb.0: -- $r4 = SLLI_W $r5, 0 --... ----- --# CHECK-LABEL: test_SRLI_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srli.w $a0, $a1, 30 --name: test_SRLI_W --body: | -- bb.0: -- $r4 = SRLI_W $r5, 30 --... ----- --# CHECK-LABEL: test_SRAI_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srai.w $a0, $a1, 24 --name: test_SRAI_W --body: | -- bb.0: -- $r4 = SRAI_W $r5, 24 --... ----- --# CHECK-LABEL: test_ROTRI_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rotri.w $a0, $a1, 23 --name: test_ROTRI_W --body: | -- bb.0: -- $r4 = ROTRI_W $r5, 23 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2RI6 --# ------------------------------------------------------------------------------------------------- --# ------------------------------------------------+-----------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------------------------+-----------------+--------------+--------------- --# opcode | imm6 | rj | rd --# ------------------------------------------------+-----------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_SLLI_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: slli.d $a0, $a1, 39 --name: test_SLLI_D --body: | -- bb.0: -- $r4 = SLLI_D $r5, 39 --... ----- --# CHECK-LABEL: test_SRLI_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srli.d $a0, $a1, 38 --name: test_SRLI_D --body: | -- bb.0: -- $r4 = SRLI_D $r5, 38 --... ----- --# CHECK-LABEL: test_SRAI_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srai.d $a0, $a1, 27 --name: test_SRAI_D --body: | -- bb.0: -- $r4 = SRAI_D $r5, 27 --... ----- --# CHECK-LABEL: test_ROTRI_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rotri.d $a0, $a1, 7 --name: test_ROTRI_D --body: | -- bb.0: -- $r4 = ROTRI_D $r5, 7 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2RI12 --# ------------------------------------------------------------------------------------------------- --# ------------------------------+-----------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------+-----------------------------------+--------------+--------------- --# opcode | imm12 | rj | rd --# ------------------------------+-----------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_SLTI: --# CHECK-ENC: 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: slti $a0, $a1, 235 --name: test_SLTI --body: | -- bb.0: -- $r4 = SLTI $r5, 235 --... ----- --# CHECK-LABEL: test_SLTUI: --# CHECK-ENC: 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sltui $a0, $a1, 162 --name: test_SLTUI --body: | -- bb.0: -- $r4 = SLTUI $r5, 162 --... ----- --# CHECK-LABEL: test_ADDI_W: --# CHECK-ENC: 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 1 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: addi.w $a0, $a1, 246 --name: test_ADDI_W --body: | -- bb.0: -- $r4 = ADDI_W $r5, 246 --... ----- --# CHECK-LABEL: test_ADDI_D: --# CHECK-ENC: 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: addi.d $a0, $a1, 75 --name: test_ADDI_D --body: | -- bb.0: -- $r4 = ADDI_D $r5, 75 --... ----- --# CHECK-LABEL: test_LU52I_D: --# CHECK-ENC: 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: lu52i.d $a0, $a1, 195 --name: test_LU52I_D --body: | -- bb.0: -- $r4 = LU52I_D $r5, 195 --... ----- --# CHECK-LABEL: test_ANDI: --# CHECK-ENC: 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: andi $a0, $a1, 106 --name: test_ANDI --body: | -- bb.0: -- $r4 = ANDI $r5, 106 --... ----- --# CHECK-LABEL: test_ORI: --# CHECK-ENC: 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ori $a0, $a1, 47 --name: test_ORI --body: | -- bb.0: -- $r4 = ORI $r5, 47 --... ----- --# CHECK-LABEL: test_XORI: --# CHECK-ENC: 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: xori $a0, $a1, 99 --name: test_XORI --body: | -- bb.0: -- $r4 = XORI $r5, 99 --... ----- --# CHECK-LABEL: test_LD_B: --# CHECK-ENC: 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.b $a0, $a1, 21 --name: test_LD_B --body: | -- bb.0: -- $r4 = LD_B $r5, 21 --... ----- --# CHECK-LABEL: test_LD_H: --# CHECK-ENC: 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.h $a0, $a1, 80 --name: test_LD_H --body: | -- bb.0: -- $r4 = LD_H $r5, 80 --... ----- --# CHECK-LABEL: test_LD_W: --# CHECK-ENC: 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.w $a0, $a1, 92 --name: test_LD_W --body: | -- bb.0: -- $r4 = LD_W $r5, 92 --... ----- --# CHECK-LABEL: test_LD_BU: --# CHECK-ENC: 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.bu $a0, $a1, 150 --name: test_LD_BU --body: | -- bb.0: -- $r4 = LD_BU $r5, 150 --... ----- --# CHECK-LABEL: test_LD_HU: --# CHECK-ENC: 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.hu $a0, $a1, 198 --name: test_LD_HU --body: | -- bb.0: -- $r4 = LD_HU $r5, 198 --... ----- --# CHECK-LABEL: test_LD_WU: --# CHECK-ENC: 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ld.wu $a0, $a1, 31 --name: test_LD_WU --body: | -- bb.0: -- $r4 = LD_WU $r5, 31 --... ----- --# CHECK-LABEL: test_ST_B: --# CHECK-ENC: 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: st.b $a0, $a1, 95 --name: test_ST_B --body: | -- bb.0: -- ST_B $r4, $r5, 95 --... ----- --# CHECK-LABEL: test_ST_H: --# CHECK-ENC: 0 0 1 0 1 0 0 1 0 1 0 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: st.h $a0, $a1, 122 --name: test_ST_H --body: | -- bb.0: -- ST_H $r4, $r5, 122 --... ----- --# CHECK-LABEL: test_ST_W: --# CHECK-ENC: 0 0 1 0 1 0 0 1 1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: st.w $a0, $a1, 175 --name: test_ST_W --body: | -- bb.0: -- ST_W $r4, $r5, 175 --... ----- --# CHECK-LABEL: test_ST_D: --# CHECK-ENC: 0 0 1 0 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: st.d $a0, $a1, 60 --name: test_ST_D --body: | -- bb.0: -- ST_D $r4, $r5, 60 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2RI14 --# ------------------------------------------------------------------------------------------------- --# ------------------------+-----------------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------+-----------------------------------------+--------------+--------------- --# opcode | imm14 | rj | rd --# ------------------------+-----------------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_LDPTR_W: --# CHECK-ENC: 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldptr.w $a0, $a1, 264 --name: test_LDPTR_W --body: | -- bb.0: -- $r4 = LDPTR_W $r5, 264 --... ----- --# CHECK-LABEL: test_LDPTR_D: --# CHECK-ENC: 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldptr.d $a0, $a1, 224 --name: test_LDPTR_D --body: | -- bb.0: -- $r4 = LDPTR_D $r5, 224 --... ----- --# CHECK-LABEL: test_STPTR_W: --# CHECK-ENC: 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stptr.w $a0, $a1, 348 --name: test_STPTR_W --body: | -- bb.0: -- STPTR_W $r4, $r5, 348 --... ----- --# CHECK-LABEL: test_STPTR_D: --# CHECK-ENC: 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stptr.d $a0, $a1, 580 --name: test_STPTR_D --body: | -- bb.0: -- STPTR_D $r4, $r5, 580 --... ----- --# CHECK-LABEL: test_LL_W: --# CHECK-ENC: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ll.w $a0, $a1, 972 --name: test_LL_W --body: | -- bb.0: -- $r4 = LL_W $r5, 972 --... ----- --# CHECK-LABEL: test_LL_D: --# CHECK-ENC: 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ll.d $a0, $a1, 296 --name: test_LL_D --body: | -- bb.0: -- $r4 = LL_D $r5, 296 --... ----- --# CHECK-LABEL: test_SC_W: --# CHECK-ENC: 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sc.w $a0, $a1, 384 --name: test_SC_W --body: | -- bb.0: -- $r4 = SC_W $r4, $r5, 384 --... ----- --# CHECK-LABEL: test_SC_D: --# CHECK-ENC: 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sc.d $a0, $a1, 420 --name: test_SC_D --body: | -- bb.0: -- $r4 = SC_D $r4, $r5, 420 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 2RI16 --# ------------------------------------------------------------------------------------------------- --# ------------------+-----------------------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------+-----------------------------------------------+--------------+--------------- --# opcode | imm16 | rj | rd --# ------------------+-----------------------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_ADDU16I_D: --# CHECK-ENC: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: addu16i.d $a0, $a1, 23 --name: test_ADDU16I_D --body: | -- bb.0: -- $r4 = ADDU16I_D $r5, 23 --... ----- --# CHECK-LABEL: test_JIRL: --# CHECK-ENC: 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: jirl $a0, $a1, 196 --name: test_JIRL --body: | -- bb.0: -- $r4 = JIRL $r5, 196 --... ----- --# CHECK-LABEL: test_BEQ: --# CHECK-ENC: 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: beq $a0, $a1, 784 --name: test_BEQ --body: | -- bb.0: -- BEQ $r4, $r5, 784 --... ----- --# CHECK-LABEL: test_BNE: --# CHECK-ENC: 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: bne $a0, $a1, 76 --name: test_BNE --body: | -- bb.0: -- BNE $r4, $r5, 76 --... ----- --# CHECK-LABEL: test_BLT: --# CHECK-ENC: 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: blt $a0, $a1, 492 --name: test_BLT --body: | -- bb.0: -- BLT $r4, $r5, 492 --... ----- --# CHECK-LABEL: test_BGE: --# CHECK-ENC: 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: bge $a0, $a1, 48 --name: test_BGE --body: | -- bb.0: -- BGE $r4, $r5, 48 --... ----- --# CHECK-LABEL: test_BLTU: --# CHECK-ENC: 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: bltu $a0, $a1, 68 --name: test_BLTU --body: | -- bb.0: -- BLTU $r4, $r5, 68 --... ----- --# CHECK-LABEL: test_BGEU: --# CHECK-ENC: 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 --# CHECK-ASM: bgeu $a0, $a1, 352 --name: test_BGEU --body: | -- bb.0: -- BGEU $r4, $r5, 352 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir -deleted file mode 100644 -index a1b97d563..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir -+++ /dev/null -@@ -1,995 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 3R --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------------+--------------+--------------+--------------- --# opcode | rk | rj | rd --# ---------------------------------------------------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_ADD_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: add.w $a0, $a1, $a0 --name: test_ADD_W --body: | -- bb.0: -- $r4 = ADD_W $r5, $r4 --... ----- --# CHECK-LABEL: test_ADD_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: add.d $a0, $a1, $a0 --name: test_ADD_D --body: | -- bb.0: -- $r4 = ADD_D $r5, $r4 --... ----- --# CHECK-LABEL: test_SUB_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sub.w $a0, $a1, $a0 --name: test_SUB_W --body: | -- bb.0: -- $r4 = SUB_W $r5, $r4 --... ----- --# CHECK-LABEL: test_SUB_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sub.d $a0, $a1, $a0 --name: test_SUB_D --body: | -- bb.0: -- $r4 = SUB_D $r5, $r4 --... ----- --# CHECK-LABEL: test_SLT: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: slt $a0, $a1, $a0 --name: test_SLT --body: | -- bb.0: -- $r4 = SLT $r5, $r4 --... ----- --# CHECK-LABEL: test_SLTU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sltu $a0, $a1, $a0 --name: test_SLTU --body: | -- bb.0: -- $r4 = SLTU $r5, $r4 --... ----- --# CHECK-LABEL: test_MASKEQZ: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: maskeqz $a0, $a1, $a0 --name: test_MASKEQZ --body: | -- bb.0: -- $r4 = MASKEQZ $r5, $r4 --... ----- --# CHECK-LABEL: test_MASKNEZ: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: masknez $a0, $a1, $a0 --name: test_MASKNEZ --body: | -- bb.0: -- $r4 = MASKNEZ $r5, $r4 --... ----- --# CHECK-LABEL: test_NOR: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: nor $a0, $a1, $a0 --name: test_NOR --body: | -- bb.0: -- $r4 = NOR $r5, $r4 --... ----- --# CHECK-LABEL: test_AND: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: and $a0, $a1, $a0 --name: test_AND --body: | -- bb.0: -- $r4 = AND $r5, $r4 --... ----- --# CHECK-LABEL: test_OR: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: or $a0, $a1, $a0 --name: test_OR --body: | -- bb.0: -- $r4 = OR $r5, $r4 --... ----- --# CHECK-LABEL: test_XOR: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: xor $a0, $a1, $a0 --name: test_XOR --body: | -- bb.0: -- $r4 = XOR $r5, $r4 --... ----- --# CHECK-LABEL: test_ORN: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: orn $a0, $a1, $a0 --name: test_ORN --body: | -- bb.0: -- $r4 = ORN $r5, $r4 --... ----- --# CHECK-LABEL: test_ANDN: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: andn $a0, $a1, $a0 --name: test_ANDN --body: | -- bb.0: -- $r4 = ANDN $r5, $r4 --... ----- --# CHECK-LABEL: test_SLL_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sll.w $a0, $a1, $a0 --name: test_SLL_W --body: | -- bb.0: -- $r4 = SLL_W $r5, $r4 --... ----- --# CHECK-LABEL: test_SRL_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srl.w $a0, $a1, $a0 --name: test_SRL_W --body: | -- bb.0: -- $r4 = SRL_W $r5, $r4 --... ----- --# CHECK-LABEL: test_SRA_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sra.w $a0, $a1, $a0 --name: test_SRA_W --body: | -- bb.0: -- $r4 = SRA_W $r5, $r4 --... ----- --# CHECK-LABEL: test_SLL_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sll.d $a0, $a1, $a0 --name: test_SLL_D --body: | -- bb.0: -- $r4 = SLL_D $r5, $r4 --... ----- --# CHECK-LABEL: test_SRL_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: srl.d $a0, $a1, $a0 --name: test_SRL_D --body: | -- bb.0: -- $r4 = SRL_D $r5, $r4 --... ----- --# CHECK-LABEL: test_SRA_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: sra.d $a0, $a1, $a0 --name: test_SRA_D --body: | -- bb.0: -- $r4 = SRA_D $r5, $r4 --... ----- --# CHECK-LABEL: test_ROTR_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rotr.w $a0, $a1, $a0 --name: test_ROTR_W --body: | -- bb.0: -- $r4 = ROTR_W $r5, $r4 --... ----- --# CHECK-LABEL: test_ROTR_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: rotr.d $a0, $a1, $a0 --name: test_ROTR_D --body: | -- bb.0: -- $r4 = ROTR_D $r5, $r4 --... ----- --# CHECK-LABEL: test_MUL_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mul.w $a0, $a1, $a0 --name: test_MUL_W --body: | -- bb.0: -- $r4 = MUL_W $r5, $r4 --... ----- --# CHECK-LABEL: test_MULH_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulh.w $a0, $a1, $a0 --name: test_MULH_W --body: | -- bb.0: -- $r4 = MULH_W $r5, $r4 --... ----- --# CHECK-LABEL: test_MULH_WU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulh.wu $a0, $a1, $a0 --name: test_MULH_WU --body: | -- bb.0: -- $r4 = MULH_WU $r5, $r4 --... ----- --# CHECK-LABEL: test_MUL_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mul.d $a0, $a1, $a0 --name: test_MUL_D --body: | -- bb.0: -- $r4 = MUL_D $r5, $r4 --... ----- --# CHECK-LABEL: test_MULH_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulh.d $a0, $a1, $a0 --name: test_MULH_D --body: | -- bb.0: -- $r4 = MULH_D $r5, $r4 --... ----- --# CHECK-LABEL: test_MULH_DU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulh.du $a0, $a1, $a0 --name: test_MULH_DU --body: | -- bb.0: -- $r4 = MULH_DU $r5, $r4 --... ----- --# CHECK-LABEL: test_MULW_D_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulw.d.w $a0, $a1, $a0 --name: test_MULW_D_W --body: | -- bb.0: -- $r4 = MULW_D_W $r5, $r4 --... ----- --# CHECK-LABEL: test_MULW_D_WU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mulw.d.wu $a0, $a1, $a0 --name: test_MULW_D_WU --body: | -- bb.0: -- $r4 = MULW_D_WU $r5, $r4 --... ----- --# CHECK-LABEL: test_DIV_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: div.w $a0, $a1, $a0 --name: test_DIV_W --body: | -- bb.0: -- $r4 = DIV_W $r5, $r4 --... ----- --# CHECK-LABEL: test_MOD_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mod.w $a0, $a1, $a0 --name: test_MOD_W --body: | -- bb.0: -- $r4 = MOD_W $r5, $r4 --... ----- --# CHECK-LABEL: test_DIV_WU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: div.wu $a0, $a1, $a0 --name: test_DIV_WU --body: | -- bb.0: -- $r4 = DIV_WU $r5, $r4 --... ----- --# CHECK-LABEL: test_MOD_WU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mod.wu $a0, $a1, $a0 --name: test_MOD_WU --body: | -- bb.0: -- $r4 = MOD_WU $r5, $r4 --... ----- --# CHECK-LABEL: test_DIV_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: div.d $a0, $a1, $a0 --name: test_DIV_D --body: | -- bb.0: -- $r4 = DIV_D $r5, $r4 --... ----- --# CHECK-LABEL: test_MOD_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mod.d $a0, $a1, $a0 --name: test_MOD_D --body: | -- bb.0: -- $r4 = MOD_D $r5, $r4 --... ----- --# CHECK-LABEL: test_DIV_DU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: div.du $a0, $a1, $a0 --name: test_DIV_DU --body: | -- bb.0: -- $r4 = DIV_DU $r5, $r4 --... ----- --# CHECK-LABEL: test_MOD_DU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: mod.du $a0, $a1, $a0 --name: test_MOD_DU --body: | -- bb.0: -- $r4 = MOD_DU $r5, $r4 --... ----- --# CHECK-LABEL: test_CRC_W_B_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crc.w.b.w $a0, $a1, $a0 --name: test_CRC_W_B_W --body: | -- bb.0: -- $r4 = CRC_W_B_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRC_W_H_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crc.w.h.w $a0, $a1, $a0 --name: test_CRC_W_H_W --body: | -- bb.0: -- $r4 = CRC_W_H_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRC_W_W_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crc.w.w.w $a0, $a1, $a0 --name: test_CRC_W_W_W --body: | -- bb.0: -- $r4 = CRC_W_W_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRC_W_D_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crc.w.d.w $a0, $a1, $a0 --name: test_CRC_W_D_W --body: | -- bb.0: -- $r4 = CRC_W_D_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRCC_W_B_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crcc.w.b.w $a0, $a1, $a0 --name: test_CRCC_W_B_W --body: | -- bb.0: -- $r4 = CRCC_W_B_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRCC_W_H_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crcc.w.h.w $a0, $a1, $a0 --name: test_CRCC_W_H_W --body: | -- bb.0: -- $r4 = CRCC_W_H_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRCC_W_W_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crcc.w.w.w $a0, $a1, $a0 --name: test_CRCC_W_W_W --body: | -- bb.0: -- $r4 = CRCC_W_W_W $r5, $r4 --... ----- --# CHECK-LABEL: test_CRCC_W_D_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: crcc.w.d.w $a0, $a1, $a0 --name: test_CRCC_W_D_W --body: | -- bb.0: -- $r4 = CRCC_W_D_W $r5, $r4 --... ----- --# CHECK-LABEL: test_AMSWAP_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amswap_db.w $a0, $a1, $a2 --name: test_AMSWAP_DB_W --body: | -- bb.0: -- $r4 = AMSWAP_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMSWAP_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amswap_db.d $a0, $a1, $a2 --name: test_AMSWAP_DB_D --body: | -- bb.0: -- $r4 = AMSWAP_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMADD_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amadd_db.w $a0, $a1, $a2 --name: test_AMADD_DB_W --body: | -- bb.0: -- $r4 = AMADD_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMADD_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amadd_db.d $a0, $a1, $a2 --name: test_AMADD_DB_D --body: | -- bb.0: -- $r4 = AMADD_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMAND_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amand_db.w $a0, $a1, $a2 --name: test_AMAND_DB_W --body: | -- bb.0: -- $r4 = AMAND_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMAND_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amand_db.d $a0, $a1, $a2 --name: test_AMAND_DB_D --body: | -- bb.0: -- $r4 = AMAND_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMOR_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amor_db.w $a0, $a1, $a2 --name: test_AMOR_DB_W --body: | -- bb.0: -- $r4 = AMOR_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMOR_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amor_db.d $a0, $a1, $a2 --name: test_AMOR_DB_D --body: | -- bb.0: -- $r4 = AMOR_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMXOR_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amxor_db.w $a0, $a1, $a2 --name: test_AMXOR_DB_W --body: | -- bb.0: -- $r4 = AMXOR_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMXOR_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amxor_db.d $a0, $a1, $a2 --name: test_AMXOR_DB_D --body: | -- bb.0: -- $r4 = AMXOR_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax_db.w $a0, $a1, $a2 --name: test_AMMAX_DB_W --body: | -- bb.0: -- $r4 = AMMAX_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax_db.d $a0, $a1, $a2 --name: test_AMMAX_DB_D --body: | -- bb.0: -- $r4 = AMMAX_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_DB_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin_db.w $a0, $a1, $a2 --name: test_AMMIN_DB_W --body: | -- bb.0: -- $r4 = AMMIN_DB_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_DB_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin_db.d $a0, $a1, $a2 --name: test_AMMIN_DB_D --body: | -- bb.0: -- $r4 = AMMIN_DB_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_DB_WU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax_db.wu $a0, $a1, $a2 --name: test_AMMAX_DB_WU --body: | -- bb.0: -- $r4 = AMMAX_DB_WU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_DB_DU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax_db.du $a0, $a1, $a2 --name: test_AMMAX_DB_DU --body: | -- bb.0: -- $r4 = AMMAX_DB_DU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_DB_WU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin_db.wu $a0, $a1, $a2 --name: test_AMMIN_DB_WU --body: | -- bb.0: -- $r4 = AMMIN_DB_WU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_DB_DU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin_db.du $a0, $a1, $a2 --name: test_AMMIN_DB_DU --body: | -- bb.0: -- $r4 = AMMIN_DB_DU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMSWAP_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amswap.w $a0, $a1, $a2 --name: test_AMSWAP_W --body: | -- bb.0: -- $r4 = AMSWAP_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMSWAP_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amswap.d $a0, $a1, $a2 --name: test_AMSWAP_D --body: | -- bb.0: -- $r4 = AMSWAP_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMADD_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amadd.w $a0, $a1, $a2 --name: test_AMADD_W --body: | -- bb.0: -- $r4 = AMADD_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMADD_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amadd.d $a0, $a1, $a2 --name: test_AMADD_D --body: | -- bb.0: -- $r4 = AMADD_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMAND_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amand.w $a0, $a1, $a2 --name: test_AMAND_W --body: | -- bb.0: -- $r4 = AMAND_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMAND_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amand.d $a0, $a1, $a2 --name: test_AMAND_D --body: | -- bb.0: -- $r4 = AMAND_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMOR_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amor.w $a0, $a1, $a2 --name: test_AMOR_W --body: | -- bb.0: -- $r4 = AMOR_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMOR_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amor.d $a0, $a1, $a2 --name: test_AMOR_D --body: | -- bb.0: -- $r4 = AMOR_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMXOR_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amxor.w $a0, $a1, $a2 --name: test_AMXOR_W --body: | -- bb.0: -- $r4 = AMXOR_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMXOR_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: amxor.d $a0, $a1, $a2 --name: test_AMXOR_D --body: | -- bb.0: -- $r4 = AMXOR_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax.w $a0, $a1, $a2 --name: test_AMMAX_W --body: | -- bb.0: -- $r4 = AMMAX_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax.d $a0, $a1, $a2 --name: test_AMMAX_D --body: | -- bb.0: -- $r4 = AMMAX_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin.w $a0, $a1, $a2 --name: test_AMMIN_W --body: | -- bb.0: -- $r4 = AMMIN_W $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin.d $a0, $a1, $a2 --name: test_AMMIN_D --body: | -- bb.0: -- $r4 = AMMIN_D $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_WU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax.wu $a0, $a1, $a2 --name: test_AMMAX_WU --body: | -- bb.0: -- $r4 = AMMAX_WU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMAX_DU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammax.du $a0, $a1, $a2 --name: test_AMMAX_DU --body: | -- bb.0: -- $r4 = AMMAX_DU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_WU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin.wu $a0, $a1, $a2 --name: test_AMMIN_WU --body: | -- bb.0: -- $r4 = AMMIN_WU $r5, $r6 --... ----- --# CHECK-LABEL: test_AMMIN_DU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 --# CHECK-ASM: ammin.du $a0, $a1, $a2 --name: test_AMMIN_DU --body: | -- bb.0: -- $r4 = AMMIN_DU $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.b $a0, $a1, $a2 --name: test_LDX_B --body: | -- bb.0: -- $r4 = LDX_B $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.h $a0, $a1, $a2 --name: test_LDX_H --body: | -- bb.0: -- $r4 = LDX_H $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.w $a0, $a1, $a2 --name: test_LDX_W --body: | -- bb.0: -- $r4 = LDX_W $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.d $a0, $a1, $a2 --name: test_LDX_D --body: | -- bb.0: -- $r4 = LDX_D $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_BU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.bu $a0, $a1, $a2 --name: test_LDX_BU --body: | -- bb.0: -- $r4 = LDX_BU $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_HU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.hu $a0, $a1, $a2 --name: test_LDX_HU --body: | -- bb.0: -- $r4 = LDX_HU $r5, $r6 --... ----- --# CHECK-LABEL: test_LDX_WU: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldx.wu $a0, $a1, $a2 --name: test_LDX_WU --body: | -- bb.0: -- $r4 = LDX_WU $r5, $r6 --... ----- --# CHECK-LABEL: test_LDGT_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldgt.b $a0, $a1, $a2 --name: test_LDGT_B --body: | -- bb.0: -- $r4 = LDGT_B $r5, $r6 --... ----- --# CHECK-LABEL: test_LDGT_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldgt.h $a0, $a1, $a2 --name: test_LDGT_H --body: | -- bb.0: -- $r4 = LDGT_H $r5, $r6 --... ----- --# CHECK-LABEL: test_LDGT_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldgt.w $a0, $a1, $a2 --name: test_LDGT_W --body: | -- bb.0: -- $r4 = LDGT_W $r5, $r6 --... ----- --# CHECK-LABEL: test_LDGT_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldgt.d $a0, $a1, $a2 --name: test_LDGT_D --body: | -- bb.0: -- $r4 = LDGT_D $r5, $r6 --... ----- --# CHECK-LABEL: test_LDLE_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldle.b $a0, $a1, $a2 --name: test_LDLE_B --body: | -- bb.0: -- $r4 = LDLE_B $r5, $r6 --... ----- --# CHECK-LABEL: test_LDLE_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldle.h $a0, $a1, $a2 --name: test_LDLE_H --body: | -- bb.0: -- $r4 = LDLE_H $r5, $r6 --... ----- --# CHECK-LABEL: test_LDLE_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldle.w $a0, $a1, $a2 --name: test_LDLE_W --body: | -- bb.0: -- $r4 = LDLE_W $r5, $r6 --... ----- --# CHECK-LABEL: test_LDLE_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: ldle.d $a0, $a1, $a2 --name: test_LDLE_D --body: | -- bb.0: -- $r4 = LDLE_D $r5, $r6 --... ----- --# CHECK-LABEL: test_STX_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stx.b $a0, $a1, $a2 --name: test_STX_B --body: | -- bb.0: -- STX_B $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STX_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stx.h $a0, $a1, $a2 --name: test_STX_H --body: | -- bb.0: -- STX_H $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STX_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stx.w $a0, $a1, $a2 --name: test_STX_W --body: | -- bb.0: -- STX_W $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STX_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stx.d $a0, $a1, $a2 --name: test_STX_D --body: | -- bb.0: -- STX_D $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STGT_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stgt.b $a0, $a1, $a2 --name: test_STGT_B --body: | -- bb.0: -- STGT_B $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STGT_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stgt.h $a0, $a1, $a2 --name: test_STGT_H --body: | -- bb.0: -- STGT_H $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STGT_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stgt.w $a0, $a1, $a2 --name: test_STGT_W --body: | -- bb.0: -- STGT_W $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STGT_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stgt.d $a0, $a1, $a2 --name: test_STGT_D --body: | -- bb.0: -- STGT_D $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STLE_B: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stle.b $a0, $a1, $a2 --name: test_STLE_B --body: | -- bb.0: -- STLE_B $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STLE_H: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stle.h $a0, $a1, $a2 --name: test_STLE_H --body: | -- bb.0: -- STLE_H $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STLE_W: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stle.w $a0, $a1, $a2 --name: test_STLE_W --body: | -- bb.0: -- STLE_W $r4, $r5, $r6 --... ----- --# CHECK-LABEL: test_STLE_D: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: stle.d $a0, $a1, $a2 --name: test_STLE_D --body: | -- bb.0: -- STLE_D $r4, $r5, $r6 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir -deleted file mode 100644 -index c86e14189..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir -+++ /dev/null -@@ -1,69 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 3RI2 --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------+-----+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------+-----+--------------+--------------+--------------- --# opcode |imm2 | rk | rj | rd --# ---------------------------------------------+-----+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_ALSL_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: alsl.w $a0, $a1, $a2, 4 --name: test_ALSL_W --body: | -- bb.0: -- $r4 = ALSL_W $r5, $r6, 4 --... ----- --# CHECK-LABEL: test_ALSL_WU: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: alsl.wu $a0, $a1, $a2, 2 --name: test_ALSL_WU --body: | -- bb.0: -- $r4 = ALSL_WU $r5, $r6, 2 --... ----- --# CHECK-LABEL: test_ALSL_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: alsl.d $a0, $a1, $a2, 4 --name: test_ALSL_D --body: | -- bb.0: -- $r4 = ALSL_D $r5, $r6, 4 --... ----- --# CHECK-LABEL: test_BYTEPICK_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bytepick.w $a0, $a1, $a2, 0 --name: test_BYTEPICK_W --body: | -- bb.0: -- $r4 = BYTEPICK_W $r5, $r6, 0 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: 3RI3 --# ------------------------------------------------------------------------------------------------- --# ------------------------------------------+--------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------------------+--------+--------------+--------------+--------------- --# opcode | imm3 | rk | rj | rd --# ------------------------------------------+--------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_BYTEPICK_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bytepick.d $a0, $a1, $a2, 4 --name: test_BYTEPICK_D --body: | -- bb.0: -- $r4 = BYTEPICK_D $r5, $r6, 4 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll -new file mode 100644 -index 000000000..c5b08dbd4 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll -@@ -0,0 +1,8 @@ -+; RUN: llc -mtriple=loongarch64 %s -o - | FileCheck %s -+ -+define void @foo() { -+;CHECK: .p2align 2 -+;CHECK: foo: -+entry: -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll -new file mode 100644 -index 000000000..d1d0c0bc4 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll -@@ -0,0 +1,17 @@ -+; Test that the last immediate 0 operand of amtomic instruction is printed -+ -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define void @test_i32(i32* %dst, i32 %val) { -+; CHECK: ammax_db.wu $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG3:[0-9]+]], 0 -+entry: -+ %a = atomicrmw umax i32* %dst, i32 %val monotonic -+ ret void -+} -+ -+define void @test_i64(i64* %dst, i64 %val) { -+; CHECK: ammax_db.du $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG3:[0-9]+]], 0 -+entry: -+ %a = atomicrmw umax i64* %dst, i64 %val monotonic -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll -new file mode 100644 -index 000000000..d5c3e0dad ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll -@@ -0,0 +1,809 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -mtriple=loongarch64 -o - %s | FileCheck %s -+ -+ -+define void @umax_8(i8* %ptr) { -+; CHECK-LABEL: umax_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: sltu $r13, $r14, $r5 -+; CHECK-NEXT: masknez $r11, $r14, $r13 -+; CHECK-NEXT: maskeqz $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB0_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umax i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @umax_16(i16* %ptr) { -+; CHECK-LABEL: umax_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB1_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: sltu $r13, $r14, $r5 -+; CHECK-NEXT: masknez $r11, $r14, $r13 -+; CHECK-NEXT: maskeqz $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB1_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umax i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+define void @max_8(i8* %ptr) { -+; CHECK-LABEL: max_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB2_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: slt $r13, $r14, $r5 -+; CHECK-NEXT: masknez $r11, $r14, $r13 -+; CHECK-NEXT: maskeqz $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB2_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw max i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @max_16(i16* %ptr) { -+; CHECK-LABEL: max_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB3_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: slt $r13, $r14, $r5 -+; CHECK-NEXT: masknez $r11, $r14, $r13 -+; CHECK-NEXT: maskeqz $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB3_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw max i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @umin_8(i8* %ptr) { -+; CHECK-LABEL: umin_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB4_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: sltu $r13, $r14, $r5 -+; CHECK-NEXT: maskeqz $r11, $r14, $r13 -+; CHECK-NEXT: masknez $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB4_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umin i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @umin_16(i16* %ptr) { -+; CHECK-LABEL: umin_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB5_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: sltu $r13, $r14, $r5 -+; CHECK-NEXT: maskeqz $r11, $r14, $r13 -+; CHECK-NEXT: masknez $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB5_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umin i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+define void @min_8(i8* %ptr) { -+; CHECK-LABEL: min_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB6_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: slt $r13, $r14, $r5 -+; CHECK-NEXT: maskeqz $r11, $r14, $r13 -+; CHECK-NEXT: masknez $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB6_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw min i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @min_16(i16* %ptr) { -+; CHECK-LABEL: min_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB7_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r14, $r10, $r7 -+; CHECK-NEXT: and $r5, $r5, $r7 -+; CHECK-NEXT: slt $r13, $r14, $r5 -+; CHECK-NEXT: maskeqz $r11, $r14, $r13 -+; CHECK-NEXT: masknez $r13, $r5, $r13 -+; CHECK-NEXT: or $r11, $r11, $r13 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB7_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw min i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @or_8(i8* %ptr) { -+; CHECK-LABEL: or_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB8_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: or $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB8_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw or i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @or_16(i16* %ptr) { -+; CHECK-LABEL: or_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB9_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: or $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB9_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw or i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @add_8(i8* %ptr) { -+; CHECK-LABEL: add_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB10_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: add.w $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB10_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw add i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @add_16(i16* %ptr) { -+; CHECK-LABEL: add_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB11_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: add.w $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB11_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw add i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @sub_8(i8* %ptr) { -+; CHECK-LABEL: sub_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: sub.w $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB12_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw sub i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @sub_16(i16* %ptr) { -+; CHECK-LABEL: sub_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB13_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: sub.w $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB13_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw sub i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @and_8(i8* %ptr) { -+; CHECK-LABEL: and_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB14_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB14_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw and i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @and_16(i16* %ptr) { -+; CHECK-LABEL: and_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB15_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB15_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw and i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @nand_8(i8* %ptr) { -+; CHECK-LABEL: nand_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB16_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r10, $r5 -+; CHECK-NEXT: nor $r11, $zero, $r11 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB16_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw nand i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @nand_16(i16* %ptr) { -+; CHECK-LABEL: nand_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB17_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r10, $r5 -+; CHECK-NEXT: nor $r11, $zero, $r11 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB17_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw nand i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @xor_8(i8* %ptr) { -+; CHECK-LABEL: xor_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB18_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: xor $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB18_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xor i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @xor_16(i16* %ptr) { -+; CHECK-LABEL: xor_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB19_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: xor $r11, $r10, $r5 -+; CHECK-NEXT: and $r11, $r11, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB19_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xor i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+ -+define void @xchg_8(i8* %ptr) { -+; CHECK-LABEL: xchg_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r7, $zero, 255 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB20_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r5, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB20_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.b $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xchg i8* %ptr, i8 100 seq_cst -+ ret void -+} -+ -+define void @xchg_16(i16* %ptr) { -+; CHECK-LABEL: xchg_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: addi.d $r6, $zero, -4 -+; CHECK-NEXT: and $r6, $r4, $r6 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r7, 15 -+; CHECK-NEXT: ori $r7, $r7, 4095 -+; CHECK-NEXT: sll.w $r7, $r7, $r4 -+; CHECK-NEXT: nor $r8, $zero, $r7 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB21_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r10, $r6, 0 -+; CHECK-NEXT: and $r11, $r5, $r7 -+; CHECK-NEXT: and $r12, $r10, $r8 -+; CHECK-NEXT: or $r12, $r12, $r11 -+; CHECK-NEXT: sc.w $r12, $r6, 0 -+; CHECK-NEXT: beq $r12, $zero, .LBB21_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: and $r9, $r10, $r7 -+; CHECK-NEXT: srl.w $r9, $r9, $r4 -+; CHECK-NEXT: ext.w.h $r9, $r9 -+; CHECK-NEXT: # %bb.3: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xchg i16* %ptr, i16 100 seq_cst -+ ret void -+} -+ -+define void @cmpxchg_8(i8* %ptr) { -+; CHECK-LABEL: cmpxchg_8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 1 -+; CHECK-NEXT: ori $r6, $zero, 100 -+; CHECK-NEXT: addi.d $r7, $zero, -4 -+; CHECK-NEXT: and $r7, $r4, $r7 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: ori $r8, $zero, 255 -+; CHECK-NEXT: sll.w $r8, $r8, $r4 -+; CHECK-NEXT: nor $r9, $zero, $r8 -+; CHECK-NEXT: andi $r6, $r6, 255 -+; CHECK-NEXT: sll.w $r6, $r6, $r4 -+; CHECK-NEXT: andi $r5, $r5, 255 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB22_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r11, $r7, 0 -+; CHECK-NEXT: and $r12, $r11, $r8 -+; CHECK-NEXT: bne $r12, $r6, .LBB22_3 -+; CHECK-NEXT: # %bb.2: # in Loop: Header=BB22_1 Depth=1 -+; CHECK-NEXT: and $r11, $r11, $r9 -+; CHECK-NEXT: or $r11, $r11, $r5 -+; CHECK-NEXT: sc.w $r11, $r7, 0 -+; CHECK-NEXT: beq $r11, $zero, .LBB22_1 -+; CHECK-NEXT: .LBB22_3: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: srl.w $r10, $r12, $r4 -+; CHECK-NEXT: ext.w.b $r10, $r10 -+; CHECK-NEXT: # %bb.4: -+; CHECK-NEXT: jr $ra -+ %ret = cmpxchg i8* %ptr, i8 100, i8 1 seq_cst seq_cst -+ ret void -+} -+ -+define void @cmpxchg_16(i16* %ptr) { -+; CHECK-LABEL: cmpxchg_16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 1 -+; CHECK-NEXT: ori $r6, $zero, 100 -+; CHECK-NEXT: addi.d $r7, $zero, -4 -+; CHECK-NEXT: and $r7, $r4, $r7 -+; CHECK-NEXT: andi $r4, $r4, 3 -+; CHECK-NEXT: slli.w $r4, $r4, 3 -+; CHECK-NEXT: lu12i.w $r8, 15 -+; CHECK-NEXT: ori $r8, $r8, 4095 -+; CHECK-NEXT: sll.w $r9, $r8, $r4 -+; CHECK-NEXT: nor $r10, $zero, $r9 -+; CHECK-NEXT: and $r6, $r6, $r8 -+; CHECK-NEXT: sll.w $r6, $r6, $r4 -+; CHECK-NEXT: and $r5, $r5, $r8 -+; CHECK-NEXT: sll.w $r5, $r5, $r4 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB23_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r11, $r7, 0 -+; CHECK-NEXT: and $r12, $r11, $r9 -+; CHECK-NEXT: bne $r12, $r6, .LBB23_3 -+; CHECK-NEXT: # %bb.2: # in Loop: Header=BB23_1 Depth=1 -+; CHECK-NEXT: and $r11, $r11, $r10 -+; CHECK-NEXT: or $r11, $r11, $r5 -+; CHECK-NEXT: sc.w $r11, $r7, 0 -+; CHECK-NEXT: beq $r11, $zero, .LBB23_1 -+; CHECK-NEXT: .LBB23_3: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: srl.w $r8, $r12, $r4 -+; CHECK-NEXT: ext.w.h $r8, $r8 -+; CHECK-NEXT: # %bb.4: -+; CHECK-NEXT: jr $ra -+ %ret = cmpxchg i16* %ptr, i16 100, i16 1 seq_cst seq_cst -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll -new file mode 100644 -index 000000000..ce400fd43 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll -@@ -0,0 +1,327 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -mtriple=loongarch64 -o - %s | FileCheck %s -+ -+ -+define void @umax_32(i32* %ptr) { -+; CHECK-LABEL: umax_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammax_db.wu $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umax i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @umax_64(i64* %ptr) { -+; CHECK-LABEL: umax_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB1_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammax_db.du $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umax i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+define void @max_32(i32* %ptr) { -+; CHECK-LABEL: max_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB2_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammax_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw max i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @max_64(i64* %ptr) { -+; CHECK-LABEL: max_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB3_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammax_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw max i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @umin_32(i32* %ptr) { -+; CHECK-LABEL: umin_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB4_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammin_db.wu $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umin i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @umin_64(i64* %ptr) { -+; CHECK-LABEL: umin_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB5_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammin_db.du $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw umin i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+define void @min_32(i32* %ptr) { -+; CHECK-LABEL: min_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB6_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammin_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw min i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @min_64(i64* %ptr) { -+; CHECK-LABEL: min_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB7_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ammin_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw min i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @or_32(i32* %ptr) { -+; CHECK-LABEL: or_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB8_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amor_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw or i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @or_64(i64* %ptr) { -+; CHECK-LABEL: or_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB9_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amor_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw or i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @add_32(i32* %ptr) { -+; CHECK-LABEL: add_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB10_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amadd_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw add i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @add_64(i64* %ptr) { -+; CHECK-LABEL: add_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB11_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amadd_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw add i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @sub_32(i32* %ptr) { -+; CHECK-LABEL: sub_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: sub.w $r7, $zero, $r5 -+; CHECK-NEXT: amadd_db.w $r6, $r7, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw sub i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @sub_64(i64* %ptr) { -+; CHECK-LABEL: sub_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB13_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: sub.d $r7, $zero, $r5 -+; CHECK-NEXT: amadd_db.d $r6, $r7, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw sub i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @and_32(i32* %ptr) { -+; CHECK-LABEL: and_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB14_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amand_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw and i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @and_64(i64* %ptr) { -+; CHECK-LABEL: and_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB15_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amand_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw and i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @nand_32(i32* %ptr) { -+; CHECK-LABEL: nand_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB16_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r6, $r4, 0 -+; CHECK-NEXT: and $r7, $r6, $r5 -+; CHECK-NEXT: nor $r7, $zero, $r7 -+; CHECK-NEXT: sc.w $r7, $r4, 0 -+; CHECK-NEXT: beq $r7, $zero, .LBB16_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw nand i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @nand_64(i64* %ptr) { -+; CHECK-LABEL: nand_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB17_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.d $r6, $r4, 0 -+; CHECK-NEXT: and $r7, $r6, $r5 -+; CHECK-NEXT: nor $r7, $zero, $r7 -+; CHECK-NEXT: sc.d $r7, $r4, 0 -+; CHECK-NEXT: beq $r7, $zero, .LBB17_1 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw nand i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @xor_32(i32* %ptr) { -+; CHECK-LABEL: xor_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB18_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amxor_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xor i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @xor_64(i64* %ptr) { -+; CHECK-LABEL: xor_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB19_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amxor_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xor i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+ -+define void @xchg_32(i32* %ptr) { -+; CHECK-LABEL: xchg_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 100 -+; CHECK-NEXT: .LBB20_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amswap_db.w $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xchg i32* %ptr, i32 100 seq_cst -+ ret void -+} -+ -+define void @xchg_64(i64* %ptr) { -+; CHECK-LABEL: xchg_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 100 -+; CHECK-NEXT: .LBB21_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: amswap_db.d $r6, $r5, $r4, 0 -+; CHECK-NEXT: # %bb.2: -+; CHECK-NEXT: jr $ra -+ %ret = atomicrmw xchg i64* %ptr, i64 100 seq_cst -+ ret void -+} -+ -+define void @cmpxchg_32(i32* %ptr) { -+; CHECK-LABEL: cmpxchg_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r5, $zero, 1 -+; CHECK-NEXT: ori $r6, $zero, 100 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB22_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.w $r7, $r4, 0 -+; CHECK-NEXT: bne $r7, $r6, .LBB22_3 -+; CHECK-NEXT: # %bb.2: # in Loop: Header=BB22_1 Depth=1 -+; CHECK-NEXT: move $r8, $r5 -+; CHECK-NEXT: sc.w $r8, $r4, 0 -+; CHECK-NEXT: beq $r8, $zero, .LBB22_1 -+; CHECK-NEXT: .LBB22_3: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: jr $ra -+ %ret = cmpxchg i32* %ptr, i32 100, i32 1 seq_cst seq_cst -+ ret void -+} -+ -+define void @cmpxchg_64(i64* %ptr) { -+; CHECK-LABEL: cmpxchg_64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r5, $zero, 1 -+; CHECK-NEXT: addi.d $r6, $zero, 100 -+; CHECK-NEXT: dbar 0 -+; CHECK-NEXT: .LBB23_1: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: ll.d $r7, $r4, 0 -+; CHECK-NEXT: bne $r7, $r6, .LBB23_3 -+; CHECK-NEXT: # %bb.2: # in Loop: Header=BB23_1 Depth=1 -+; CHECK-NEXT: move $r8, $r5 -+; CHECK-NEXT: sc.d $r8, $r4, 0 -+; CHECK-NEXT: beq $r8, $zero, .LBB23_1 -+; CHECK-NEXT: .LBB23_3: -+; CHECK-NEXT: dbar 1792 -+; CHECK-NEXT: jr $ra -+ %ret = cmpxchg i64* %ptr, i64 100, i64 1 seq_cst seq_cst -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll -new file mode 100644 -index 000000000..cfc30b3a7 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll -@@ -0,0 +1,5 @@ -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+; CHECK: .section .bss,"aw",@nobits -+; CHECK: .globl a -+@a = global i32 0, align 4 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll -new file mode 100644 -index 000000000..d6c8e72f2 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll -@@ -0,0 +1,752 @@ -+; Test the base intrinsics. -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define void @cpucfg() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %u32_a = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i32 @llvm.loongarch.cpucfg(i32 %0) -+ store i32 %1, i32* %u32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.cpucfg(i32) -+ -+; CHECK-LABEL: cpucfg: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: cpucfg $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @csrrd_w() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %0 = call i32 @llvm.loongarch.csrrd.w(i32 1) -+ store i32 %0, i32* %u32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.csrrd.w(i32) -+ -+; CHECK-LABEL: csrrd_w: -+; CHECK: csrrd $r[[REG:[0-9]+]], 1 -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @csrrd_d() { -+entry: -+ %u64_r = alloca i64, align 8 -+ %0 = call i64 @llvm.loongarch.csrrd.d(i64 1) -+ store i64 %0, i64* %u64_r, align 8 -+ ret void -+} -+ -+declare i64 @llvm.loongarch.csrrd.d(i64) -+ -+; CHECK-LABEL: csrrd_d: -+; CHECK: csrrd $r[[REG:[0-9]+]], 1 -+; CHECK: st.d $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @csrwr_w() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %u32_a = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i32 @llvm.loongarch.csrwr.w(i32 %0, i32 1) -+ store i32 %1, i32* %u32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.csrwr.w(i32, i32) -+ -+; CHECK-LABEL: csrwr_w: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: csrwr $r[[REG:[0-9]+]], 1 -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @csrwr_d() { -+entry: -+ %u64_r = alloca i64, align 8 -+ %u64_a = alloca i64, align 8 -+ %0 = load i64, i64* %u64_a, align 8 -+ %1 = call i64 @llvm.loongarch.csrwr.d(i64 %0, i64 1) -+ store i64 %1, i64* %u64_r, align 8 -+ ret void -+} -+ -+declare i64 @llvm.loongarch.csrwr.d(i64, i64) -+ -+; CHECK-LABEL: csrwr_d: -+; CHECK: ld.d $r[[REG:[0-9]+]], $sp, 0 -+; CHECK: csrwr $r[[REG:[0-9]+]], 1 -+; CHECK: st.d $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @csrxchg_w() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %u32_a = alloca i32, align 4 -+ %u32_b = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = load i32, i32* %u32_b, align 4 -+ %2 = call i32 @llvm.loongarch.csrxchg.w(i32 %0, i32 %1, i32 1) -+ store i32 %2, i32* %u32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.csrxchg.w(i32, i32, i32) -+ -+; CHECK-LABEL: csrxchg_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 -+; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: csrxchg $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], 1 -+; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @csrxchg_d() { -+entry: -+ %u64_r = alloca i64, align 8 -+ %u64_a = alloca i64, align 8 -+ %u64_b = alloca i64, align 8 -+ %0 = load i64, i64* %u64_a, align 8 -+ %1 = load i64, i64* %u64_b, align 8 -+ %2 = call i64 @llvm.loongarch.csrxchg.d(i64 %0, i64 %1, i64 1) -+ store i64 %2, i64* %u64_r, align 8 -+ ret void -+} -+ -+declare i64 @llvm.loongarch.csrxchg.d(i64, i64, i64) -+ -+; CHECK-LABEL: csrxchg_d: -+; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 16 -+; CHECK: csrxchg $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], 1 -+; CHECK: st.d $r[[REG1:[0-9]+]], $sp, 24 -+; CHECK: jr $ra -+; -+ -+define void @iocsrrd_b() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u8_r = alloca i8, align 1 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i32 @llvm.loongarch.iocsrrd.b(i32 %0) -+ %conv = trunc i32 %1 to i8 -+ store i8 %conv, i8* %u8_r, align 1 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.iocsrrd.b(i32) -+ -+; CHECK-LABEL: iocsrrd_b: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: iocsrrd.b $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: st.b $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @iocsrrd_h() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u16_r = alloca i16, align 2 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i32 @llvm.loongarch.iocsrrd.h(i32 %0) -+ %conv = trunc i32 %1 to i16 -+ store i16 %conv, i16* %u16_r, align 2 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.iocsrrd.h(i32) -+ -+; CHECK-LABEL: iocsrrd_h: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: iocsrrd.h $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: st.h $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @iocsrrd_w() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %u32_a = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i32 @llvm.loongarch.iocsrrd.w(i32 %0) -+ store i32 %1, i32* %u32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.iocsrrd.w(i32) -+ -+; CHECK-LABEL: iocsrrd_w: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: iocsrrd.w $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @iocsrrd_d() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u64_r = alloca i64, align 8 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = call i64 @llvm.loongarch.iocsrrd.d(i32 %0) -+ store i64 %1, i64* %u64_r, align 8 -+ ret void -+} -+ -+declare i64 @llvm.loongarch.iocsrrd.d(i32) -+ -+; CHECK-LABEL: iocsrrd_d: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: iocsrrd.d $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: st.d $r[[REG:[0-9]+]], $sp, 0 -+; CHECK: jr $ra -+; -+ -+define void @iocsrwr_b() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u8_a = alloca i8, align 1 -+ %0 = load i8, i8* %u8_a, align 1 -+ %conv = zext i8 %0 to i32 -+ %1 = load i32, i32* %u32_a, align 4 -+ call void @llvm.loongarch.iocsrwr.b(i32 %conv, i32 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.iocsrwr.b(i32, i32) -+ -+; CHECK-LABEL: iocsrwr_b: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 -+; CHECK: ld.bu $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: iocsrwr.b $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @iocsrwr_h() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u16_a = alloca i16, align 2 -+ %0 = load i16, i16* %u16_a, align 2 -+ %conv = zext i16 %0 to i32 -+ %1 = load i32, i32* %u32_a, align 4 -+ call void @llvm.loongarch.iocsrwr.h(i32 %conv, i32 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.iocsrwr.h(i32, i32) -+ -+; CHECK-LABEL: iocsrwr_h: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 -+; CHECK: ld.hu $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: iocsrwr.h $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @iocsrwr_w() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u32_b = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ %1 = load i32, i32* %u32_b, align 4 -+ call void @llvm.loongarch.iocsrwr.w(i32 %0, i32 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.iocsrwr.w(i32, i32) -+ -+; CHECK-LABEL: iocsrwr_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 12 -+; CHECK: iocsrwr.w $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @iocsrwr_d() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %u64_a = alloca i64, align 8 -+ %0 = load i64, i64* %u64_a, align 8 -+ %1 = load i32, i32* %u32_a, align 4 -+ call void @llvm.loongarch.iocsrwr.d(i64 %0, i32 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.iocsrwr.d(i64, i32) -+ -+; CHECK-LABEL: iocsrwr_d: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 -+; CHECK: iocsrwr.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @cacop_w() { -+entry: -+ %i32_a = alloca i32, align 4 -+ %0 = load i32, i32* %i32_a, align 4 -+ call void @llvm.loongarch.cacop.w(i32 1, i32 %0, i32 2) -+ ret void -+} -+ -+declare void @llvm.loongarch.cacop.w(i32, i32, i32) -+ -+; CHECK-LABEL: cacop_w: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: cacop 1, $r[[REG:[0-9]+]], 2 -+; CHECK: jr $ra -+; -+ -+define void @cacop_d() { -+entry: -+ %i64_a = alloca i64, align 8 -+ %0 = load i64, i64* %i64_a, align 8 -+ call void @llvm.loongarch.cacop.d(i32 1, i64 %0, i64 2) -+ ret void -+} -+ -+declare void @llvm.loongarch.cacop.d(i32, i64, i64) -+ -+; CHECK-LABEL: cacop_d: -+; CHECK: ld.d $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: cacop 1, $r[[REG:[0-9]+]], 2 -+; CHECK: jr $ra -+; -+ -+define void @rdtime_d() { -+entry: -+ %value = alloca i64, align 8 -+ %timeid = alloca i64, align 8 -+ %0 = call { i64, i64 } asm sideeffect "rdtime.d\09$0,$1\0A\09", "=&r,=&r"() nounwind -+ %asmresult0 = extractvalue { i64, i64 } %0, 0 -+ %asmresult1 = extractvalue { i64, i64 } %0, 1 -+ store i64 %asmresult0, i64* %value, align 8 -+ store i64 %asmresult1, i64* %timeid, align 8 -+ ret void -+} -+ -+; CHECK-LABEL: rdtime_d: -+; CHECK: rdtime.d $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] -+; CHECK: st.d $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: st.d $r[[REG1:[0-9]+]], $sp, 0 -+; CHECK: jr $ra -+; -+ -+define void @rdtimeh_w() { -+entry: -+ %value = alloca i32, align 4 -+ %timeid = alloca i32, align 4 -+ %0 = call { i32, i32 } asm sideeffect "rdtimeh.w\09$0,$1\0A\09", "=&r,=&r"() nounwind -+ %asmresult0 = extractvalue { i32, i32 } %0, 0 -+ %asmresult1 = extractvalue { i32, i32 } %0, 1 -+ store i32 %asmresult0, i32* %value, align 4 -+ store i32 %asmresult1, i32* %timeid, align 4 -+ ret void -+} -+ -+; CHECK-LABEL: rdtimeh_w: -+; CHECK: rdtimeh.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] -+; CHECK: st.w $r[[REG2:[0-9]+]], $sp, 12 -+; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @rdtimel_w() { -+entry: -+ %value = alloca i32, align 4 -+ %timeid = alloca i32, align 4 -+ %0 = call { i32, i32 } asm sideeffect "rdtimel.w\09$0,$1\0A\09", "=&r,=&r"() nounwind -+ %asmresult0 = extractvalue { i32, i32 } %0, 0 -+ %asmresult1 = extractvalue { i32, i32 } %0, 1 -+ store i32 %asmresult0, i32* %value, align 4 -+ store i32 %asmresult1, i32* %timeid, align 4 -+ ret void -+} -+ -+; CHECK-LABEL: rdtimel_w: -+; CHECK: rdtimel.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] -+; CHECK: st.w $r[[REG2:[0-9]+]], $sp, 12 -+; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: jr $ra -+; -+ -+define void @crc_w_b_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i8_a = alloca i8, align 1 -+ %0 = load i8, i8* %i8_a, align 1 -+ %conv = sext i8 %0 to i32 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crc.w.b.w(i32 %conv, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) -+ -+; CHECK-LABEL: crc_w_b_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.b $r[[REG2:[0-9]+]], $sp, 4 -+; CHECK: crc.w.b.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crc_w_h_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i16_a = alloca i16, align 2 -+ %0 = load i16, i16* %i16_a, align 2 -+ %conv = sext i16 %0 to i32 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crc.w.h.w(i32 %conv, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crc.w.h.w(i32, i32) -+ -+; CHECK-LABEL: crc_w_h_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.h $r[[REG2:[0-9]+]], $sp, 4 -+; CHECK: crc.w.h.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crc_w_w_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i32_b = alloca i32, align 4 -+ %0 = load i32, i32* %i32_a, align 4 -+ %1 = load i32, i32* %i32_b, align 4 -+ %2 = call i32 @llvm.loongarch.crc.w.w.w(i32 %0, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crc.w.w.w(i32, i32) -+ -+; CHECK-LABEL: crc_w_w_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 -+; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: crc.w.w.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crc_w_d_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i64_a = alloca i64, align 8 -+ %0 = load i64, i64* %i64_a, align 8 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crc.w.d.w(i64 %0, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crc.w.d.w(i64, i32) -+ -+; CHECK-LABEL: crc_w_d_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 -+; CHECK: crc.w.d.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crcc_w_b_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i8_a = alloca i8, align 1 -+ %0 = load i8, i8* %i8_a, align 1 -+ %conv = sext i8 %0 to i32 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crcc.w.b.w(i32 %conv, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crcc.w.b.w(i32, i32) -+ -+; CHECK-LABEL: crcc_w_b_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.b $r[[REG2:[0-9]+]], $sp, 4 -+; CHECK: crcc.w.b.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crcc_w_h_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i16_a = alloca i16, align 2 -+ %0 = load i16, i16* %i16_a, align 2 -+ %conv = sext i16 %0 to i32 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crcc.w.h.w(i32 %conv, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crcc.w.h.w(i32, i32) -+ -+; CHECK-LABEL: crcc_w_h_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.h $r[[REG2:[0-9]+]], $sp, 4 -+; CHECK: crcc.w.h.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crcc_w_w_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i32_b = alloca i32, align 4 -+ %0 = load i32, i32* %i32_a, align 4 -+ %1 = load i32, i32* %i32_b, align 4 -+ %2 = call i32 @llvm.loongarch.crcc.w.w.w(i32 %0, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crcc.w.w.w(i32, i32) -+ -+; CHECK-LABEL: crcc_w_w_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 -+; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: crcc.w.w.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @crcc_w_d_w() { -+entry: -+ %i32_r = alloca i32, align 4 -+ %i32_a = alloca i32, align 4 -+ %i64_a = alloca i64, align 8 -+ %0 = load i64, i64* %i64_a, align 8 -+ %1 = load i32, i32* %i32_a, align 4 -+ %2 = call i32 @llvm.loongarch.crcc.w.d.w(i64 %0, i32 %1) -+ store i32 %2, i32* %i32_r, align 4 -+ ret void -+} -+ -+declare i32 @llvm.loongarch.crcc.w.d.w(i64, i32) -+ -+; CHECK-LABEL: crcc_w_d_w: -+; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 -+; CHECK: crcc.w.d.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @tlbclr() { -+entry: -+ call void @llvm.loongarch.tlbclr() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbclr() -+ -+; CHECK-LABEL: tlbclr: -+; CHECK: tlbclr -+; CHECK: jr $ra -+; -+ -+define void @tlbflush() { -+entry: -+ call void @llvm.loongarch.tlbflush() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbflush() -+ -+; CHECK-LABEL: tlbflush: -+; CHECK: tlbflush -+; CHECK: jr $ra -+; -+ -+define void @tlbfill() { -+entry: -+ call void @llvm.loongarch.tlbfill() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbfill() -+ -+; CHECK-LABEL: tlbfill: -+; CHECK: tlbfill -+; CHECK: jr $ra -+; -+ -+define void @tlbrd() { -+entry: -+ call void @llvm.loongarch.tlbrd() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbrd() -+ -+; CHECK-LABEL: tlbrd: -+; CHECK: tlbrd -+; CHECK: jr $ra -+; -+ -+define void @tlbwr() { -+entry: -+ call void @llvm.loongarch.tlbwr() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbwr() -+ -+; CHECK-LABEL: tlbwr: -+; CHECK: tlbwr -+; CHECK: jr $ra -+; -+ -+define void @tlbsrch() { -+entry: -+ call void @llvm.loongarch.tlbsrch() -+ ret void -+} -+ -+declare void @llvm.loongarch.tlbsrch() -+ -+; CHECK-LABEL: tlbsrch: -+; CHECK: tlbsrch -+; CHECK: jr $ra -+; -+ -+define void @syscall() { -+entry: -+ call void @llvm.loongarch.syscall(i64 1) -+ ret void -+} -+ -+declare void @llvm.loongarch.syscall(i64) -+ -+; CHECK-LABEL: syscall: -+; CHECK: syscall 1 -+; CHECK: jr $ra -+; -+ -+define void @break_builtin() { -+entry: -+ call void @llvm.loongarch.break(i64 1) -+ ret void -+} -+ -+declare void @llvm.loongarch.break(i64) -+ -+; CHECK-LABEL: break_builtin: -+; CHECK: break 1 -+; CHECK: jr $ra -+; -+ -+define void @asrtle_d() { -+entry: -+ %i64_a = alloca i64, align 8 -+ %i64_b = alloca i64, align 8 -+ %0 = load i64, i64* %i64_a, align 8 -+ %1 = load i64, i64* %i64_b, align 8 -+ call void @llvm.loongarch.asrtle.d(i64 %0, i64 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.asrtle.d(i64, i64) -+ -+; CHECK-LABEL: asrtle_d: -+; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 0 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: asrtle.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @asrtgt_d() { -+entry: -+ %i64_a = alloca i64, align 8 -+ %i64_b = alloca i64, align 8 -+ %0 = load i64, i64* %i64_a, align 8 -+ %1 = load i64, i64* %i64_b, align 8 -+ call void @llvm.loongarch.asrtgt.d(i64 %0, i64 %1) -+ ret void -+} -+ -+declare void @llvm.loongarch.asrtgt.d(i64, i64) -+ -+; CHECK-LABEL: asrtgt_d: -+; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 0 -+; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 8 -+; CHECK: asrtgt.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] -+; CHECK: jr $ra -+; -+ -+define void @dbar() { -+entry: -+ call void @llvm.loongarch.dbar(i64 0) -+ ret void -+} -+ -+declare void @llvm.loongarch.dbar(i64) -+ -+; CHECK-LABEL: dbar: -+; CHECK: dbar 0 -+; CHECK: jr $ra -+; -+ -+define void @ibar() { -+entry: -+ call void @llvm.loongarch.ibar(i64 0) -+ ret void -+} -+ -+declare void @llvm.loongarch.ibar(i64) -+ -+; CHECK-LABEL: ibar: -+; CHECK: ibar 0 -+; CHECK: jr $ra -+; -+ -+define void @movfcsr2gr() { -+entry: -+ %u32_r = alloca i32, align 4 -+ %rd = alloca i32, align 4 -+ %0 = call i32 asm sideeffect "movfcsr2gr $0, $$fcsr0", "=&r"() -+ store i32 %0, i32* %rd, align 4 -+ %1 = load i32, i32* %rd, align 4 -+ store i32 %1, i32* %u32_r, align 4 -+ ret void -+} -+ -+; CHECK-LABEL: movfcsr2gr: -+; CHECK: movfcsr2gr $r[[REG:[0-9]+]], $fcsr[[REG:[0-9]+]] -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 8 -+; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: jr $ra -+; -+ -+define void @movgr2fcsr() { -+entry: -+ %u32_a = alloca i32, align 4 -+ %0 = load i32, i32* %u32_a, align 4 -+ call void asm sideeffect "movgr2fcsr $$fcsr0, $0", "r"(i32 %0) -+ ret void -+} -+ -+; CHECK-LABEL: movgr2fcsr: -+; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 -+; CHECK: movgr2fcsr $fcsr[[REG:[0-9]+]], $r[[REG:[0-9]+]] -+; CHECK: jr $ra -+; -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll -new file mode 100644 -index 000000000..955e16268 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll -@@ -0,0 +1,245 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -mtriple=loongarch64-linux-gnu < %s | FileCheck %s -+ -+ -+; This test is copied from Mips except the mul2730_32 and mul2730_64 -+ -+define i32 @mul5_32(i32 signext %a) { -+; CHECK-LABEL: mul5_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: alsl.w $r4, $r4, $r4, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i32 %a, 5 -+ ret i32 %mul -+} -+ -+define i32 @mul27_32(i32 signext %a) { -+; CHECK-LABEL: mul27_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: alsl.w $r5, $r4, $r4, 2 -+; CHECK-NEXT: slli.w $r4, $r4, 5 -+; CHECK-NEXT: sub.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i32 %a, 27 -+ ret i32 %mul -+} -+ -+define i32 @muln2147483643_32(i32 signext %a) { -+; CHECK-LABEL: muln2147483643_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: alsl.w $r5, $r4, $r4, 2 -+; CHECK-NEXT: slli.w $r4, $r4, 31 -+; CHECK-NEXT: add.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i32 %a, -2147483643 -+ ret i32 %mul -+} -+ -+define i64 @muln9223372036854775805_64(i64 signext %a) { -+; CHECK-LABEL: muln9223372036854775805_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: alsl.d $r5, $r4, $r4, 1 -+; CHECK-NEXT: slli.d $r4, $r4, 63 -+; CHECK-NEXT: add.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i64 %a, -9223372036854775805 -+ ret i64 %mul -+} -+ -+define i128 @muln170141183460469231731687303715884105725_128(i128 signext %a) { -+; CHECK-LABEL: muln170141183460469231731687303715884105725_128: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: srli.d $r6, $r4, 63 -+; CHECK-NEXT: slli.d $r7, $r5, 1 -+; CHECK-NEXT: or $r6, $r7, $r6 -+; CHECK-NEXT: add.d $r5, $r6, $r5 -+; CHECK-NEXT: slli.d $r7, $r4, 1 -+; CHECK-NEXT: alsl.d $r6, $r4, $r4, 1 -+; CHECK-NEXT: sltu $r7, $r6, $r7 -+; CHECK-NEXT: bstrpick.d $r7, $r7, 31, 0 -+; CHECK-NEXT: add.d $r5, $r5, $r7 -+; CHECK-NEXT: slli.d $r4, $r4, 63 -+; CHECK-NEXT: add.d $r5, $r4, $r5 -+; CHECK-NEXT: move $r4, $r6 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i128 %a, -170141183460469231731687303715884105725 -+ ret i128 %mul -+} -+ -+define i128 @mul170141183460469231731687303715884105723_128(i128 signext %a) { -+; CHECK-LABEL: mul170141183460469231731687303715884105723_128: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: srli.d $r6, $r4, 62 -+; CHECK-NEXT: slli.d $r7, $r5, 2 -+; CHECK-NEXT: or $r6, $r7, $r6 -+; CHECK-NEXT: add.d $r5, $r6, $r5 -+; CHECK-NEXT: slli.d $r6, $r4, 2 -+; CHECK-NEXT: alsl.d $r7, $r4, $r4, 2 -+; CHECK-NEXT: sltu $r6, $r7, $r6 -+; CHECK-NEXT: bstrpick.d $r6, $r6, 31, 0 -+; CHECK-NEXT: add.d $r5, $r5, $r6 -+; CHECK-NEXT: slli.d $r4, $r4, 63 -+; CHECK-NEXT: sub.d $r4, $r4, $r5 -+; CHECK-NEXT: sltu $r5, $zero, $r7 -+; CHECK-NEXT: bstrpick.d $r5, $r5, 31, 0 -+; CHECK-NEXT: sub.d $r5, $r4, $r5 -+; CHECK-NEXT: addi.d $r4, $zero, 0 -+; CHECK-NEXT: sub.d $r4, $r4, $r7 -+; CHECK-NEXT: jr $ra -+entry: -+ %mul = mul nsw i128 %a, 170141183460469231731687303715884105723 -+ ret i128 %mul -+} -+ -+define i32 @mul42949673_32(i32 %a) { -+; CHECK-LABEL: mul42949673_32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r5, 10485 -+; CHECK-NEXT: ori $r5, $r5, 3113 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+ %b = mul i32 %a, 42949673 -+ ret i32 %b -+} -+ -+define i64 @mul42949673_64(i64 %a) { -+; CHECK-LABEL: mul42949673_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 10485 -+; CHECK-NEXT: ori $r5, $r5, 3113 -+; CHECK-NEXT: mul.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 42949673 -+ ret i64 %b -+} -+ -+define i32 @mul22224078_32(i32 %a) { -+; CHECK-LABEL: mul22224078_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5425 -+; CHECK-NEXT: ori $r5, $r5, 3278 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i32 %a, 22224078 -+ ret i32 %b -+} -+ -+define i64 @mul22224078_64(i64 %a) { -+; CHECK-LABEL: mul22224078_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5425 -+; CHECK-NEXT: ori $r5, $r5, 3278 -+; CHECK-NEXT: mul.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 22224078 -+ ret i64 %b -+} -+ -+define i32 @mul22245375_32(i32 %a) { -+; CHECK-LABEL: mul22245375_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5430 -+; CHECK-NEXT: ori $r5, $r5, 4095 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i32 %a, 22245375 -+ ret i32 %b -+} -+ -+define i64 @mul22245375_64(i64 %a) { -+; CHECK-LABEL: mul22245375_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5430 -+; CHECK-NEXT: ori $r5, $r5, 4095 -+; CHECK-NEXT: mul.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 22245375 -+ ret i64 %b -+} -+ -+define i32 @mul25165824_32(i32 %a) { -+; CHECK-LABEL: mul25165824_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5430 -+; CHECK-NEXT: ori $r5, $r5, 4095 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i32 %a, 22245375 -+ ret i32 %b -+} -+ -+define i64 @mul25165824_64(i64 %a) { -+; CHECK-LABEL: mul25165824_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.d $r5, $r4, 23 -+; CHECK-NEXT: slli.d $r4, $r4, 24 -+; CHECK-NEXT: add.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 25165824 -+ ret i64 %b -+} -+ -+define i32 @mul33554432_32(i32 %a) { -+; CHECK-LABEL: mul33554432_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r5, 5430 -+; CHECK-NEXT: ori $r5, $r5, 4095 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i32 %a, 22245375 -+ ret i32 %b -+} -+ -+define i64 @mul33554432_64(i64 %a) { -+; CHECK-LABEL: mul33554432_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.d $r4, $r4, 25 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 33554432 -+ ret i64 %b -+} -+ -+define i32 @mul2730_32(i32 %a) { -+; CHECK-LABEL: mul2730_32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: ori $r5, $zero, 2730 -+; CHECK-NEXT: mul.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i32 %a, 2730 -+ ret i32 %b -+} -+ -+define i64 @mul2730_64(i64 %a) { -+; CHECK-LABEL: mul2730_64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ori $r5, $zero, 2730 -+; CHECK-NEXT: mul.d $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = mul i64 %a, 2730 -+ ret i64 %b -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll -new file mode 100644 -index 000000000..586daca23 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll -@@ -0,0 +1,94 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s \ -+; RUN: | FileCheck %s --check-prefixes=CHECK1 -+; RUN: llc -march=loongarch64 -relocation-model=pic -disable-tail-calls < %s \ -+; RUN: | FileCheck %s --check-prefixes=CHECK2 -+; RUN: llc -march=loongarch64 -relocation-model=pic -disable-tail-calls=false < %s \ -+; RUN: | FileCheck %s --check-prefixes=CHECK3 -+ -+; Function with attribute #0 = { "disable-tail-calls"="true" } -+define i32 @caller1(i32 %a) #0 { -+; CHECK1-LABEL: caller1: -+; CHECK1: # %bb.0: # %entry -+; CHECK1-NEXT: addi.d $sp, $sp, -16 -+; CHECK1-NEXT: .cfi_def_cfa_offset 16 -+; CHECK1-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK1-NEXT: .cfi_offset 1, -8 -+; CHECK1-NEXT: bl callee -+; CHECK1-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK1-NEXT: addi.d $sp, $sp, 16 -+; CHECK1-NEXT: jr $ra -+; -+; CHECK2-LABEL: caller1: -+; CHECK2: # %bb.0: # %entry -+; CHECK2-NEXT: addi.d $sp, $sp, -16 -+; CHECK2-NEXT: .cfi_def_cfa_offset 16 -+; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK2-NEXT: .cfi_offset 1, -8 -+; CHECK2-NEXT: bl callee -+; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK2-NEXT: addi.d $sp, $sp, 16 -+; CHECK2-NEXT: jr $ra -+; -+; CHECK3-LABEL: caller1: -+; CHECK3: # %bb.0: # %entry -+; CHECK3-NEXT: b callee -+entry: -+ %call = tail call i32 @callee(i32 %a) -+ ret i32 %call -+} -+ -+ -+; Function with attribute #1 = { "disable-tail-calls"="false" } -+define i32 @caller2(i32 %a) #1 { -+; CHECK1-LABEL: caller2: -+; CHECK1: # %bb.0: # %entry -+; CHECK1-NEXT: b callee -+; -+; CHECK2-LABEL: caller2: -+; CHECK2: # %bb.0: # %entry -+; CHECK2-NEXT: addi.d $sp, $sp, -16 -+; CHECK2-NEXT: .cfi_def_cfa_offset 16 -+; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK2-NEXT: .cfi_offset 1, -8 -+; CHECK2-NEXT: bl callee -+; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK2-NEXT: addi.d $sp, $sp, 16 -+; CHECK2-NEXT: jr $ra -+; -+; CHECK3-LABEL: caller2: -+; CHECK3: # %bb.0: # %entry -+; CHECK3-NEXT: b callee -+entry: -+ %call = tail call i32 @callee(i32 %a) -+ ret i32 %call -+} -+ -+define i32 @caller3(i32 %a) { -+; CHECK1-LABEL: caller3: -+; CHECK1: # %bb.0: # %entry -+; CHECK1-NEXT: b callee -+; -+; CHECK2-LABEL: caller3: -+; CHECK2: # %bb.0: # %entry -+; CHECK2-NEXT: addi.d $sp, $sp, -16 -+; CHECK2-NEXT: .cfi_def_cfa_offset 16 -+; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK2-NEXT: .cfi_offset 1, -8 -+; CHECK2-NEXT: bl callee -+; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK2-NEXT: addi.d $sp, $sp, 16 -+; CHECK2-NEXT: jr $ra -+; -+; CHECK3-LABEL: caller3: -+; CHECK3: # %bb.0: # %entry -+; CHECK3-NEXT: b callee -+entry: -+ %call = tail call i32 @callee(i32 %a) -+ ret i32 %call -+} -+ -+declare i32 @callee(i32) -+ -+attributes #0 = { "disable-tail-calls"="true" } -+attributes #1 = { "disable-tail-calls"="false" } -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll -new file mode 100644 -index 000000000..34293a83c ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll -@@ -0,0 +1,68 @@ -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -check-prefixes=CHECK,CHECK-TRAP -+ -+; RUN: llc -march=loongarch64 -mnocheck-zero-division -relocation-model=pic < %s | FileCheck %s -check-prefixes=CHECK,NOCHECK -+ -+; FileCheck Prefixes: -+; CHECK-TRAP - trap -+; NOCHECK - Division by zero will not be detected -+ -+define i32 @sdiv1(i32 signext %a0, i32 signext %a1) nounwind readnone { -+entry: -+; CHECK-LABEL: sdiv1: -+ -+; CHECK: div.w $r4, $r4, $r5 -+; CHECK-TRAP: bne $r5, $zero, 8 -+; CHECK-TRAP: break 7 -+ -+; NOCHECK-NOT: bne -+; NOCHECK-NOT: break -+ -+ %div = sdiv i32 %a0, %a1 -+ ret i32 %div -+} -+ -+define i32 @srem1(i32 signext %a0, i32 signext %a1) nounwind readnone { -+entry: -+; CHECK-LABEL: srem1: -+ -+; CHECK: mod.w $r4, $r4, $r5 -+; CHECK-TRAP: bne $r5, $zero, 8 -+; CHECK-TRAP: break 7 -+ -+; NOCHECK-NOT: bne -+; NOCHECK-NOT: break -+ -+ %rem = srem i32 %a0, %a1 -+ ret i32 %rem -+} -+ -+define i32 @udiv1(i32 signext %a0, i32 signext %a1) nounwind readnone { -+entry: -+; CHECK-LABEL: udiv1: -+ -+; CHECK: div.wu $r4, $r4, $r5 -+; CHECK-TRAP: bne $r5, $zero, 8 -+; CHECK-TRAP: break 7 -+ -+; NOCHECK-NOT: bne -+; NOCHECK-NOT: break -+ -+ %div = udiv i32 %a0, %a1 -+ ret i32 %div -+} -+ -+define i32 @urem1(i32 signext %a0, i32 signext %a1) nounwind readnone { -+entry: -+; CHECK-LABEL: urem1: -+ -+ -+; CHECK: mod.wu $r4, $r4, $r5 -+; CHECK-TRAP: bne $r5, $zero, 8 -+; CHECK-TRAP: break 7 -+ -+; NOCHECK-NOT: bne -+; NOCHECK-NOT: break -+ -+ %rem = urem i32 %a0, %a1 -+ ret i32 %rem -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll -new file mode 100644 -index 000000000..cad67e98c ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll -@@ -0,0 +1,45 @@ -+; RUN: llc --mtriple=loongarch64 --relocation-model=pic -o - %s | FileCheck %s -+ -+;; Duplicate returns to enable tail call optimizations. -+declare i32 @test() -+declare i32 @test1() -+declare i32 @test2() -+declare i32 @test3() -+define i32 @duplicate_returns(i32 %a, i32 %b) nounwind { -+; CHECK-LABEL: duplicate_returns: -+; CHECK: b test2 -+; CHECK: b test -+; CHECK: b test1 -+; CHECK: b test3 -+entry: -+ %cmp = icmp eq i32 %a, 0 -+ br i1 %cmp, label %if.then, label %if.else -+ -+if.then: ; preds = %entry -+ %call = tail call i32 @test() -+ br label %return -+ -+if.else: ; preds = %entry -+ %cmp1 = icmp eq i32 %b, 0 -+ br i1 %cmp1, label %if.then2, label %if.else4 -+ -+if.then2: ; preds = %if.else -+ %call3 = tail call i32 @test1() -+ br label %return -+ -+if.else4: ; preds = %if.else -+ %cmp5 = icmp sgt i32 %a, %b -+ br i1 %cmp5, label %if.then6, label %if.else8 -+ -+if.then6: ; preds = %if.else4 -+ %call7 = tail call i32 @test2() -+ br label %return -+ -+if.else8: ; preds = %if.else4 -+ %call9 = tail call i32 @test3() -+ br label %return -+ -+return: ; preds = %if.else8, %if.then6, %if.then2, %if.then -+ %retval = phi i32 [ %call, %if.then ], [ %call3, %if.then2 ], [ %call7, %if.then6 ], [ %call9, %if.else8 ] -+ ret i32 %retval -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll -new file mode 100644 -index 000000000..0272c95bd ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll -@@ -0,0 +1,106 @@ -+; Check whether LoongArchSERegisterInfo::eliminateFI works well -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define signext i32 @ldptr_w_unaligned() { -+; CHECK-LABEL: ldptr_w_unaligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 -+ %0 = bitcast i8* %arrayidx to i32* -+; the offset MUST be 0 -+; CHECK: ldptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, 0 -+ %1 = load i32, i32* %0, align 1 -+ ret i32 %1 -+} -+ -+define signext i32 @ldptr_w_aligned() { -+; CHECK-LABEL: ldptr_w_aligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 -+ %0 = bitcast i8* %arrayidx to i32* -+; the offset may not be 0, but MUST be 4-bytes aligned -+; CHECK: ldptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} -+ %1 = load i32, i32* %0, align 1 -+ ret i32 %1 -+} -+ -+define signext i64 @ldptr_d_unaligned() { -+; CHECK-LABEL: ldptr_d_unaligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 -+ %0 = bitcast i8* %arrayidx to i64* -+; the offset MUST be 0 -+; CHECK: ldptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, 0 -+ %1 = load i64, i64* %0, align 1 -+ ret i64 %1 -+} -+ -+define signext i64 @ldptr_d_aligned() { -+; CHECK-LABEL: ldptr_d_aligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 -+ %0 = bitcast i8* %arrayidx to i64* -+; the offset may not be 0, but MUST be 4-bytes aligned -+; CHECK: ldptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} -+ %1 = load i64, i64* %0, align 1 -+ ret i64 %1 -+} -+ -+define void @stptr_w_unaligned(i32 signext %val) { -+; CHECK-LABEL: stptr_w_unaligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 -+ %0 = bitcast i8* %arrayidx to i32* -+; the offset MUST be 0 -+; CHECK: stptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, 0 -+ store i32 %val, i32* %0, align 1 -+ ret void -+} -+ -+define void @stptr_w_aligned(i32 signext %val) { -+; CHECK-LABEL: stptr_w_aligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 -+ %0 = bitcast i8* %arrayidx to i32* -+; the offset may not be 0, but MUST be 4-bytes aligned -+; CHECK: stptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} -+ store i32 %val, i32* %0, align 1 -+ ret void -+} -+ -+define void @stptr_d_unaligned(i64 %val) { -+; CHECK-LABEL: stptr_d_unaligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 -+ %0 = bitcast i8* %arrayidx to i64* -+; the offset MUST be 0 -+; CHECK: stptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, 0 -+ store i64 %val, i64* %0, align 1 -+ ret void -+} -+ -+define void @stptr_d_aligned(i64 %val) { -+; CHECK-LABEL: stptr_d_aligned: -+; CHECK: # %bb.0: # %entry -+entry: -+ %array = alloca [6000 x i8], align 1 -+ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 -+ %0 = bitcast i8* %arrayidx to i64* -+; the offset may not be 0, but MUST be 4-bytes aligned -+; CHECK: stptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} -+ store i64 %val, i64* %0, align 1 -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll -new file mode 100644 -index 000000000..80fa7a855 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll -@@ -0,0 +1,103 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc --mtriple=loongarch64 -O0 < %s | FileCheck %s -+ -+@var = external global i32 -+ -+define void @func() { -+; CHECK-LABEL: func: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $sp, $sp, -2048 -+; CHECK-NEXT: addi.d $sp, $sp, -2048 -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 4112 -+; CHECK-NEXT: lu12i.w $r5, var -+; CHECK-NEXT: ori $r5, $r5, var -+; CHECK-NEXT: lu32i.d $r5, var -+; CHECK-NEXT: lu52i.d $r5, $r5, var -+; CHECK-NEXT: ld.w $r20, $r5, 0 -+; CHECK-NEXT: ld.w $r19, $r5, 0 -+; CHECK-NEXT: ld.w $r18, $r5, 0 -+; CHECK-NEXT: ld.w $r17, $r5, 0 -+; CHECK-NEXT: ld.w $r16, $r5, 0 -+; CHECK-NEXT: ld.w $r15, $r5, 0 -+; CHECK-NEXT: ld.w $r14, $r5, 0 -+; CHECK-NEXT: ld.w $r13, $r5, 0 -+; CHECK-NEXT: ld.w $r12, $r5, 0 -+; CHECK-NEXT: ld.w $r11, $r5, 0 -+; CHECK-NEXT: ld.w $r10, $r5, 0 -+; CHECK-NEXT: ld.w $r9, $r5, 0 -+; CHECK-NEXT: ld.w $r8, $r5, 0 -+; CHECK-NEXT: ld.w $r7, $r5, 0 -+; CHECK-NEXT: ld.w $r6, $r5, 0 -+; CHECK-NEXT: ld.w $r4, $r5, 0 -+; CHECK-NEXT: st.d $r23, $sp, 0 -+; CHECK-NEXT: lu12i.w $r23, 1 -+; CHECK-NEXT: ori $r23, $r23, 12 -+; CHECK-NEXT: add.d $r23, $sp, $r23 -+; CHECK-NEXT: st.w $r20, $r23, 0 -+; CHECK-NEXT: ld.d $r23, $sp, 0 -+; CHECK-NEXT: st.w $r20, $r5, 0 -+; CHECK-NEXT: st.w $r19, $r5, 0 -+; CHECK-NEXT: st.w $r18, $r5, 0 -+; CHECK-NEXT: st.w $r17, $r5, 0 -+; CHECK-NEXT: st.w $r16, $r5, 0 -+; CHECK-NEXT: st.w $r15, $r5, 0 -+; CHECK-NEXT: st.w $r14, $r5, 0 -+; CHECK-NEXT: st.w $r13, $r5, 0 -+; CHECK-NEXT: st.w $r12, $r5, 0 -+; CHECK-NEXT: st.w $r11, $r5, 0 -+; CHECK-NEXT: st.w $r10, $r5, 0 -+; CHECK-NEXT: st.w $r9, $r5, 0 -+; CHECK-NEXT: st.w $r8, $r5, 0 -+; CHECK-NEXT: st.w $r7, $r5, 0 -+; CHECK-NEXT: st.w $r6, $r5, 0 -+; CHECK-NEXT: st.w $r4, $r5, 0 -+; CHECK-NEXT: lu12i.w $r4, 1 -+; CHECK-NEXT: ori $r4, $r4, 16 -+; CHECK-NEXT: add.d $sp, $sp, $r4 -+; CHECK-NEXT: jr $ra -+ %space = alloca i32, align 4 -+ %stackspace = alloca[1024 x i32], align 4 -+ -+ ;; Load values to increase register pressure. -+ %v0 = load volatile i32, i32* @var -+ %v1 = load volatile i32, i32* @var -+ %v2 = load volatile i32, i32* @var -+ %v3 = load volatile i32, i32* @var -+ %v4 = load volatile i32, i32* @var -+ %v5 = load volatile i32, i32* @var -+ %v6 = load volatile i32, i32* @var -+ %v7 = load volatile i32, i32* @var -+ %v8 = load volatile i32, i32* @var -+ %v9 = load volatile i32, i32* @var -+ %v10 = load volatile i32, i32* @var -+ %v11 = load volatile i32, i32* @var -+ %v12 = load volatile i32, i32* @var -+ %v13 = load volatile i32, i32* @var -+ %v14 = load volatile i32, i32* @var -+ %v15 = load volatile i32, i32* @var -+ -+ ;; Computing a stack-relative values needs an additional register. -+ ;; We should get an emergency spill/reload for this. -+ store volatile i32 %v0, i32* %space -+ -+ ;; store values so they are used. -+ store volatile i32 %v0, i32* @var -+ store volatile i32 %v1, i32* @var -+ store volatile i32 %v2, i32* @var -+ store volatile i32 %v3, i32* @var -+ store volatile i32 %v4, i32* @var -+ store volatile i32 %v5, i32* @var -+ store volatile i32 %v6, i32* @var -+ store volatile i32 %v7, i32* @var -+ store volatile i32 %v8, i32* @var -+ store volatile i32 %v9, i32* @var -+ store volatile i32 %v10, i32* @var -+ store volatile i32 %v11, i32* @var -+ store volatile i32 %v12, i32* @var -+ store volatile i32 %v13, i32* @var -+ store volatile i32 %v14, i32* @var -+ store volatile i32 %v15, i32* @var -+ -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll -new file mode 100644 -index 000000000..c16413715 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll -@@ -0,0 +1,17 @@ -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define float @fcopysign_s(float %a, float %b) { -+; CHECK-LABEL: fcopysign_s: -+; CHECK: fcopysign.s $f0, $f0, $f1 -+ %ret = call float @llvm.copysign.f32(float %a, float %b) -+ ret float %ret -+} -+declare float @llvm.copysign.f32(float %a, float %b) -+ -+define double @fcopysign_d(double %a, double %b) { -+; CHECK-LABEL: fcopysign_d: -+; CHECK: fcopysign.d $f0, $f0, $f1 -+ %ret = call double @llvm.copysign.f64(double %a, double %b) -+ ret double %ret -+} -+declare double @llvm.copysign.f64(double %a, double %b) -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll -new file mode 100644 -index 000000000..eb4fc69fa ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll -@@ -0,0 +1,132 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -relocation-model=pic -mtriple=loongarch64 -frame-pointer=all < %s | FileCheck %s -+ -+define void @trivial() { -+; CHECK-LABEL: trivial: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $r22, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 22, -8 -+; CHECK-NEXT: addi.d $r22, $sp, 16 -+; CHECK-NEXT: .cfi_def_cfa 22, 0 -+; CHECK-NEXT: ld.d $r22, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+ ret void -+} -+ -+define void @stack_alloc(i32 signext %size) { -+; CHECK-LABEL: stack_alloc: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -32 -+; CHECK-NEXT: .cfi_def_cfa_offset 32 -+; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -+; CHECK-NEXT: st.d $r22, $sp, 16 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: .cfi_offset 22, -16 -+; CHECK-NEXT: addi.d $r22, $sp, 32 -+; CHECK-NEXT: .cfi_def_cfa 22, 0 -+; CHECK-NEXT: addi.w $r5, $zero, -16 -+; CHECK-NEXT: lu32i.d $r5, 1 -+; CHECK-NEXT: bstrpick.d $r4, $r4, 31, 0 -+; CHECK-NEXT: addi.d $r4, $r4, 15 -+; CHECK-NEXT: and $r4, $r4, $r5 -+; CHECK-NEXT: sub.d $r4, $sp, $r4 -+; CHECK-NEXT: move $sp, $r4 -+; CHECK-NEXT: bl callee_with_args -+; CHECK-NEXT: addi.d $sp, $r22, -32 -+; CHECK-NEXT: ld.d $r22, $sp, 16 # 8-byte Folded Reload -+; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 32 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = alloca i8, i32 %size, align 16 -+ call void @callee_with_args(i8* nonnull %0) -+ ret void -+} -+ -+define void @branch_and_tail_call(i1 %a) { -+; CHECK-LABEL: branch_and_tail_call: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: andi $r4, $r4, 1 -+; CHECK-NEXT: beqz $r4, .LBB2_2 -+; CHECK-NEXT: # %bb.1: # %blue_pill -+; CHECK-NEXT: b callee1 -+; CHECK-NEXT: .LBB2_2: # %red_pill -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: st.d $r22, $sp, 0 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: .cfi_offset 22, -16 -+; CHECK-NEXT: addi.d $r22, $sp, 16 -+; CHECK-NEXT: .cfi_def_cfa 22, 0 -+; CHECK-NEXT: bl callee2 -+; CHECK-NEXT: ld.d $r22, $sp, 0 # 8-byte Folded Reload -+; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+ br i1 %a, label %blue_pill, label %red_pill -+blue_pill: -+ tail call void @callee1() -+ ret void -+red_pill: -+ call void @callee2() -+ ret void -+} -+ -+define void @big_frame() { -+; CHECK-LABEL: big_frame: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -2032 -+; CHECK-NEXT: .cfi_def_cfa_offset 2032 -+; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill -+; CHECK-NEXT: st.d $r22, $sp, 2016 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: .cfi_offset 22, -16 -+; CHECK-NEXT: addi.d $r22, $sp, 2032 -+; CHECK-NEXT: .cfi_def_cfa 22, 0 -+; CHECK-NEXT: addi.d $sp, $sp, -48 -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2016 -+; CHECK-NEXT: add.d $r4, $r22, $r4 -+; CHECK-NEXT: addi.d $r4, $r4, 0 -+; CHECK-NEXT: bl callee_with_args -+; CHECK-NEXT: addi.d $sp, $sp, 48 -+; CHECK-NEXT: ld.d $r22, $sp, 2016 # 8-byte Folded Reload -+; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 2032 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = alloca i8, i32 2048, align 16 -+ call void @callee_with_args(i8* nonnull %0) -+ ret void -+} -+ -+define void @varargs_frame(i32 %i, ...) { -+; CHECK-LABEL: varargs_frame: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $sp, $sp, -80 -+; CHECK-NEXT: .cfi_def_cfa_offset 80 -+; CHECK-NEXT: st.d $r22, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 22, -72 -+; CHECK-NEXT: addi.d $r22, $sp, 16 -+; CHECK-NEXT: .cfi_def_cfa 22, 64 -+; CHECK-NEXT: st.d $r11, $r22, 56 -+; CHECK-NEXT: st.d $r10, $r22, 48 -+; CHECK-NEXT: st.d $r9, $r22, 40 -+; CHECK-NEXT: st.d $r8, $r22, 32 -+; CHECK-NEXT: st.d $r7, $r22, 24 -+; CHECK-NEXT: st.d $r6, $r22, 16 -+; CHECK-NEXT: st.d $r5, $r22, 8 -+; CHECK-NEXT: ld.d $r22, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 80 -+; CHECK-NEXT: jr $ra -+ ret void -+} -+ -+declare void @callee1() -+declare void @callee2() -+declare void @callee_with_args(i8*) -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll -new file mode 100644 -index 000000000..f41ee08c0 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll -@@ -0,0 +1,47 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+ -+define double @olt_f64(double %a, double %b) { -+; CHECK-LABEL: olt_f64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: fcmp.clt.d $fcc0, $f0, $f1 -+; CHECK-NEXT: fsel $f0, $f1, $f0, $fcc0 -+; CHECK-NEXT: jr $ra -+ %cond = fcmp olt double %a, %b -+ %ret = select i1 %cond, double %a, double %b -+ ret double %ret -+} -+ -+define double @ogt_f64(double %a, double %b) { -+; CHECK-LABEL: ogt_f64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: fcmp.cule.d $fcc0, $f0, $f1 -+; CHECK-NEXT: fsel $f0, $f0, $f1, $fcc0 -+; CHECK-NEXT: jr $ra -+ %cond = fcmp ogt double %a, %b -+ %ret = select i1 %cond, double %a, double %b -+ ret double %ret -+} -+ -+define float @olt_f32(float %a, float %b) { -+; CHECK-LABEL: olt_f32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: fcmp.clt.s $fcc0, $f0, $f1 -+; CHECK-NEXT: fsel $f0, $f1, $f0, $fcc0 -+; CHECK-NEXT: jr $ra -+ %cond = fcmp olt float %a, %b -+ %ret = select i1 %cond, float %a, float %b -+ ret float %ret -+} -+ -+define float @ogt_f32(float %a, float %b) { -+; CHECK-LABEL: ogt_f32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: fcmp.cule.s $fcc0, $f0, $f1 -+; CHECK-NEXT: fsel $f0, $f0, $f1, $fcc0 -+; CHECK-NEXT: jr $ra -+ %cond = fcmp ogt float %a, %b -+ %ret = select i1 %cond, float %a, float %b -+ ret float %ret -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll -new file mode 100644 -index 000000000..1de3ef0fc ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll -@@ -0,0 +1,2542 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -mtriple=loongarch64 < %s | FileCheck %s -+define i64 @li0000000000000000() { -+; CHECK-LABEL: li0000000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r4, $zero, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 0 -+} -+ -+define i64 @li00000000000007ff() { -+; CHECK-LABEL: li00000000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r4, $zero, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 2047 -+} -+ -+define i64 @li0000000000000800() { -+; CHECK-LABEL: li0000000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: jr $ra -+ ret i64 2048 -+} -+ -+define i64 @li0000000000000fff() { -+; CHECK-LABEL: li0000000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: jr $ra -+ ret i64 4095 -+} -+ -+define i64 @li000000007ffff000() { -+; CHECK-LABEL: li000000007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2147479552 -+} -+ -+define i64 @li000000007ffff7ff() { -+; CHECK-LABEL: li000000007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 2147481599 -+} -+ -+define i64 @li000000007ffff800() { -+; CHECK-LABEL: li000000007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: jr $ra -+ ret i64 2147481600 -+} -+ -+define i64 @li000000007fffffff() { -+; CHECK-LABEL: li000000007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: jr $ra -+ ret i64 2147483647 -+} -+ -+define i64 @li0000000080000000() { -+; CHECK-LABEL: li0000000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2147483648 -+} -+ -+define i64 @li00000000800007ff() { -+; CHECK-LABEL: li00000000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2147485695 -+} -+ -+define i64 @li0000000080000800() { -+; CHECK-LABEL: li0000000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2147485696 -+} -+ -+define i64 @li0000000080000fff() { -+; CHECK-LABEL: li0000000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2147487743 -+} -+ -+define i64 @li00000000fffff000() { -+; CHECK-LABEL: li00000000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4294963200 -+} -+ -+define i64 @li00000000fffff7ff() { -+; CHECK-LABEL: li00000000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4294965247 -+} -+ -+define i64 @li00000000fffff800() { -+; CHECK-LABEL: li00000000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4294965248 -+} -+ -+define i64 @li00000000ffffffff() { -+; CHECK-LABEL: li00000000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4294967295 -+} -+ -+define i64 @li0007ffff00000000() { -+; CHECK-LABEL: li0007ffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251795518717952 -+} -+ -+define i64 @li0007ffff000007ff() { -+; CHECK-LABEL: li0007ffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251795518719999 -+} -+ -+define i64 @li0007ffff00000800() { -+; CHECK-LABEL: li0007ffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251795518720000 -+} -+ -+define i64 @li0007ffff00000fff() { -+; CHECK-LABEL: li0007ffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251795518722047 -+} -+ -+define i64 @li0007ffff7ffff000() { -+; CHECK-LABEL: li0007ffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666197504 -+} -+ -+define i64 @li0007ffff7ffff7ff() { -+; CHECK-LABEL: li0007ffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666199551 -+} -+ -+define i64 @li0007ffff7ffff800() { -+; CHECK-LABEL: li0007ffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666199552 -+} -+ -+define i64 @li0007ffff7fffffff() { -+; CHECK-LABEL: li0007ffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666201599 -+} -+ -+define i64 @li0007ffff80000000() { -+; CHECK-LABEL: li0007ffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666201600 -+} -+ -+define i64 @li0007ffff800007ff() { -+; CHECK-LABEL: li0007ffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666203647 -+} -+ -+define i64 @li0007ffff80000800() { -+; CHECK-LABEL: li0007ffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666203648 -+} -+ -+define i64 @li0007ffff80000fff() { -+; CHECK-LABEL: li0007ffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251797666205695 -+} -+ -+define i64 @li0007fffffffff000() { -+; CHECK-LABEL: li0007fffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813681152 -+} -+ -+define i64 @li0007fffffffff7ff() { -+; CHECK-LABEL: li0007fffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813683199 -+} -+ -+define i64 @li0007fffffffff800() { -+; CHECK-LABEL: li0007fffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813683200 -+} -+ -+define i64 @li0007ffffffffffff() { -+; CHECK-LABEL: li0007ffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813685247 -+} -+ -+define i64 @li0008000000000000() { -+; CHECK-LABEL: li0008000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813685248 -+} -+ -+define i64 @li00080000000007ff() { -+; CHECK-LABEL: li00080000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813687295 -+} -+ -+define i64 @li0008000000000800() { -+; CHECK-LABEL: li0008000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813687296 -+} -+ -+define i64 @li0008000000000fff() { -+; CHECK-LABEL: li0008000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251799813689343 -+} -+ -+define i64 @li000800007ffff000() { -+; CHECK-LABEL: li000800007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961164800 -+} -+ -+define i64 @li000800007ffff7ff() { -+; CHECK-LABEL: li000800007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961166847 -+} -+ -+define i64 @li000800007ffff800() { -+; CHECK-LABEL: li000800007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961166848 -+} -+ -+define i64 @li000800007fffffff() { -+; CHECK-LABEL: li000800007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961168895 -+} -+ -+define i64 @li0008000080000000() { -+; CHECK-LABEL: li0008000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961168896 -+} -+ -+define i64 @li00080000800007ff() { -+; CHECK-LABEL: li00080000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961170943 -+} -+ -+define i64 @li0008000080000800() { -+; CHECK-LABEL: li0008000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961170944 -+} -+ -+define i64 @li0008000080000fff() { -+; CHECK-LABEL: li0008000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251801961172991 -+} -+ -+define i64 @li00080000fffff000() { -+; CHECK-LABEL: li00080000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251804108648448 -+} -+ -+define i64 @li00080000fffff7ff() { -+; CHECK-LABEL: li00080000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251804108650495 -+} -+ -+define i64 @li00080000fffff800() { -+; CHECK-LABEL: li00080000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251804108650496 -+} -+ -+define i64 @li00080000ffffffff() { -+; CHECK-LABEL: li00080000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 2251804108652543 -+} -+ -+define i64 @li000fffff00000000() { -+; CHECK-LABEL: li000fffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503595332403200 -+} -+ -+define i64 @li000fffff000007ff() { -+; CHECK-LABEL: li000fffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503595332405247 -+} -+ -+define i64 @li000fffff00000800() { -+; CHECK-LABEL: li000fffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503595332405248 -+} -+ -+define i64 @li000fffff00000fff() { -+; CHECK-LABEL: li000fffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503595332407295 -+} -+ -+define i64 @li000fffff7ffff000() { -+; CHECK-LABEL: li000fffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479882752 -+} -+ -+define i64 @li000fffff7ffff7ff() { -+; CHECK-LABEL: li000fffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479884799 -+} -+ -+define i64 @li000fffff7ffff800() { -+; CHECK-LABEL: li000fffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479884800 -+} -+ -+define i64 @li000fffff7fffffff() { -+; CHECK-LABEL: li000fffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479886847 -+} -+ -+define i64 @li000fffff80000000() { -+; CHECK-LABEL: li000fffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479886848 -+} -+ -+define i64 @li000fffff800007ff() { -+; CHECK-LABEL: li000fffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479888895 -+} -+ -+define i64 @li000fffff80000800() { -+; CHECK-LABEL: li000fffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479888896 -+} -+ -+define i64 @li000fffff80000fff() { -+; CHECK-LABEL: li000fffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503597479890943 -+} -+ -+define i64 @li000ffffffffff000() { -+; CHECK-LABEL: li000ffffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503599627366400 -+} -+ -+define i64 @li000ffffffffff7ff() { -+; CHECK-LABEL: li000ffffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503599627368447 -+} -+ -+define i64 @li000ffffffffff800() { -+; CHECK-LABEL: li000ffffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503599627368448 -+} -+ -+define i64 @li000fffffffffffff() { -+; CHECK-LABEL: li000fffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i64 4503599627370495 -+} -+ -+define i64 @li7ff0000000000000() { -+; CHECK-LABEL: li7ff0000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu52i.d $r4, $zero, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868437227405312 -+} -+ -+define i64 @li7ff00000000007ff() { -+; CHECK-LABEL: li7ff00000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868437227407359 -+} -+ -+define i64 @li7ff0000000000800() { -+; CHECK-LABEL: li7ff0000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868437227407360 -+} -+ -+define i64 @li7ff0000000000fff() { -+; CHECK-LABEL: li7ff0000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868437227409407 -+} -+ -+define i64 @li7ff000007ffff000() { -+; CHECK-LABEL: li7ff000007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374884864 -+} -+ -+define i64 @li7ff000007ffff7ff() { -+; CHECK-LABEL: li7ff000007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374886911 -+} -+ -+define i64 @li7ff000007ffff800() { -+; CHECK-LABEL: li7ff000007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374886912 -+} -+ -+define i64 @li7ff000007fffffff() { -+; CHECK-LABEL: li7ff000007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374888959 -+} -+ -+define i64 @li7ff0000080000000() { -+; CHECK-LABEL: li7ff0000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374888960 -+} -+ -+define i64 @li7ff00000800007ff() { -+; CHECK-LABEL: li7ff00000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374891007 -+} -+ -+define i64 @li7ff0000080000800() { -+; CHECK-LABEL: li7ff0000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374891008 -+} -+ -+define i64 @li7ff0000080000fff() { -+; CHECK-LABEL: li7ff0000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868439374893055 -+} -+ -+define i64 @li7ff00000fffff000() { -+; CHECK-LABEL: li7ff00000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868441522368512 -+} -+ -+define i64 @li7ff00000fffff7ff() { -+; CHECK-LABEL: li7ff00000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868441522370559 -+} -+ -+define i64 @li7ff00000fffff800() { -+; CHECK-LABEL: li7ff00000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868441522370560 -+} -+ -+define i64 @li7ff00000ffffffff() { -+; CHECK-LABEL: li7ff00000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9218868441522372607 -+} -+ -+define i64 @li7ff7ffff00000000() { -+; CHECK-LABEL: li7ff7ffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120232746123264 -+} -+ -+define i64 @li7ff7ffff000007ff() { -+; CHECK-LABEL: li7ff7ffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120232746125311 -+} -+ -+define i64 @li7ff7ffff00000800() { -+; CHECK-LABEL: li7ff7ffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120232746125312 -+} -+ -+define i64 @li7ff7ffff00000fff() { -+; CHECK-LABEL: li7ff7ffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120232746127359 -+} -+ -+define i64 @li7ff7ffff7ffff000() { -+; CHECK-LABEL: li7ff7ffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893602816 -+} -+ -+define i64 @li7ff7ffff7ffff7ff() { -+; CHECK-LABEL: li7ff7ffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893604863 -+} -+ -+define i64 @li7ff7ffff7ffff800() { -+; CHECK-LABEL: li7ff7ffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893604864 -+} -+ -+define i64 @li7ff7ffff7fffffff() { -+; CHECK-LABEL: li7ff7ffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893606911 -+} -+ -+define i64 @li7ff7ffff80000000() { -+; CHECK-LABEL: li7ff7ffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893606912 -+} -+ -+define i64 @li7ff7ffff800007ff() { -+; CHECK-LABEL: li7ff7ffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893608959 -+} -+ -+define i64 @li7ff7ffff80000800() { -+; CHECK-LABEL: li7ff7ffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893608960 -+} -+ -+define i64 @li7ff7ffff80000fff() { -+; CHECK-LABEL: li7ff7ffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120234893611007 -+} -+ -+define i64 @li7ff7fffffffff000() { -+; CHECK-LABEL: li7ff7fffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041086464 -+} -+ -+define i64 @li7ff7fffffffff7ff() { -+; CHECK-LABEL: li7ff7fffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041088511 -+} -+ -+define i64 @li7ff7fffffffff800() { -+; CHECK-LABEL: li7ff7fffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041088512 -+} -+ -+define i64 @li7ff7ffffffffffff() { -+; CHECK-LABEL: li7ff7ffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041090559 -+} -+ -+define i64 @li7ff8000000000000() { -+; CHECK-LABEL: li7ff8000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041090560 -+} -+ -+define i64 @li7ff80000000007ff() { -+; CHECK-LABEL: li7ff80000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041092607 -+} -+ -+define i64 @li7ff8000000000800() { -+; CHECK-LABEL: li7ff8000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041092608 -+} -+ -+define i64 @li7ff8000000000fff() { -+; CHECK-LABEL: li7ff8000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120237041094655 -+} -+ -+define i64 @li7ff800007ffff000() { -+; CHECK-LABEL: li7ff800007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188570112 -+} -+ -+define i64 @li7ff800007ffff7ff() { -+; CHECK-LABEL: li7ff800007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188572159 -+} -+ -+define i64 @li7ff800007ffff800() { -+; CHECK-LABEL: li7ff800007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188572160 -+} -+ -+define i64 @li7ff800007fffffff() { -+; CHECK-LABEL: li7ff800007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188574207 -+} -+ -+define i64 @li7ff8000080000000() { -+; CHECK-LABEL: li7ff8000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188574208 -+} -+ -+define i64 @li7ff80000800007ff() { -+; CHECK-LABEL: li7ff80000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188576255 -+} -+ -+define i64 @li7ff8000080000800() { -+; CHECK-LABEL: li7ff8000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188576256 -+} -+ -+define i64 @li7ff8000080000fff() { -+; CHECK-LABEL: li7ff8000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120239188578303 -+} -+ -+define i64 @li7ff80000fffff000() { -+; CHECK-LABEL: li7ff80000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120241336053760 -+} -+ -+define i64 @li7ff80000fffff7ff() { -+; CHECK-LABEL: li7ff80000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120241336055807 -+} -+ -+define i64 @li7ff80000fffff800() { -+; CHECK-LABEL: li7ff80000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120241336055808 -+} -+ -+define i64 @li7ff80000ffffffff() { -+; CHECK-LABEL: li7ff80000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9221120241336057855 -+} -+ -+define i64 @li7fffffff00000000() { -+; CHECK-LABEL: li7fffffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372032559808512 -+} -+ -+define i64 @li7fffffff000007ff() { -+; CHECK-LABEL: li7fffffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372032559810559 -+} -+ -+define i64 @li7fffffff00000800() { -+; CHECK-LABEL: li7fffffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372032559810560 -+} -+ -+define i64 @li7fffffff00000fff() { -+; CHECK-LABEL: li7fffffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372032559812607 -+} -+ -+define i64 @li7fffffff7ffff000() { -+; CHECK-LABEL: li7fffffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707288064 -+} -+ -+define i64 @li7fffffff7ffff7ff() { -+; CHECK-LABEL: li7fffffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707290111 -+} -+ -+define i64 @li7fffffff7ffff800() { -+; CHECK-LABEL: li7fffffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707290112 -+} -+ -+define i64 @li7fffffff7fffffff() { -+; CHECK-LABEL: li7fffffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707292159 -+} -+ -+define i64 @li7fffffff80000000() { -+; CHECK-LABEL: li7fffffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707292160 -+} -+ -+define i64 @li7fffffff800007ff() { -+; CHECK-LABEL: li7fffffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707294207 -+} -+ -+define i64 @li7fffffff80000800() { -+; CHECK-LABEL: li7fffffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707294208 -+} -+ -+define i64 @li7fffffff80000fff() { -+; CHECK-LABEL: li7fffffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372034707296255 -+} -+ -+define i64 @li7ffffffffffff000() { -+; CHECK-LABEL: li7ffffffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372036854771712 -+} -+ -+define i64 @li7ffffffffffff7ff() { -+; CHECK-LABEL: li7ffffffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372036854773759 -+} -+ -+define i64 @li7ffffffffffff800() { -+; CHECK-LABEL: li7ffffffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372036854773760 -+} -+ -+define i64 @li7fffffffffffffff() { -+; CHECK-LABEL: li7fffffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 9223372036854775807 -+} -+ -+define i64 @li8000000000000000() { -+; CHECK-LABEL: li8000000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu52i.d $r4, $zero, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372036854775808 -+} -+ -+define i64 @li80000000000007ff() { -+; CHECK-LABEL: li80000000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372036854773761 -+} -+ -+define i64 @li8000000000000800() { -+; CHECK-LABEL: li8000000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372036854773760 -+} -+ -+define i64 @li8000000000000fff() { -+; CHECK-LABEL: li8000000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372036854771713 -+} -+ -+define i64 @li800000007ffff000() { -+; CHECK-LABEL: li800000007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707296256 -+} -+ -+define i64 @li800000007ffff7ff() { -+; CHECK-LABEL: li800000007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707294209 -+} -+ -+define i64 @li800000007ffff800() { -+; CHECK-LABEL: li800000007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707294208 -+} -+ -+define i64 @li800000007fffffff() { -+; CHECK-LABEL: li800000007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707292161 -+} -+ -+define i64 @li8000000080000000() { -+; CHECK-LABEL: li8000000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707292160 -+} -+ -+define i64 @li80000000800007ff() { -+; CHECK-LABEL: li80000000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707290113 -+} -+ -+define i64 @li8000000080000800() { -+; CHECK-LABEL: li8000000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707290112 -+} -+ -+define i64 @li8000000080000fff() { -+; CHECK-LABEL: li8000000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372034707288065 -+} -+ -+define i64 @li80000000fffff000() { -+; CHECK-LABEL: li80000000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372032559812608 -+} -+ -+define i64 @li80000000fffff7ff() { -+; CHECK-LABEL: li80000000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372032559810561 -+} -+ -+define i64 @li80000000fffff800() { -+; CHECK-LABEL: li80000000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372032559810560 -+} -+ -+define i64 @li80000000ffffffff() { -+; CHECK-LABEL: li80000000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9223372032559808513 -+} -+ -+define i64 @li8007ffff00000000() { -+; CHECK-LABEL: li8007ffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120241336057856 -+} -+ -+define i64 @li8007ffff000007ff() { -+; CHECK-LABEL: li8007ffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120241336055809 -+} -+ -+define i64 @li8007ffff00000800() { -+; CHECK-LABEL: li8007ffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120241336055808 -+} -+ -+define i64 @li8007ffff00000fff() { -+; CHECK-LABEL: li8007ffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120241336053761 -+} -+ -+define i64 @li8007ffff7ffff000() { -+; CHECK-LABEL: li8007ffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188578304 -+} -+ -+define i64 @li8007ffff7ffff7ff() { -+; CHECK-LABEL: li8007ffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188576257 -+} -+ -+define i64 @li8007ffff7ffff800() { -+; CHECK-LABEL: li8007ffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188576256 -+} -+ -+define i64 @li8007ffff7fffffff() { -+; CHECK-LABEL: li8007ffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188574209 -+} -+ -+define i64 @li8007ffff80000000() { -+; CHECK-LABEL: li8007ffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188574208 -+} -+ -+define i64 @li8007ffff800007ff() { -+; CHECK-LABEL: li8007ffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188572161 -+} -+ -+define i64 @li8007ffff80000800() { -+; CHECK-LABEL: li8007ffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188572160 -+} -+ -+define i64 @li8007ffff80000fff() { -+; CHECK-LABEL: li8007ffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120239188570113 -+} -+ -+define i64 @li8007fffffffff000() { -+; CHECK-LABEL: li8007fffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041094656 -+} -+ -+define i64 @li8007fffffffff7ff() { -+; CHECK-LABEL: li8007fffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041092609 -+} -+ -+define i64 @li8007fffffffff800() { -+; CHECK-LABEL: li8007fffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041092608 -+} -+ -+define i64 @li8007ffffffffffff() { -+; CHECK-LABEL: li8007ffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041090561 -+} -+ -+define i64 @li8008000000000000() { -+; CHECK-LABEL: li8008000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041090560 -+} -+ -+define i64 @li80080000000007ff() { -+; CHECK-LABEL: li80080000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041088513 -+} -+ -+define i64 @li8008000000000800() { -+; CHECK-LABEL: li8008000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041088512 -+} -+ -+define i64 @li8008000000000fff() { -+; CHECK-LABEL: li8008000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120237041086465 -+} -+ -+define i64 @li800800007ffff000() { -+; CHECK-LABEL: li800800007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893611008 -+} -+ -+define i64 @li800800007ffff7ff() { -+; CHECK-LABEL: li800800007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893608961 -+} -+ -+define i64 @li800800007ffff800() { -+; CHECK-LABEL: li800800007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893608960 -+} -+ -+define i64 @li800800007fffffff() { -+; CHECK-LABEL: li800800007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893606913 -+} -+ -+define i64 @li8008000080000000() { -+; CHECK-LABEL: li8008000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893606912 -+} -+ -+define i64 @li80080000800007ff() { -+; CHECK-LABEL: li80080000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893604865 -+} -+ -+define i64 @li8008000080000800() { -+; CHECK-LABEL: li8008000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893604864 -+} -+ -+define i64 @li8008000080000fff() { -+; CHECK-LABEL: li8008000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120234893602817 -+} -+ -+define i64 @li80080000fffff000() { -+; CHECK-LABEL: li80080000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120232746127360 -+} -+ -+define i64 @li80080000fffff7ff() { -+; CHECK-LABEL: li80080000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120232746125313 -+} -+ -+define i64 @li80080000fffff800() { -+; CHECK-LABEL: li80080000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120232746125312 -+} -+ -+define i64 @li80080000ffffffff() { -+; CHECK-LABEL: li80080000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9221120232746123265 -+} -+ -+define i64 @li800fffff00000000() { -+; CHECK-LABEL: li800fffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868441522372608 -+} -+ -+define i64 @li800fffff000007ff() { -+; CHECK-LABEL: li800fffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868441522370561 -+} -+ -+define i64 @li800fffff00000800() { -+; CHECK-LABEL: li800fffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868441522370560 -+} -+ -+define i64 @li800fffff00000fff() { -+; CHECK-LABEL: li800fffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868441522368513 -+} -+ -+define i64 @li800fffff7ffff000() { -+; CHECK-LABEL: li800fffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374893056 -+} -+ -+define i64 @li800fffff7ffff7ff() { -+; CHECK-LABEL: li800fffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374891009 -+} -+ -+define i64 @li800fffff7ffff800() { -+; CHECK-LABEL: li800fffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374891008 -+} -+ -+define i64 @li800fffff7fffffff() { -+; CHECK-LABEL: li800fffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374888961 -+} -+ -+define i64 @li800fffff80000000() { -+; CHECK-LABEL: li800fffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374888960 -+} -+ -+define i64 @li800fffff800007ff() { -+; CHECK-LABEL: li800fffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374886913 -+} -+ -+define i64 @li800fffff80000800() { -+; CHECK-LABEL: li800fffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374886912 -+} -+ -+define i64 @li800fffff80000fff() { -+; CHECK-LABEL: li800fffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868439374884865 -+} -+ -+define i64 @li800ffffffffff000() { -+; CHECK-LABEL: li800ffffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868437227409408 -+} -+ -+define i64 @li800ffffffffff7ff() { -+; CHECK-LABEL: li800ffffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868437227407361 -+} -+ -+define i64 @li800ffffffffff800() { -+; CHECK-LABEL: li800ffffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868437227407360 -+} -+ -+define i64 @li800fffffffffffff() { -+; CHECK-LABEL: li800fffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -9218868437227405313 -+} -+ -+define i64 @lifff0000000000000() { -+; CHECK-LABEL: lifff0000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu52i.d $r4, $zero, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503599627370496 -+} -+ -+define i64 @lifff00000000007ff() { -+; CHECK-LABEL: lifff00000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503599627368449 -+} -+ -+define i64 @lifff0000000000800() { -+; CHECK-LABEL: lifff0000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503599627368448 -+} -+ -+define i64 @lifff0000000000fff() { -+; CHECK-LABEL: lifff0000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503599627366401 -+} -+ -+define i64 @lifff000007ffff000() { -+; CHECK-LABEL: lifff000007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479890944 -+} -+ -+define i64 @lifff000007ffff7ff() { -+; CHECK-LABEL: lifff000007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479888897 -+} -+ -+define i64 @lifff000007ffff800() { -+; CHECK-LABEL: lifff000007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479888896 -+} -+ -+define i64 @lifff000007fffffff() { -+; CHECK-LABEL: lifff000007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479886849 -+} -+ -+define i64 @lifff0000080000000() { -+; CHECK-LABEL: lifff0000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479886848 -+} -+ -+define i64 @lifff00000800007ff() { -+; CHECK-LABEL: lifff00000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479884801 -+} -+ -+define i64 @lifff0000080000800() { -+; CHECK-LABEL: lifff0000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479884800 -+} -+ -+define i64 @lifff0000080000fff() { -+; CHECK-LABEL: lifff0000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503597479882753 -+} -+ -+define i64 @lifff00000fffff000() { -+; CHECK-LABEL: lifff00000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503595332407296 -+} -+ -+define i64 @lifff00000fffff7ff() { -+; CHECK-LABEL: lifff00000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503595332405249 -+} -+ -+define i64 @lifff00000fffff800() { -+; CHECK-LABEL: lifff00000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503595332405248 -+} -+ -+define i64 @lifff00000ffffffff() { -+; CHECK-LABEL: lifff00000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4503595332403201 -+} -+ -+define i64 @lifff7ffff00000000() { -+; CHECK-LABEL: lifff7ffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251804108652544 -+} -+ -+define i64 @lifff7ffff000007ff() { -+; CHECK-LABEL: lifff7ffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251804108650497 -+} -+ -+define i64 @lifff7ffff00000800() { -+; CHECK-LABEL: lifff7ffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251804108650496 -+} -+ -+define i64 @lifff7ffff00000fff() { -+; CHECK-LABEL: lifff7ffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251804108648449 -+} -+ -+define i64 @lifff7ffff7ffff000() { -+; CHECK-LABEL: lifff7ffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961172992 -+} -+ -+define i64 @lifff7ffff7ffff7ff() { -+; CHECK-LABEL: lifff7ffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961170945 -+} -+ -+define i64 @lifff7ffff7ffff800() { -+; CHECK-LABEL: lifff7ffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961170944 -+} -+ -+define i64 @lifff7ffff7fffffff() { -+; CHECK-LABEL: lifff7ffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961168897 -+} -+ -+define i64 @lifff7ffff80000000() { -+; CHECK-LABEL: lifff7ffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961168896 -+} -+ -+define i64 @lifff7ffff800007ff() { -+; CHECK-LABEL: lifff7ffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961166849 -+} -+ -+define i64 @lifff7ffff80000800() { -+; CHECK-LABEL: lifff7ffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961166848 -+} -+ -+define i64 @lifff7ffff80000fff() { -+; CHECK-LABEL: lifff7ffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251801961164801 -+} -+ -+define i64 @lifff7fffffffff000() { -+; CHECK-LABEL: lifff7fffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813689344 -+} -+ -+define i64 @lifff7fffffffff7ff() { -+; CHECK-LABEL: lifff7fffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813687297 -+} -+ -+define i64 @lifff7fffffffff800() { -+; CHECK-LABEL: lifff7fffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813687296 -+} -+ -+define i64 @lifff7ffffffffffff() { -+; CHECK-LABEL: lifff7ffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813685249 -+} -+ -+define i64 @lifff8000000000000() { -+; CHECK-LABEL: lifff8000000000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813685248 -+} -+ -+define i64 @lifff80000000007ff() { -+; CHECK-LABEL: lifff80000000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813683201 -+} -+ -+define i64 @lifff8000000000800() { -+; CHECK-LABEL: lifff8000000000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813683200 -+} -+ -+define i64 @lifff8000000000fff() { -+; CHECK-LABEL: lifff8000000000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251799813681153 -+} -+ -+define i64 @lifff800007ffff000() { -+; CHECK-LABEL: lifff800007ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666205696 -+} -+ -+define i64 @lifff800007ffff7ff() { -+; CHECK-LABEL: lifff800007ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666203649 -+} -+ -+define i64 @lifff800007ffff800() { -+; CHECK-LABEL: lifff800007ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666203648 -+} -+ -+define i64 @lifff800007fffffff() { -+; CHECK-LABEL: lifff800007fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666201601 -+} -+ -+define i64 @lifff8000080000000() { -+; CHECK-LABEL: lifff8000080000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666201600 -+} -+ -+define i64 @lifff80000800007ff() { -+; CHECK-LABEL: lifff80000800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666199553 -+} -+ -+define i64 @lifff8000080000800() { -+; CHECK-LABEL: lifff8000080000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666199552 -+} -+ -+define i64 @lifff8000080000fff() { -+; CHECK-LABEL: lifff8000080000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251797666197505 -+} -+ -+define i64 @lifff80000fffff000() { -+; CHECK-LABEL: lifff80000fffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251795518722048 -+} -+ -+define i64 @lifff80000fffff7ff() { -+; CHECK-LABEL: lifff80000fffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251795518720001 -+} -+ -+define i64 @lifff80000fffff800() { -+; CHECK-LABEL: lifff80000fffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251795518720000 -+} -+ -+define i64 @lifff80000ffffffff() { -+; CHECK-LABEL: lifff80000ffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2251795518717953 -+} -+ -+define i64 @liffffffff00000000() { -+; CHECK-LABEL: liffffffff00000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4294967296 -+} -+ -+define i64 @liffffffff000007ff() { -+; CHECK-LABEL: liffffffff000007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4294965249 -+} -+ -+define i64 @liffffffff00000800() { -+; CHECK-LABEL: liffffffff00000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4294965248 -+} -+ -+define i64 @liffffffff00000fff() { -+; CHECK-LABEL: liffffffff00000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4294963201 -+} -+ -+define i64 @liffffffff7ffff000() { -+; CHECK-LABEL: liffffffff7ffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147487744 -+} -+ -+define i64 @liffffffff7ffff7ff() { -+; CHECK-LABEL: liffffffff7ffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147485697 -+} -+ -+define i64 @liffffffff7ffff800() { -+; CHECK-LABEL: liffffffff7ffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147485696 -+} -+ -+define i64 @liffffffff7fffffff() { -+; CHECK-LABEL: liffffffff7fffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147483649 -+} -+ -+define i64 @liffffffff80000000() { -+; CHECK-LABEL: liffffffff80000000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147483648 -+} -+ -+define i64 @liffffffff800007ff() { -+; CHECK-LABEL: liffffffff800007ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147481601 -+} -+ -+define i64 @liffffffff80000800() { -+; CHECK-LABEL: liffffffff80000800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147481600 -+} -+ -+define i64 @liffffffff80000fff() { -+; CHECK-LABEL: liffffffff80000fff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 4095 -+; CHECK-NEXT: jr $ra -+ ret i64 -2147479553 -+} -+ -+define i64 @lifffffffffffff000() { -+; CHECK-LABEL: lifffffffffffff000: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -4096 -+} -+ -+define i64 @lifffffffffffff7ff() { -+; CHECK-LABEL: lifffffffffffff7ff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: jr $ra -+ ret i64 -2049 -+} -+ -+define i64 @lifffffffffffff800() { -+; CHECK-LABEL: lifffffffffffff800: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r4, $zero, -2048 -+; CHECK-NEXT: jr $ra -+ ret i64 -2048 -+} -+ -+define i64 @liffffffffffffffff() { -+; CHECK-LABEL: liffffffffffffffff: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.d $r4, $zero, -1 -+; CHECK-NEXT: jr $ra -+ ret i64 -1 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll -new file mode 100644 -index 000000000..986e27e2a ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll -@@ -0,0 +1,8 @@ -+; RUN: llc -march=loongarch64 -no-integrated-as -o - %s | FileCheck %s -+ -+define i64 @test(i64 %a) { -+; CHECK: add.d $r4, $r4, $r0 -+entry: -+ %0 = tail call i64 asm sideeffect "add.d $0, $1, ${2:z} \0A", "=r,r,Jr"(i64 %a, i64 0) -+ ret i64 %0 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll -new file mode 100644 -index 000000000..94e330673 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll -@@ -0,0 +1,31 @@ -+; RUN: llc -march=loongarch64 -target-abi=lp64 -o - %s 2>&1 | FileCheck %s -+ -+;; Test that floating-point bits can be stored in GPR. -+ -+define void @reg_float(float %x) { -+; CHECK-LABEL: reg_float: -+; CHECK: movfr2gr.s $r{{[0-9]+}}, $f0 -+ call void asm "", "r"(float %x) -+ ret void -+} -+ -+define void @r10_float(float %x) { -+; CHECK-LABEL: r10_float: -+; CHECK: movfr2gr.s $r10, $f0 -+ call void asm "", "{$r10}"(float %x) -+ ret void -+} -+ -+define void @reg_double(double %x) { -+; CHECK-LABEL: reg_double: -+; CHECK: movfr2gr.d $r{{[0-9]+}}, $f0 -+ call void asm "", "r"(double %x) -+ ret void -+} -+ -+define void @r10_double(double %x) { -+; CHECK-LABEL: r10_double: -+; CHECK: movfr2gr.d $r10, $f0 -+ call void asm "", "{$r10}"(double %x) -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll -new file mode 100644 -index 000000000..7f58ea2ee ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll -@@ -0,0 +1,8 @@ -+; RUN: not llc -march=loongarch64 %s 2>&1 | FileCheck %s -+ -+define void @test_i128() { -+; CHECK: error: couldn't allocate input reg for constraint '{$r20}' -+start: -+ call void asm "", "{$r20}"(i128 5) -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll -new file mode 100644 -index 000000000..d18a184ab ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll -@@ -0,0 +1,42 @@ -+; RUN: llc -march=loongarch64 -o - %s 2>&1 | FileCheck %s -+ -+;; Test that non native value types can be parsed. -+ -+define void @test_i1() { -+; CHECK-LABEL: test_i1: -+; CHECK: ori $r6, $zero, 0 -+; CHECK: jr $ra -+start: -+ call void asm "", "{$r6}"(i1 0) -+ ret void -+} -+ -+;; Note: non-simple values like `i3` are only allowed in newer llvm versions (>= 12). -+;; In older llvm versions (<= 11), SelectionDAGBuilder::visitInlineAsm asserts simple -+;; values must be used. For details, please see https://reviews.llvm.org/D91710. -+define void @test_i3() { -+; CHECK-LABEL: test_i3: -+; CHECK: ori $r7, $zero, 0 -+; CHECK: jr $ra -+start: -+ call void asm "", "{$r7}"(i3 0) -+ ret void -+} -+ -+define void @test_i8() { -+; CHECK-LABEL: test_i8: -+; CHECK: ori $r5, $zero, 0 -+; CHECK: jr $ra -+start: -+ call void asm "", "{$r5}"(i8 0) -+ ret void -+} -+ -+define void @test_i16() { -+; CHECK-LABEL: test_i16: -+; CHECK: ori $r20, $zero, 5 -+; CHECK: jr $ra -+start: -+ call void asm "", "{$r20}"(i16 5) -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll -new file mode 100644 -index 000000000..8dbbed99f ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll -@@ -0,0 +1,8 @@ -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define void @preld(i32* %p) { -+entry: -+ ; CHECK: preld 10, $r4, 23 -+ tail call void asm sideeffect "preld 10, $0, 23 \0A\09", "r"(i32* %p) -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll -new file mode 100644 -index 000000000..70b588bea ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll -@@ -0,0 +1,34 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -verify-machineinstrs -o - %s \ -+; RUN: | FileCheck %s --check-prefix=STATIC -+; RUN: llc -march=loongarch64 -verify-machineinstrs -relocation-model=pic --code-model=large -o - %s \ -+; RUN: | FileCheck %s --check-prefix=LARGE -+ -+define void @test() nounwind { -+; STATIC-LABEL: test: -+; STATIC: # %bb.0: -+; STATIC-NEXT: addi.d $sp, $sp, -16 -+; STATIC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; STATIC-NEXT: lu12i.w $ra, foo -+; STATIC-NEXT: ori $ra, $ra, foo -+; STATIC-NEXT: lu32i.d $ra, foo -+; STATIC-NEXT: lu52i.d $ra, $ra, foo -+; STATIC-NEXT: jirl $ra, $ra, 0 -+; STATIC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; STATIC-NEXT: addi.d $sp, $sp, 16 -+; STATIC-NEXT: jr $ra -+; -+; LARGE-LABEL: test: -+; LARGE: # %bb.0: -+; LARGE-NEXT: addi.d $sp, $sp, -16 -+; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; LARGE-NEXT: pcaddu18i $ra, foo -+; LARGE-NEXT: jirl $ra, $ra, foo -+; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; LARGE-NEXT: addi.d $sp, $sp, 16 -+; LARGE-NEXT: jr $ra -+ call void @foo() nounwind -+ ret void -+} -+ -+declare void @foo() -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll -new file mode 100644 -index 000000000..1b4b52c7a ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll -@@ -0,0 +1,54 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @uvadd(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvadd: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvhaddw.du.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> -+ %1 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> -+ %2 = add <4 x i32> %0, %1 -+ %3 = zext <4 x i32> %2 to <4 x i64> -+ ret <4 x i64> %3 -+} -+ -+define <4 x i64> @svadd(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svadd: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvhaddw.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> -+ %1 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> -+ %2 = add nsw <4 x i32> %0, %1 -+ %3 = sext <4 x i32> %2 to <4 x i64> -+ ret <4 x i64> %3 -+} -+ -+define <4 x i64> @uvsub(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvsub: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvhsubw.du.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> -+ %1 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> -+ %2 = sub <4 x i32> %0, %1 -+ %3 = zext <4 x i32> %2 to <4 x i64> -+ ret <4 x i64> %3 -+} -+ -+define <4 x i64> @svsub(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svsub: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvhsubw.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> -+ %1 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> -+ %2 = sub nsw <4 x i32> %0, %1 -+ %3 = sext <4 x i32> %2 to <4 x i64> -+ ret <4 x i64> %3 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll -new file mode 100644 -index 000000000..07b80895b ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll -@@ -0,0 +1,176 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @build_lasx0(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx0: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx1(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx1: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu52i.d $r4, $zero, 2047 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx2(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx2: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx3(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx3: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx4(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx4: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx5(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx5: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx6(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx6: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx7(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx7: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx8(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx9(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx9: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx10(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx10: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx11(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx11: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx12(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx12: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -+ -+define <4 x i64> @build_lasx13(<4 x i64> %a) { -+; CHECK-LABEL: build_lasx13: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 -+; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %b = add <4 x i64> %a, -+ ret <4 x i64> %b -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll -new file mode 100644 -index 000000000..337632491 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll -@@ -0,0 +1,55 @@ -+; A basic inline assembly test -+ -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+@v4i64_r = global <4 x i64> zeroinitializer, align 32 -+@v8i32_r = global <8 x i32> zeroinitializer, align 32 -+ -+define void @test1() nounwind { -+entry: -+ ; CHECK-LABEL: test1: -+ %0 = call <4 x i64> asm "xvldi ${0:u}, 1", "=f"() -+ ; CHECK: xvldi $xr{{[1-3]?[0-9]}}, 1 -+ store <4 x i64> %0, <4 x i64>* @v4i64_r -+ ret void -+} -+ -+define void @test2() nounwind { -+entry: -+ ; CHECK-LABEL: test2: -+ %0 = load <8 x i32>, <8 x i32>* @v8i32_r -+ %1 = call <8 x i32> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(<8 x i32> %0) -+ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 -+ store <8 x i32> %1, <8 x i32>* @v8i32_r -+ ret void -+} -+ -+define void @test2_d() nounwind { -+entry: -+ ; CHECK-LABEL: test2_d: -+ %0 = load < 4 x i64>, < 4 x i64>* @v4i64_r -+ %1 = call < 4 x i64> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(< 4 x i64> %0) -+ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 -+ store < 4 x i64> %1, < 4 x i64>* @v4i64_r -+ ret void -+} -+ -+define void @test3() nounwind { -+entry: -+ ; CHECK-LABEL: test3: -+ %0 = load <8 x i32>, <8 x i32>* @v8i32_r -+ %1 = call <8 x i32> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<8 x i32> %0) -+ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 -+ store <8 x i32> %1, <8 x i32>* @v8i32_r -+ ret void -+} -+ -+define void @test3_d() nounwind { -+entry: -+ ; CHECK-LABEL: test3_d: -+ %0 = load <4 x i64>, <4 x i64>* @v4i64_r -+ %1 = call <4 x i64> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<4 x i64> %0) -+ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 -+ store <4 x i64> %1, <4 x i64>* @v4i64_r -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll -new file mode 100644 -index 000000000..51fa34606 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll -@@ -0,0 +1,38 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <16 x i16> @lasxH(<16 x i16> %d, <8 x i16> %s1) { -+; CHECK-LABEL: lasxH: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 -+; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 -+; CHECK-NEXT: jr $ra -+entry: -+ %r1 = shufflevector <8 x i16> %s1, <8 x i16> poison, <16 x i32> -+ %r2 = shufflevector <16 x i16> %r1, <16 x i16> %d, <16 x i32> -+ ret <16 x i16> %r2 -+} -+ -+define <8 x i32> @lasxW(<8 x i32> %d, <4 x i32> %s1) { -+; CHECK-LABEL: lasxW: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 -+; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 -+; CHECK-NEXT: jr $ra -+entry: -+ %r1 = shufflevector <4 x i32> %s1, <4 x i32> poison, <8 x i32> -+ %r2 = shufflevector <8 x i32> %r1, <8 x i32> %d, <8 x i32> -+ ret <8 x i32> %r2 -+} -+ -+define <4 x i64> @lasxD(<4 x i64> %d, <2 x i64> %s1) { -+; CHECK-LABEL: lasxD: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 -+; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 -+; CHECK-NEXT: jr $ra -+entry: -+ %r1 = shufflevector <2 x i64> %s1, <2 x i64> poison, <4 x i32> -+ %r2 = shufflevector <4 x i64> %r1, <4 x i64> %d, <4 x i32> -+ ret <4 x i64> %r2 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll -new file mode 100644 -index 000000000..05b720077 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll -@@ -0,0 +1,70 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+declare <32 x i8> @llvm.loongarch.lasx.xvrepli.b(i32) -+declare <16 x i16> @llvm.loongarch.lasx.xvrepli.h(i32) -+declare <8 x i32> @llvm.loongarch.lasx.xvrepli.w(i32) -+declare <4 x i64> @llvm.loongarch.lasx.xvrepli.d(i32) -+ -+declare <4 x double> @llvm.loongarch.lasx.xvpickve.d.f(<4 x double>, i32) -+declare <8 x float> @llvm.loongarch.lasx.xvpickve.w.f(<8 x float>, i32) -+ -+define <32 x i8> @lasx_xvrepli_b() { -+; CHECK-LABEL: lasx_xvrepli_b: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvldi $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <32 x i8> @llvm.loongarch.lasx.xvrepli.b(i32 2) -+ ret <32 x i8> %0 -+} -+ -+define <16 x i16> @lasx_xvrepli_h() { -+; CHECK-LABEL: lasx_xvrepli_h: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvldi $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <16 x i16> @llvm.loongarch.lasx.xvrepli.h(i32 2) -+ ret <16 x i16> %0 -+} -+ -+define <8 x i32> @lasx_xvrepli_w() { -+; CHECK-LABEL: lasx_xvrepli_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvldi $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <8 x i32> @llvm.loongarch.lasx.xvrepli.w(i32 2) -+ ret <8 x i32> %0 -+} -+ -+define <4 x i64> @lasx_xvrepli_d() { -+; CHECK-LABEL: lasx_xvrepli_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvldi $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <4 x i64> @llvm.loongarch.lasx.xvrepli.d(i32 2) -+ ret <4 x i64> %0 -+} -+ -+define <4 x double> @lasx_xvpickve_d_f(<4 x double> %a) { -+; CHECK-LABEL: lasx_xvpickve_d_f: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvpickve.d $xr0, $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <4 x double> @llvm.loongarch.lasx.xvpickve.d.f(<4 x double> %a, i32 2) -+ ret <4 x double> %0 -+} -+ -+define <8 x float> @lasx_xvpickve_w_f(<8 x float> %a) { -+; CHECK-LABEL: lasx_xvpickve_w_f: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvpickve.w $xr0, $xr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <8 x float> @llvm.loongarch.lasx.xvpickve.w.f(<8 x float> %a, i32 2) -+ ret <8 x float> %0 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll -new file mode 100644 -index 000000000..b40698104 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll -@@ -0,0 +1,46 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <32 x i8> @clri8(<32 x i8> %0, <32 x i8> %1) { -+; CHECK-LABEL: clri8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitclr.b $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = shl <32 x i8> , %1 -+ %4 = xor <32 x i8> %3, -+ %5 = and <32 x i8> %4, %0 -+ ret <32 x i8> %5 -+} -+ -+define <16 x i16> @clri16(<16 x i16> %0, <16 x i16> %1) { -+; CHECK-LABEL: clri16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitclr.h $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = shl <16 x i16> , %1 -+ %4 = xor <16 x i16> %3, -+ %5 = and <16 x i16> %4, %0 -+ ret <16 x i16> %5 -+} -+ -+define <8 x i32> @clri32(<8 x i32> %0, <8 x i32> %1) { -+; CHECK-LABEL: clri32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitclr.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = shl <8 x i32> , %1 -+ %4 = xor <8 x i32> %3, -+ %5 = and <8 x i32> %4, %0 -+ ret <8 x i32> %5 -+} -+ -+define <4 x i64> @clri64(<4 x i64> %0, <4 x i64> %1) { -+; CHECK-LABEL: clri64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitclr.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = shl <4 x i64> , %1 -+ %4 = xor <4 x i64> %3, -+ %5 = and <4 x i64> %4, %0 -+ ret <4 x i64> %5 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll -new file mode 100644 -index 000000000..ff28569a1 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll -@@ -0,0 +1,130 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @not_v4i64(<4 x i64> %a) { -+; CHECK-LABEL: not_v4i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i64> %a, -+ ret <4 x i64> %not -+} -+ -+define <8 x i32> @not_v8i32(<8 x i32> %a) { -+; CHECK-LABEL: not_v8i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i32> %a, -+ ret <8 x i32> %not -+} -+ -+define <16 x i16> @not_v16i16(<16 x i16> %a) { -+; CHECK-LABEL: not_v16i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i16> %a, -+ ret <16 x i16> %not -+} -+ -+define <32 x i8> @not_v32i8(<32 x i8> %a) { -+; CHECK-LABEL: not_v32i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvxori.b $xr0, $xr0, 255 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <32 x i8> %a, -+ ret <32 x i8> %not -+} -+ -+define <4 x i64> @andn_v4i64(<4 x i64> %a, <4 x i64> %b) { -+; CHECK-LABEL: andn_v4i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i64> %b, -+ %and = and <4 x i64> %not, %a -+ ret <4 x i64> %and -+} -+ -+define <8 x i32> @andn_v8i32(<8 x i32> %a, <8 x i32> %b) { -+; CHECK-LABEL: andn_v8i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i32> %b, -+ %and = and <8 x i32> %not, %a -+ ret <8 x i32> %and -+} -+ -+define <16 x i16> @andn_v16i16(<16 x i16> %a, <16 x i16> %b) { -+; CHECK-LABEL: andn_v16i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i16> %b, -+ %and = and <16 x i16> %not, %a -+ ret <16 x i16> %and -+} -+ -+define <32 x i8> @andn_v32i8(<32 x i8> %a, <32 x i8> %b) { -+; CHECK-LABEL: andn_v32i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <32 x i8> %b, -+ %and = and <32 x i8> %not, %a -+ ret <32 x i8> %and -+} -+ -+define <4 x i64> @orn_v4i64(<4 x i64> %a, <4 x i64> %b) { -+; CHECK-LABEL: orn_v4i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i64> %b, -+ %or = or <4 x i64> %not, %a -+ ret <4 x i64> %or -+} -+ -+define <8 x i32> @orn_v8i32(<8 x i32> %a, <8 x i32> %b) { -+; CHECK-LABEL: orn_v8i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i32> %b, -+ %or = or <8 x i32> %not, %a -+ ret <8 x i32> %or -+} -+ -+define <16 x i16> @orn_v16i16(<16 x i16> %a, <16 x i16> %b) { -+; CHECK-LABEL: orn_v16i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i16> %b, -+ %or = or <16 x i16> %not, %a -+ ret <16 x i16> %or -+} -+ -+define <32 x i8> @orn_v32i8(<32 x i8> %a, <32 x i8> %b) { -+; CHECK-LABEL: orn_v32i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <32 x i8> %b, -+ %or = or <32 x i8> %not, %a -+ ret <32 x i8> %or -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll -new file mode 100644 -index 000000000..443262eac ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll -@@ -0,0 +1,38 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <32 x i8> @seti8(<32 x i8>) { -+; CHECK-LABEL: seti8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitseti.b $xr0, $xr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <32 x i8> %0, -+ ret <32 x i8> %2 -+} -+ -+define <16 x i16> @seti16(<16 x i16>) { -+; CHECK-LABEL: seti16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitseti.h $xr0, $xr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <16 x i16> %0, -+ ret <16 x i16> %2 -+} -+ -+define <8 x i32> @seti32(<8 x i32>) { -+; CHECK-LABEL: seti32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitseti.w $xr0, $xr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <8 x i32> %0, -+ ret <8 x i32> %2 -+} -+ -+define <4 x i64> @seti64(<4 x i64>) { -+; CHECK-LABEL: seti64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvbitseti.d $xr0, $xr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <4 x i64> %0, -+ ret <4 x i64> %2 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll -new file mode 100644 -index 000000000..965cfe94c ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll -@@ -0,0 +1,19 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @shuffle_v4i64_1032(<4 x i64> %vj, <4 x i64> %vk) { -+; CHECK-LABEL: shuffle_v4i64_1032: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvpickve2gr.d $r4, $xr0, 2 -+; CHECK-NEXT: xvpickve2gr.d $r5, $xr0, 3 -+; CHECK-NEXT: xvpickve2gr.d $r6, $xr0, 0 -+; CHECK-NEXT: xvpickve2gr.d $r7, $xr0, 1 -+; CHECK-NEXT: xvinsgr2vr.d $xr0, $r7, 0 -+; CHECK-NEXT: xvinsgr2vr.d $xr0, $r6, 1 -+; CHECK-NEXT: xvinsgr2vr.d $xr0, $r5, 2 -+; CHECK-NEXT: xvinsgr2vr.d $xr0, $r4, 3 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <4 x i64> %vj, <4 x i64> %vk, <4 x i32> -+ ret <4 x i64> %vd -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll -new file mode 100644 -index 000000000..7bd3dca73 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll -@@ -0,0 +1,65 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @s_v4i32_v4i64(<4 x i32> %a0) { -+; CHECK-LABEL: s_v4i32_v4i64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ %1 = sext <4 x i32> %a0 to <4 x i64> -+ ret <4 x i64> %1 -+} -+ -+define <4 x i64> @z_v4i32_v4i64(<4 x i32> %a0) { -+; CHECK-LABEL: z_v4i32_v4i64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ %1 = zext <4 x i32> %a0 to <4 x i64> -+ ret <4 x i64> %1 -+} -+ -+define <16 x i16> @s_v16i8_v16i16(<16 x i8> %A) { -+; CHECK-LABEL: s_v16i8_v16i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ entry: -+ %B = sext <16 x i8> %A to <16 x i16> -+ ret <16 x i16> %B -+} -+ -+define <16 x i16> @z_v16i8_v16i16(<16 x i8> %A) { -+; CHECK-LABEL: z_v16i8_v16i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ entry: -+ %B = zext <16 x i8> %A to <16 x i16> -+ ret <16 x i16> %B -+} -+ -+define <8 x i32> @s_v8i16_v8i32(<8 x i16> %x) { -+; CHECK-LABEL: s_v8i16_v8i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ %1 = sext <8 x i16> %x to <8 x i32> -+ ret <8 x i32> %1 -+} -+ -+define <8 x i32> @z_v8i16_v8i32(<8 x i16> %x) { -+; CHECK-LABEL: z_v8i16_v8i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 -+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0 -+; CHECK-NEXT: jr $ra -+ %1 = zext <8 x i16> %x to <8 x i32> -+ ret <8 x i32> %1 -+} -+ -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll -new file mode 100644 -index 000000000..a849fef3e ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll -@@ -0,0 +1,62 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <32 x i8> @xvaddab(<32 x i8>, <32 x i8>) { -+; CHECK-LABEL: xvaddab: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvadda.b $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <32 x i8> %0, zeroinitializer -+ %4 = sub <32 x i8> zeroinitializer, %0 -+ %5 = select <32 x i1> %3, <32 x i8> %4, <32 x i8> %0 -+ %6 = icmp slt <32 x i8> %1, zeroinitializer -+ %7 = sub <32 x i8> zeroinitializer, %1 -+ %8 = select <32 x i1> %6, <32 x i8> %7, <32 x i8> %1 -+ %9 = add <32 x i8> %5, %8 -+ ret <32 x i8> %9 -+} -+ -+define <16 x i16> @xvaddah(<16 x i16>, <16 x i16>) { -+; CHECK-LABEL: xvaddah: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvadda.h $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <16 x i16> %0, zeroinitializer -+ %4 = sub <16 x i16> zeroinitializer, %0 -+ %5 = select <16 x i1> %3, <16 x i16> %4, <16 x i16> %0 -+ %6 = icmp slt <16 x i16> %1, zeroinitializer -+ %7 = sub <16 x i16> zeroinitializer, %1 -+ %8 = select <16 x i1> %6, <16 x i16> %7, <16 x i16> %1 -+ %9 = add <16 x i16> %5, %8 -+ ret <16 x i16> %9 -+} -+ -+define <8 x i32> @xvaddaw(<8 x i32>, <8 x i32>) { -+; CHECK-LABEL: xvaddaw: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvadda.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <8 x i32> %0, zeroinitializer -+ %4 = sub nsw <8 x i32> zeroinitializer, %0 -+ %5 = select <8 x i1> %3, <8 x i32> %4, <8 x i32> %0 -+ %6 = icmp slt <8 x i32> %1, zeroinitializer -+ %7 = sub nsw <8 x i32> zeroinitializer, %1 -+ %8 = select <8 x i1> %6, <8 x i32> %7, <8 x i32> %1 -+ %9 = add nuw nsw <8 x i32> %5, %8 -+ ret <8 x i32> %9 -+} -+ -+define <4 x i64> @xvaddad(<4 x i64>, <4 x i64>) { -+; CHECK-LABEL: xvaddad: -+; CHECK: # %bb.0: -+; CHECK-NEXT: xvadda.d $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <4 x i64> %0, zeroinitializer -+ %4 = sub nsw <4 x i64> zeroinitializer, %0 -+ %5 = select <4 x i1> %3, <4 x i64> %4, <4 x i64> %0 -+ %6 = icmp slt <4 x i64> %1, zeroinitializer -+ %7 = sub nsw <4 x i64> zeroinitializer, %1 -+ %8 = select <4 x i1> %6, <4 x i64> %7, <4 x i64> %1 -+ %9 = add nuw nsw <4 x i64> %5, %8 -+ ret <4 x i64> %9 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll -new file mode 100644 -index 000000000..eb2c493d2 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll -@@ -0,0 +1,98 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @svaddev(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svaddev: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvaddwev.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = add nsw <8 x i32> %c, %b -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = sext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @uvaddev(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvaddev: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvaddwev.d.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = add <8 x i32> %c, %b -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = zext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @uvsubev(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvsubev: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvsubwev.d.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = sub <8 x i32> %b, %c -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = zext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @svsubev(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svsubev: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvsubwev.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = sub nsw <8 x i32> %b, %c -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = sext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @uvaddod(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvaddod: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvaddwod.d.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = add <8 x i32> %c, %b -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = zext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @svaddod(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svaddod: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvaddwod.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = add nsw <8 x i32> %c, %b -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = sext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @uvsubod(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: uvsubod: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvsubwod.d.wu $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = sub <8 x i32> %b, %c -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = zext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -+ -+define <4 x i64> @svsubod(<8 x i32> %b, <8 x i32> %c) { -+; CHECK-LABEL: svsubod: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvsubwod.d.w $xr0, $xr0, $xr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = sub nsw <8 x i32> %b, %c -+ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> -+ %2 = sext <4 x i32> %1 to <4 x i64> -+ ret <4 x i64> %2 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll -new file mode 100644 -index 000000000..5b452c5eb ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll -@@ -0,0 +1,21 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <4 x i64> @mul(<4 x i64> %a, <8 x i32> %m, <8 x i32> %n) { -+; CHECK-LABEL: mul: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvhaddw.d.w $xr0, $xr1, $xr2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = shufflevector <8 x i32> %n, <8 x i32> undef, <2 x i32> -+ %1 = shufflevector <8 x i32> %m, <8 x i32> undef, <2 x i32> -+ %2 = add nsw <2 x i32> %0, %1 -+ %3 = sext <2 x i32> %2 to <2 x i64> -+ %4 = shufflevector <8 x i32> %n, <8 x i32> undef, <2 x i32> -+ %5 = shufflevector <8 x i32> %m, <8 x i32> undef, <2 x i32> -+ %6 = add nsw <2 x i32> %4, %5 -+ %7 = sext <2 x i32> %6 to <2 x i64> -+ %vecins16 = shufflevector <2 x i64> %3, <2 x i64> %7, <4 x i32> -+ ret <4 x i64> %vecins16 -+} -+ -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll -new file mode 100644 -index 000000000..11f96f435 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll -@@ -0,0 +1,32 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <32 x i8> @xvilvhb(<32 x i8> %vj, <32 x i8> %vk) { -+; CHECK-LABEL: xvilvhb: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvh.b $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <32 x i8> %vj, <32 x i8> %vk, <32 x i32> -+ ret <32 x i8> %vd -+} -+ -+define <16 x i16> @xvilvhh(<16 x i16> %vj, <16 x i16> %vk) { -+; CHECK-LABEL: xvilvhh: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvh.h $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <16 x i16> %vj, <16 x i16> %vk, <16 x i32> -+ ret <16 x i16> %vd -+} -+ -+define <8 x i32> @xvilvhw(<8 x i32> %vj, <8 x i32> %vk) { -+; CHECK-LABEL: xvilvhw: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvh.w $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <8 x i32> %vj, <8 x i32> %vk, <8 x i32> -+ ret <8 x i32> %vd -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll -new file mode 100644 -index 000000000..7249bc76c ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll -@@ -0,0 +1,32 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s -+ -+define <32 x i8> @xvilvlb(<32 x i8> %vj, <32 x i8> %vk) { -+; CHECK-LABEL: xvilvlb: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvl.b $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <32 x i8> %vj, <32 x i8> %vk, <32 x i32> -+ ret <32 x i8> %vd -+} -+ -+define <16 x i16> @xvilvlh(<16 x i16> %vj, <16 x i16> %vk) { -+; CHECK-LABEL: xvilvlh: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvl.h $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <16 x i16> %vj, <16 x i16> %vk, <16 x i32> -+ ret <16 x i16> %vd -+} -+ -+define <8 x i32> @xvilvlw(<8 x i32> %vj, <8 x i32> %vk) { -+; CHECK-LABEL: xvilvlw: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xvilvl.w $xr0, $xr1, $xr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %vd = shufflevector <8 x i32> %vj, <8 x i32> %vk, <8 x i32> -+ ret <8 x i32> %vd -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll -new file mode 100644 -index 000000000..8395b264f ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll -@@ -0,0 +1,70 @@ -+; Check whether ld.w/ld.d/ldptr.w/ldptr.d/ldx.w/ldx.d instructions are properly generated -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define signext i32 @ld_w(i32* %p) { -+; CHECK-LABEL: ld_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ld.w $r4, $r4, 2044 -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i32, i32* %p, i64 511 -+ %val = load i32, i32* %addr, align 4 -+ ret i32 %val -+} -+ -+define signext i32 @ldptr_w(i32* %p) { -+; CHECK-LABEL: ldptr_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ldptr.w $r4, $r4, 2048 -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i32, i32* %p, i64 512 -+ %val = load i32, i32* %addr, align 4 -+ ret i32 %val -+} -+ -+define signext i32 @ldx_w(i32* %p) { -+; CHECK-LABEL: ldx_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r[[REG:[0-9]+]], 8 -+; CHECK-NEXT: ldx.w $r4, $r4, $r[[REG:[0-9]+]] -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i32, i32* %p, i64 8192 -+ %val = load i32, i32* %addr, align 4 -+ ret i32 %val -+} -+ -+define i64 @ld_d(i64* %p) { -+; CHECK-LABEL: ld_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ld.d $r4, $r4, 2040 -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i64, i64* %p, i64 255 -+ %val = load i64, i64* %addr, align 8 -+ ret i64 %val -+} -+ -+define i64 @ldptr_d(i64* %p) { -+; CHECK-LABEL: ldptr_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ldptr.d $r4, $r4, 2048 -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i64, i64* %p, i64 256 -+ %val = load i64, i64* %addr, align 8 -+ ret i64 %val -+} -+ -+define i64 @ldx_d(i64* %p) { -+; CHECK-LABEL: ldx_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: lu12i.w $r[[REG:[0-9]+]], 8 -+; CHECK-NEXT: ldx.d $r4, $r4, $r[[REG:[0-9]+]] -+; CHECK-NEXT: jr $ra -+entry: -+ %addr = getelementptr inbounds i64, i64* %p, i64 4096 -+ %val = load i64, i64* %addr, align 8 -+ ret i64 %val -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg -index a54f5aeca..6223fc691 100644 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg -@@ -1,13 +1,3 @@ --import os -- --config.suffixes = ['.ll', '.mir', '.test', '.txt'] -- --extract_section_path = os.path.join(config.llvm_src_root, -- 'utils', 'extract-section.py') -- --config.substitutions.append(('extract-section', -- "'%s' %s %s" % (config.python_executable, -- extract_section_path, '--bits-endian little'))) -- - if not 'LoongArch' in config.root.targets: - config.unsupported = True -+ -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll -new file mode 100644 -index 000000000..c1029c1ff ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll -@@ -0,0 +1,171 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define signext i32 @foo32(i32 signext %a) { -+; CHECK-LABEL: foo32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: sltui $r4, $r4, 1 -+; CHECK-NEXT: jr $ra -+entry: -+ %tobool = icmp eq i32 %a, 0 -+ %conv = zext i1 %tobool to i32 -+ ret i32 %conv -+} -+ -+define i64 @foo(i64 %a) { -+; CHECK-LABEL: foo: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: sltui $r4, $r4, 1 -+; CHECK-NEXT: jr $ra -+entry: -+ %tobool = icmp eq i64 %a, 0 -+ %conv = zext i1 %tobool to i64 -+ ret i64 %conv -+} -+ -+define i64 @not(i64 %a) { -+; CHECK-LABEL: not: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i64 %a, -1 -+ ret i64 %not -+} -+ -+define i64 @and(i64 %a, i64 %b) { -+; CHECK-LABEL: and: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: and $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %and = and i64 %b, %a -+ ret i64 %and -+} -+ -+define i64 @or(i64 %a, i64 %b) { -+; CHECK-LABEL: or: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: or $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %or = or i64 %b, %a -+ ret i64 %or -+} -+ -+define i64 @xor(i64 %a, i64 %b) { -+; CHECK-LABEL: xor: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xor $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %xor = xor i64 %b, %a -+ ret i64 %xor -+} -+ -+define i64 @nor(i64 %a, i64 %b) { -+; CHECK-LABEL: nor: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: nor $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %or = or i64 %b, %a -+ %not = xor i64 %or, -1 -+ ret i64 %not -+} -+ -+define i64 @andn(i64 %a, i64 %b) { -+; CHECK-LABEL: andn: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: andn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i64 %b, -1 -+ %and = and i64 %not, %a -+ ret i64 %and -+} -+ -+define signext i32 @andn32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: andn32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: andn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i32 %b, -1 -+ %and = and i32 %not, %a -+ ret i32 %and -+} -+ -+define i64 @orn(i64 %a, i64 %b) { -+; CHECK-LABEL: orn: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: orn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i64 %b, -1 -+ %or = or i64 %not, %a -+ ret i64 %or -+} -+ -+define signext i32 @orn32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: orn32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: orn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i32 %b, -1 -+ %or = or i32 %not, %a -+ ret i32 %or -+} -+ -+define signext i32 @and32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: and32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: and $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %and = and i32 %b, %a -+ ret i32 %and -+} -+ -+define signext i32 @or32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: or32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: or $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %or = or i32 %b, %a -+ ret i32 %or -+} -+ -+define signext i32 @xor32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: xor32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: xor $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %xor = xor i32 %b, %a -+ ret i32 %xor -+} -+ -+define signext i32 @nor32(i32 signext %a, i32 signext %b) { -+; CHECK-LABEL: nor32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: nor $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %or = or i32 %b, %a -+ %not = xor i32 %or, -1 -+ ret i32 %not -+} -+ -+define signext i32 @not32(i32 signext %a) { -+; CHECK-LABEL: not32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor i32 %a, -1 -+ ret i32 %not -+} -+ -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll -new file mode 100644 -index 000000000..54e4a5f2d ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll -@@ -0,0 +1,12 @@ -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define signext i32 @foo(i32 %a) { -+; CHECK-LABEL: foo: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: bstrpick.d $r4, $r4, 31, 1 -+; CHECK-NEXT: jr $ra -+entry: -+ %b = lshr i32 %a, 1 -+ ret i32 %b -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll -new file mode 100644 -index 000000000..97b23be80 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll -@@ -0,0 +1,176 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+define <2 x i64> @build_lsx0(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx0: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -1 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx1(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx1: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu52i.d $r4, $zero, 2047 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx2(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx2: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 2048 -+; CHECK-NEXT: lu32i.d $r4, 524287 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx3(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx3: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu52i.d $r4, $r4, -1 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx4(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx4: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ori $r4, $zero, 4095 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx5(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx5: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx6(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx6: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx7(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx7: -+; CHECK: # %bb.0: -+; CHECK-NEXT: addi.w $r4, $zero, -2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx8(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx9(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx9: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -1 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx10(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx10: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: lu32i.d $r4, 0 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx11(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx11: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, 524287 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -1 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx12(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx12: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2047 -+; CHECK-NEXT: lu52i.d $r4, $r4, 2047 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -+ -+define <2 x i64> @build_lsx13(<2 x i64> %a) { -+; CHECK-LABEL: build_lsx13: -+; CHECK: # %bb.0: -+; CHECK-NEXT: lu12i.w $r4, -524288 -+; CHECK-NEXT: ori $r4, $r4, 2048 -+; CHECK-NEXT: lu32i.d $r4, -524288 -+; CHECK-NEXT: lu52i.d $r4, $r4, 0 -+; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 -+; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %b = add <2 x i64> %a, -+ ret <2 x i64> %b -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll -new file mode 100644 -index 000000000..37cb6dfc9 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll -@@ -0,0 +1,34 @@ -+; A basic inline assembly test -+ -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+@v2i64_r = global <2 x i64> zeroinitializer, align 16 -+ -+define void @test1() nounwind { -+entry: -+ ; CHECK-LABEL: test1: -+ %0 = call <2 x i64> asm "vldi ${0:w}, 1", "=f"() -+ ; CHECK: vldi $vr{{[1-3]?[0-9]}}, 1 -+ store <2 x i64> %0, <2 x i64>* @v2i64_r -+ ret void -+} -+ -+define void @test2() nounwind { -+entry: -+ ; CHECK-LABEL: test2: -+ %0 = load <2 x i64>, <2 x i64>* @v2i64_r -+ %1 = call <2 x i64> asm "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f"(<2 x i64> %0) -+ ; CHECK: vaddi.wu $vr{{[1-3]?[0-9]}}, $vr{{[1-3]?[0-9]}}, 1 -+ store <2 x i64> %1, <2 x i64>* @v2i64_r -+ ret void -+} -+ -+define void @test3() nounwind { -+entry: -+ ; CHECK-LABEL: test3: -+ %0 = load <2 x i64>, <2 x i64>* @v2i64_r -+ %1 = call <2 x i64> asm sideeffect "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f,~{$vr0}"(<2 x i64> %0) -+ ; CHECK: vaddi.wu $vr{{([1-9]|[1-3][0-9])}}, $vr{{([1-9]|[1-3][0-9])}}, 1 -+ store <2 x i64> %1, <2 x i64>* @v2i64_r -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll -new file mode 100644 -index 000000000..60ff93095 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll -@@ -0,0 +1,92 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+declare <16 x i8> @llvm.loongarch.lsx.vsrlrni.b.h(<16 x i8>, <16 x i8>, i32) -+declare <8 x i16> @llvm.loongarch.lsx.vsrlrni.h.w(<8 x i16>, <8 x i16>, i32) -+declare <4 x i32> @llvm.loongarch.lsx.vsrlrni.w.d(<4 x i32>, <4 x i32>, i32) -+declare <2 x i64> @llvm.loongarch.lsx.vsrlrni.d.q(<2 x i64>, <2 x i64>, i32) -+ -+declare <16 x i8> @llvm.loongarch.lsx.vrepli.b(i32) -+declare <8 x i16> @llvm.loongarch.lsx.vrepli.h(i32) -+declare <4 x i32> @llvm.loongarch.lsx.vrepli.w(i32) -+declare <2 x i64> @llvm.loongarch.lsx.vrepli.d(i32) -+ -+define <16 x i8> @lsx_vsrlrni_b_h(<16 x i8> %a, <16 x i8> %b) { -+; CHECK-LABEL: lsx_vsrlrni_b_h: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vsrlrni.b.h $vr0, $vr1, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <16 x i8> @llvm.loongarch.lsx.vsrlrni.b.h(<16 x i8> %a, <16 x i8> %b, i32 2) -+ ret <16 x i8> %0 -+} -+ -+define <8 x i16> @lsx_vsrlrni_h_w(<8 x i16> %a, <8 x i16> %b) { -+; CHECK-LABEL: lsx_vsrlrni_h_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vsrlrni.h.w $vr0, $vr1, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <8 x i16> @llvm.loongarch.lsx.vsrlrni.h.w(<8 x i16> %a, <8 x i16> %b, i32 2) -+ ret <8 x i16> %0 -+} -+ -+define <4 x i32> @lsx_vsrlrni_w_d(<4 x i32> %a, <4 x i32> %b) { -+; CHECK-LABEL: lsx_vsrlrni_w_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vsrlrni.w.d $vr0, $vr1, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <4 x i32> @llvm.loongarch.lsx.vsrlrni.w.d(<4 x i32> %a, <4 x i32> %b, i32 2) -+ ret <4 x i32> %0 -+} -+ -+define <2 x i64> @lsx_vsrlrni_d_q(<2 x i64> %a, <2 x i64> %b) { -+; CHECK-LABEL: lsx_vsrlrni_d_q: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vsrlrni.d.q $vr0, $vr1, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <2 x i64> @llvm.loongarch.lsx.vsrlrni.d.q(<2 x i64> %a, <2 x i64> %b, i32 2) -+ ret <2 x i64> %0 -+} -+ -+define <16 x i8> @lsx_vrepli_b() { -+; CHECK-LABEL: lsx_vrepli_b: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vldi $vr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <16 x i8> @llvm.loongarch.lsx.vrepli.b(i32 2) -+ ret <16 x i8> %0 -+} -+ -+define <8 x i16> @lsx_vrepli_h() { -+; CHECK-LABEL: lsx_vrepli_h: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vldi $vr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <8 x i16> @llvm.loongarch.lsx.vrepli.h(i32 2) -+ ret <8 x i16> %0 -+} -+ -+define <4 x i32> @lsx_vrepli_w() { -+; CHECK-LABEL: lsx_vrepli_w: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vldi $vr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <4 x i32> @llvm.loongarch.lsx.vrepli.w(i32 2) -+ ret <4 x i32> %0 -+} -+ -+define <2 x i64> @lsx_vrepli_d() { -+; CHECK-LABEL: lsx_vrepli_d: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vldi $vr0, 2 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = tail call <2 x i64> @llvm.loongarch.lsx.vrepli.d(i32 2) -+ ret <2 x i64> %0 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll -new file mode 100644 -index 000000000..0dd29b27e ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll -@@ -0,0 +1,132 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+define <2 x i64> @not_v2i64(<2 x i64> %a) { -+; CHECK-LABEL: not_v2i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <2 x i64> %a, -+ ret <2 x i64> %not -+} -+ -+define <4 x i32> @not_v4i32(<4 x i32> %a) { -+; CHECK-LABEL: not_v4i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i32> %a, -+ ret <4 x i32> %not -+} -+ -+define <8 x i16> @not_v8i16(<8 x i16> %a) { -+; CHECK-LABEL: not_v8i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i16> %a, -+ ret <8 x i16> %not -+} -+ -+define <16 x i8> @not_v16i8(<16 x i8> %a) { -+; CHECK-LABEL: not_v16i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vxori.b $vr0, $vr0, 255 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i8> %a, -+ ret <16 x i8> %not -+} -+ -+ -+define <2 x i64> @andn_v2i64(<2 x i64> %a, <2 x i64> %b) { -+; CHECK-LABEL: andn_v2i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <2 x i64> %b, -+ %and = and <2 x i64> %not, %a -+ ret <2 x i64> %and -+} -+ -+define <4 x i32> @andn_v4i32(<4 x i32> %a, <4 x i32> %b) { -+; CHECK-LABEL: andn_v4i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i32> %b, -+ %and = and <4 x i32> %not, %a -+ ret <4 x i32> %and -+} -+ -+define <8 x i16> @andn_v8i16(<8 x i16> %a, <8 x i16> %b) { -+; CHECK-LABEL: andn_v8i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i16> %b, -+ %and = and <8 x i16> %not, %a -+ ret <8 x i16> %and -+} -+ -+define <16 x i8> @andn_v16i8(<16 x i8> %a, <16 x i8> %b) { -+; CHECK-LABEL: andn_v16i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i8> %b, -+ %and = and <16 x i8> %not, %a -+ ret <16 x i8> %and -+} -+ -+ -+define <2 x i64> @orn_v2i64(<2 x i64> %a, <2 x i64> %b) { -+; CHECK-LABEL: orn_v2i64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <2 x i64> %b, -+ %or = or <2 x i64> %not, %a -+ ret <2 x i64> %or -+} -+ -+define <4 x i32> @orn_v4i32(<4 x i32> %a, <4 x i32> %b) { -+; CHECK-LABEL: orn_v4i32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <4 x i32> %b, -+ %or = or <4 x i32> %not, %a -+ ret <4 x i32> %or -+} -+ -+define <8 x i16> @orn_v8i16(<8 x i16> %a, <8 x i16> %b) { -+; CHECK-LABEL: orn_v8i16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <8 x i16> %b, -+ %or = or <8 x i16> %not, %a -+ ret <8 x i16> %or -+} -+ -+define <16 x i8> @orn_v16i8(<16 x i8> %a, <16 x i8> %b) { -+; CHECK-LABEL: orn_v16i8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %not = xor <16 x i8> %b, -+ %or = or <16 x i8> %not, %a -+ ret <16 x i8> %or -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll -new file mode 100644 -index 000000000..951254baa ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll -@@ -0,0 +1,50 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+define <16 x i8> @clri8(<16 x i8> %b, <16 x i8> %c) { -+; CHECK-LABEL: clri8: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vbitclr.b $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %shl = shl <16 x i8> , %c -+ %xor = xor <16 x i8> %shl, -+ %and = and <16 x i8> %xor, %b -+ ret <16 x i8> %and -+} -+ -+define <8 x i16> @clri16(<8 x i16> %b, <8 x i16> %c) { -+; CHECK-LABEL: clri16: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vbitclr.h $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %shl = shl <8 x i16> , %c -+ %xor = xor <8 x i16> %shl, -+ %and = and <8 x i16> %xor, %b -+ ret <8 x i16> %and -+} -+ -+define <4 x i32> @clri32(<4 x i32> %b, <4 x i32> %c) { -+; CHECK-LABEL: clri32: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vbitclr.w $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %shl = shl <4 x i32> , %c -+ %xor = xor <4 x i32> %shl, -+ %and = and <4 x i32> %xor, %b -+ ret <4 x i32> %and -+} -+ -+define <2 x i64> @clri64(<2 x i64> %b, <2 x i64> %c) { -+; CHECK-LABEL: clri64: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: vbitclr.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+entry: -+ %shl = shl <2 x i64> , %c -+ %xor = xor <2 x i64> %shl, -+ %and = and <2 x i64> %xor, %b -+ ret <2 x i64> %and -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll -new file mode 100644 -index 000000000..69f19297d ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll -@@ -0,0 +1,38 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+define <16 x i8> @seti8(<16 x i8>) { -+; CHECK-LABEL: seti8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vbitseti.b $vr0, $vr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <16 x i8> %0, -+ ret <16 x i8> %2 -+} -+ -+define <8 x i16> @seti16(<8 x i16>) { -+; CHECK-LABEL: seti16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vbitseti.h $vr0, $vr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <8 x i16> %0, -+ ret <8 x i16> %2 -+} -+ -+define <4 x i32> @seti32(<4 x i32>) { -+; CHECK-LABEL: seti32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vbitseti.w $vr0, $vr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <4 x i32> %0, -+ ret <4 x i32> %2 -+} -+ -+define <2 x i64> @seti64(<2 x i64>) { -+; CHECK-LABEL: seti64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vbitseti.d $vr0, $vr0, 6 -+; CHECK-NEXT: jr $ra -+ %2 = or <2 x i64> %0, -+ ret <2 x i64> %2 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll -new file mode 100644 -index 000000000..4c987fb1b ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll -@@ -0,0 +1,62 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s -+ -+define <16 x i8> @vaddab(<16 x i8>, <16 x i8>) { -+; CHECK-LABEL: vaddab: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vadda.b $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <16 x i8> %0, zeroinitializer -+ %4 = sub <16 x i8> zeroinitializer, %0 -+ %5 = select <16 x i1> %3, <16 x i8> %4, <16 x i8> %0 -+ %6 = icmp slt <16 x i8> %1, zeroinitializer -+ %7 = sub <16 x i8> zeroinitializer, %1 -+ %8 = select <16 x i1> %6, <16 x i8> %7, <16 x i8> %1 -+ %9 = add <16 x i8> %5, %8 -+ ret <16 x i8> %9 -+} -+ -+define <8 x i16> @vaddah(<8 x i16>, <8 x i16>) { -+; CHECK-LABEL: vaddah: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vadda.h $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <8 x i16> %0, zeroinitializer -+ %4 = sub <8 x i16> zeroinitializer, %0 -+ %5 = select <8 x i1> %3, <8 x i16> %4, <8 x i16> %0 -+ %6 = icmp slt <8 x i16> %1, zeroinitializer -+ %7 = sub <8 x i16> zeroinitializer, %1 -+ %8 = select <8 x i1> %6, <8 x i16> %7, <8 x i16> %1 -+ %9 = add <8 x i16> %5, %8 -+ ret <8 x i16> %9 -+} -+ -+define <4 x i32> @vaddaw(<4 x i32>, <4 x i32>) { -+; CHECK-LABEL: vaddaw: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vadda.w $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <4 x i32> %0, zeroinitializer -+ %4 = sub nsw <4 x i32> zeroinitializer, %0 -+ %5 = select <4 x i1> %3, <4 x i32> %4, <4 x i32> %0 -+ %6 = icmp slt <4 x i32> %1, zeroinitializer -+ %7 = sub nsw <4 x i32> zeroinitializer, %1 -+ %8 = select <4 x i1> %6, <4 x i32> %7, <4 x i32> %1 -+ %9 = add nuw nsw <4 x i32> %5, %8 -+ ret <4 x i32> %9 -+} -+ -+define <2 x i64> @vaddad(<2 x i64>, <2 x i64>) { -+; CHECK-LABEL: vaddad: -+; CHECK: # %bb.0: -+; CHECK-NEXT: vadda.d $vr0, $vr0, $vr1 -+; CHECK-NEXT: jr $ra -+ %3 = icmp slt <2 x i64> %0, zeroinitializer -+ %4 = sub nsw <2 x i64> zeroinitializer, %0 -+ %5 = select <2 x i1> %3, <2 x i64> %4, <2 x i64> %0 -+ %6 = icmp slt <2 x i64> %1, zeroinitializer -+ %7 = sub nsw <2 x i64> zeroinitializer, %1 -+ %8 = select <2 x i1> %6, <2 x i64> %7, <2 x i64> %1 -+ %9 = add nuw nsw <2 x i64> %5, %8 -+ ret <2 x i64> %9 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll -new file mode 100644 -index 000000000..55fd40edd ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll -@@ -0,0 +1,7 @@ -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define i32 @foo() { -+; CHECK: lu12i.w $r4, -1 -+entry: -+ ret i32 -4096 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll -new file mode 100644 -index 000000000..c0c782fea ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll -@@ -0,0 +1,72 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -mcpu=la264 -o - %s | FileCheck -check-prefix=ALIGNED %s -+; RUN: llc -march=loongarch64 -mcpu=la364 -o - %s | FileCheck -check-prefix=ALIGNED %s -+; RUN: llc -march=loongarch64 -mcpu=la464 -o - %s | FileCheck -check-prefix=UNALIGNED %s -+ -+define i32 @i32_load(i32* %p) { -+; ALIGNED-LABEL: i32_load: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.hu $r4, $r4, 2 -+; ALIGNED-NEXT: slli.w $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+; -+; UNALIGNED-LABEL: i32_load: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.w $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define signext i32 @i32_sextload(i32* %p) { -+; ALIGNED-LABEL: i32_sextload: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.h $r4, $r4, 2 -+; ALIGNED-NEXT: slli.d $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+; -+; UNALIGNED-LABEL: i32_sextload: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.w $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define zeroext i32 @i32_zextload(i32* %p) { -+; ALIGNED-LABEL: i32_zextload: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.hu $r4, $r4, 2 -+; ALIGNED-NEXT: slli.d $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+; -+; UNALIGNED-LABEL: i32_zextload: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.wu $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define i64 @i64_load(i64* %p) { -+; ALIGNED-LABEL: i64_load: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.wu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.wu $r4, $r4, 4 -+; ALIGNED-NEXT: slli.d $r4, $r4, 32 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+; -+; UNALIGNED-LABEL: i64_load: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.d $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+ %tmp = load i64, i64* %p, align 4 -+ ret i64 %tmp -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir -deleted file mode 100644 -index 56793c583..000000000 ---- a/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir -+++ /dev/null -@@ -1,200 +0,0 @@ --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ --# RUN: | extract-section .text \ --# RUN: | FileCheck %s -check-prefix=CHECK-ENC --# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ --# RUN: | FileCheck %s -check-prefix=CHECK-ASM -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: I15 --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------------+--------------------------------------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------------+--------------------------------------------- --# opcode | imm15 --# ---------------------------------------------------+--------------------------------------------- -- ----- --# CHECK-LABEL: test_DBAR: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --# CHECK-ASM: dbar 0 --name: test_DBAR --body: | -- bb.0: -- DBAR 0 --... ----- --# CHECK-LABEL: test_IBAR: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --# CHECK-ASM: ibar 0 --name: test_IBAR --body: | -- bb.0: -- IBAR 0 --... ----- --# CHECK-LABEL: test_SYSCALL: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 --# CHECK-ASM: syscall 100 --name: test_SYSCALL --body: | -- bb.0: -- SYSCALL 100 --... ----- --# CHECK-LABEL: test_BREAK: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 --# CHECK-ASM: break 199 --name: test_BREAK --body: | -- bb.0: -- BREAK 199 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: I26 --# ------------------------------------------------------------------------------------------------- --# ------------------+-----------------------------------------------+------------------------------ --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------+-----------------------------------------------+------------------------------ --# opcode | imm26{15-0} | imm26{25-16} --# ------------------+-----------------------------------------------+------------------------------ -- ----- --# CHECK-LABEL: test_B: --# CHECK-ENC: 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 --# CHECK-ASM: b 80 --name: test_B --body: | -- bb.0: -- B 80 --... ----- --# CHECK-LABEL: test_BL: --# CHECK-ENC: 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 --# CHECK-ASM: bl 136 --name: test_BL --body: | -- bb.0: -- BL 136 --... -- --# -------------------------------------------------------------------------------------------------------- --# Encoding format: BSTR_W --# -------------------------------------------------------------------------------------------------------- --# ---------------------------------+--------------+---------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------+--------------+---------+--------------+--------------+--------------- --# opcode{11-1} | msb |opcode{0}| lsb | rj | rd --# ---------------------------------+--------------+---------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_BSTRINS_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bstrins.w $a0, $a1, 7, 2 --name: test_BSTRINS_W --body: | -- bb.0: -- $r4 = BSTRINS_W $r4, $r5, 7, 2 --... ----- --# CHECK-LABEL: test_BSTRPICK_W: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bstrpick.w $a0, $a1, 10, 4 --name: test_BSTRPICK_W --body: | -- bb.0: -- $r4 = BSTRPICK_W $r5, 10, 4 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: BSTR_D --# ------------------------------------------------------------------------------------------------- --# ------------------------------+-----------------+-----------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------+-----------------+-----------------+--------------+--------------- --# opcode | msb | lsb | rj | rd --# ------------------------------+-----------------+-----------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_BSTRINS_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bstrins.d $a0, $a1, 7, 2 --name: test_BSTRINS_D --body: | -- bb.0: -- $r4 = BSTRINS_D $r4, $r5, 7, 2 --... ----- --# CHECK-LABEL: test_BSTRPICK_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 --# CHECK-ASM: bstrpick.d $a0, $a1, 39, 22 --name: test_BSTRPICK_D --body: | -- bb.0: -- $r4 = BSTRPICK_D $r5, 39, 22 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: ASRT --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------------+--------------+--------------+--------------- --# opcode | rk | rj | 0x0 --# ---------------------------------------------------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_ASRTLE_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 --# CHECK-ASM: asrtle.d $a0, $a1 --name: test_ASRTLE_D --body: | -- bb.0: -- ASRTLE_D $r4, $r5 --... ----- --# CHECK-LABEL: test_ASRTGT_D: --# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 --# CHECK-ASM: asrtgt.d $a0, $a1 --name: test_ASRTGT_D --body: | -- bb.0: -- ASRTGT_D $r4, $r5 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: PRELD --# ------------------------------------------------------------------------------------------------- --# ------------------------------+-----------------------------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ------------------------------+-----------------------------------+--------------+--------------- --# opcode | imm12 | rj | imm5 --# ------------------------------+-----------------------------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_PRELD: --# CHECK-ENC: 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 1 1 1 1 --# CHECK-ASM: preld 15, $a0, 21 --name: test_PRELD --body: | -- bb.0: -- PRELD 15, $r4, 21 --... -- --# ------------------------------------------------------------------------------------------------- --# Encoding format: PRELDX --# ------------------------------------------------------------------------------------------------- --# ---------------------------------------------------+--------------+--------------+--------------- --# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 --# ---------------------------------------------------+--------------+--------------+--------------- --# opcode | rk | rj | imm5 --# ---------------------------------------------------+--------------+--------------+--------------- -- ----- --# CHECK-LABEL: test_PRELDX: --# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 1 0 1 1 --# CHECK-ASM: preldx 11, $a0, $a1 --name: test_PRELDX --body: | -- bb.0: -- PRELDX 11, $r4, $r5 -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll -new file mode 100644 -index 000000000..0b0660fca ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll -@@ -0,0 +1,29 @@ -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define i64 @get_r2() { -+; CHECK-LABEL: get_r2: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: move $r4, $tp -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = call i64 @llvm.read_register.i64(metadata !0) -+ ret i64 %0 -+} -+ -+define i64 @get_r21() { -+; CHECK-LABEL: get_r21: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: move $r4, $r21 -+; CHECK-NEXT: jr $ra -+entry: -+ %0 = call i64 @llvm.read_register.i64(metadata !1) -+ ret i64 %0 -+} -+ -+declare i64 @llvm.read_register.i64(metadata) -+ -+!llvm.named.register.$r2 = !{!0} -+!llvm.named.register.$r21 = !{!1} -+ -+!0 = !{!"$r2"} -+!1 = !{!"$r21"} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll -new file mode 100644 -index 000000000..a8ce63225 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll -@@ -0,0 +1,35 @@ -+; RUN: llc < %s -mtriple=loongarch64 -relocation-model=pic -o - | FileCheck %s -+ -+define void @foo(i32 %i) { -+entry: -+ switch i32 %i, label %if.end3 [ -+ i32 5, label %if.then -+ i32 7, label %if.then2 -+ ] -+ -+if.then: -+ tail call void @bar() #0 -+ br label %if.end3 -+ -+if.then2: -+ tail call void @bar() #0 -+ br label %if.end3 -+ -+if.end3: -+ tail call void @bar() #0 -+ ret void -+} -+ -+declare void @bar() -+ -+attributes #0 = { nomerge } -+ -+; CHECK-LABEL: foo: -+; CHECK: # %bb.0: # %entry -+; CHECK: .LBB0_1: # %entry -+; CHECK: .LBB0_2: # %if.then -+; CHECK-NEXT: bl bar -+; CHECK: .LBB0_3: # %if.then2 -+; CHECK-NEXT: bl bar -+; CHECK: .LBB0_4: # %if.end3 -+; CHECK: b bar -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll -new file mode 100644 -index 000000000..9aa8c4391 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll -@@ -0,0 +1,143 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define i8 @nor_i8(i8 %a, i8 %b) nounwind { -+; CHECK-LABEL: nor_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: or $r4, $r4, $r5 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %or = or i8 %a, %b -+ %neg = xor i8 %or, -1 -+ ret i8 %neg -+} -+ -+define i16 @nor_i16(i16 %a, i16 %b) nounwind { -+; CHECK-LABEL: nor_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: or $r4, $r4, $r5 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %or = or i16 %a, %b -+ %neg = xor i16 %or, -1 -+ ret i16 %neg -+} -+ -+define i32 @nor_i32(i32 %a, i32 %b) nounwind { -+; CHECK-LABEL: nor_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: or $r4, $r4, $r5 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %or = or i32 %a, %b -+ %neg = xor i32 %or, -1 -+ ret i32 %neg -+} -+ -+define i8 @nor_zero_i8(i8 %a) nounwind { -+; CHECK-LABEL: nor_zero_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i8 %a, -1 -+ ret i8 %neg -+} -+ -+define i16 @nor_zero_i16(i16 %a) nounwind { -+; CHECK-LABEL: nor_zero_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i16 %a, -1 -+ ret i16 %neg -+} -+ -+define i32 @nor_zero_i32(i32 %a) nounwind { -+; CHECK-LABEL: nor_zero_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: nor $r4, $zero, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i32 %a, -1 -+ ret i32 %neg -+} -+ -+define i8 @orn_i8(i8 %a, i8 %b) nounwind { -+; CHECK-LABEL: orn_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: nor $r5, $zero, $r5 -+; CHECK-NEXT: or $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i8 %b, -1 -+ %or = or i8 %neg, %a -+ ret i8 %or -+} -+ -+define i16 @orn_i16(i16 %a, i16 %b) nounwind { -+; CHECK-LABEL: orn_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: nor $r5, $zero, $r5 -+; CHECK-NEXT: or $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i16 %b, -1 -+ %or = or i16 %neg, %a -+ ret i16 %or -+} -+ -+define i32 @orn_i32(i32 %a, i32 %b) nounwind { -+; CHECK-LABEL: orn_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: nor $r5, $zero, $r5 -+; CHECK-NEXT: or $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+ %neg = xor i32 %b, -1 -+ %or = or i32 %neg, %a -+ ret i32 %or -+} -+ -+define i8 @andn_i8(i8 %a, i8 %b) nounwind { -+; CHECK-LABEL: andn_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: andn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+ %neg = xor i8 %b, -1 -+ %and = and i8 %neg, %a -+ ret i8 %and -+} -+ -+define i16 @andn_i16(i16 %a, i16 %b) nounwind { -+; CHECK-LABEL: andn_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: andn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+ %neg = xor i16 %b, -1 -+ %and = and i16 %neg, %a -+ ret i16 %and -+} -+ -+define i32 @andn_i32(i32 %a, i32 %b) nounwind { -+; CHECK-LABEL: andn_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: andn $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+ %neg = xor i32 %b, -1 -+ %and = and i32 %neg, %a -+ ret i32 %and -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll -new file mode 100644 -index 000000000..541ea4256 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll -@@ -0,0 +1,100 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s -+ -+define i8 @load_i8() nounwind { -+; CHECK-LABEL: load_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.bu $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 -+ ret i8 %a -+} -+define signext i8 @load_i8_sext() nounwind { -+; CHECK-LABEL: load_i8_sext: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.b $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 -+ ret i8 %a -+} -+ -+define i16 @load_i16() nounwind { -+; CHECK-LABEL: load_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.hu $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 -+ ret i16 %a -+} -+ -+define signext i16 @load_i16_sext() nounwind { -+; CHECK-LABEL: load_i16_sext: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.h $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 -+ ret i16 %a -+} -+ -+define i32 @load_i32() nounwind { -+; CHECK-LABEL: load_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.w $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 -+ ret i32 %a -+} -+ -+define signext i32 @load_i32_sext() nounwind { -+; CHECK-LABEL: load_i32_sext: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.w $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 -+ ret i32 %a -+} -+ -+define i64 @load_i64() nounwind { -+; CHECK-LABEL: load_i64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: ld.d $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ %a = load i64, i64* inttoptr (i64 40 to i64*), align 8 -+ ret i64 %a -+} -+ -+define void @store_i8(i8 %v) nounwind { -+; CHECK-LABEL: store_i8: -+; CHECK: # %bb.0: -+; CHECK-NEXT: st.b $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ store i8 %v, i8* inttoptr (i64 40 to i8*), align 8 -+ ret void -+} -+ -+define void @store_i16(i16 %v) nounwind { -+; CHECK-LABEL: store_i16: -+; CHECK: # %bb.0: -+; CHECK-NEXT: st.h $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ store i16 %v, i16* inttoptr (i64 40 to i16*), align 8 -+ ret void -+} -+ -+define void @store_i32(i32 %v) nounwind { -+; CHECK-LABEL: store_i32: -+; CHECK: # %bb.0: -+; CHECK-NEXT: st.w $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ store i32 %v, i32* inttoptr (i64 40 to i32*), align 8 -+ ret void -+} -+ -+define void @store_i64(i64 %v) nounwind { -+; CHECK-LABEL: store_i64: -+; CHECK: # %bb.0: -+; CHECK-NEXT: st.d $r4, $zero, 40 -+; CHECK-NEXT: jr $ra -+ store i64 %v, i64* inttoptr (i64 40 to i64*), align 8 -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll -new file mode 100644 -index 000000000..13c710d14 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll -@@ -0,0 +1,37 @@ -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define i32 @foo(i32 signext %a) { -+; CHECK-LABEL: foo: -+; CHECK: # %bb.0: -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+ ret i32 %a -+} -+ -+define signext i32 @foo1() { -+; CHECK-LABEL: foo1: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: ori $r4, $zero, 0 -+; CHECK-NEXT: ori $r5, $zero, 896 -+; CHECK-NEXT: move $r6, $r4 -+; CHECK-NEXT: .LBB1_1: # %for.body -+; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -+; CHECK-NEXT: add.w $r4, $r4, $r6 -+; CHECK-NEXT: addi.w $r6, $r6, 1 -+; CHECK-NEXT: bne $r6, $r5, .LBB1_1 -+; CHECK-NEXT: # %bb.2: # %for.end -+; CHECK-NEXT: jr $ra -+entry: -+ br label %for.body -+ -+for.body: -+ %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ] -+ %i.010 = phi i32 [ 0, %entry ], [ %inc, %for.body ] -+ %add = add i32 %sum.013, %i.010 -+ %inc = add nuw nsw i32 %i.010, 1 -+ %exitcond = icmp eq i32 %inc, 896 -+ br i1 %exitcond, label %for.end, label %for.body -+ -+for.end: -+ ret i32 %add -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll -new file mode 100644 -index 000000000..0a54e0f8f ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll -@@ -0,0 +1,52 @@ -+; Check whether st.w/st.d/stptr.w/stptr.d/stx.w/stx.d instructions are properly generated -+; RUN: llc -march=loongarch64 -o - %s | FileCheck %s -+ -+define void @st_w(i32* %p, i32 signext %val) { -+; CHECK: st.w $r5, $r4, 2044 -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i32, i32* %p, i64 511 -+ store i32 %val, i32* %addr, align 4 -+ ret void -+} -+ -+define void @stptr_w(i32* %p, i32 signext %val) { -+; CHECK: stptr.w $r5, $r4, 2048 -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i32, i32* %p, i64 512 -+ store i32 %val, i32* %addr, align 4 -+ ret void -+} -+ -+define void @stx_w(i32* %p, i32 signext %val) { -+; CHECK: lu12i.w $r[[REG:[0-9]+]], 8 -+; CHECK: stx.w $r5, $r4, $r[[REG:[0-9]+]] -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i32, i32* %p, i64 8192 -+ store i32 %val, i32* %addr, align 4 -+ ret void -+} -+ -+define void @st_d(i64* %p, i64 %val) { -+; CHECK: st.d $r5, $r4, 2040 -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i64, i64* %p, i64 255 -+ store i64 %val, i64* %addr, align 8 -+ ret void -+} -+ -+define void @stptr_d(i64* %p, i64 %val) { -+; CHECK: stptr.d $r5, $r4, 2048 -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i64, i64* %p, i64 256 -+ store i64 %val, i64* %addr, align 8 -+ ret void -+} -+ -+define void @stx_d(i64* %p, i64 %val) { -+; CHECK: lu12i.w $r[[REG:[0-9]+]], 8 -+; CHECK: stx.d $r5, $r4, $r[[REG:[0-9]+]] -+; CHECK: jr $ra -+ %addr = getelementptr inbounds i64, i64* %p, i64 4096 -+ store i64 %val, i64* %addr, align 8 -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll -new file mode 100644 -index 000000000..2445e32ea ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll -@@ -0,0 +1,62 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -+ -+@errors = external local_unnamed_addr global i32, align 4 -+ -+define signext i32 @compare(i8* %x, i8* %y) { -+; CHECK-LABEL: compare: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -32 -+; CHECK-NEXT: .cfi_def_cfa_offset 32 -+; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -+; CHECK-NEXT: st.d $r23, $sp, 16 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: .cfi_offset 23, -16 -+; CHECK-NEXT: ld.w $r23, $r5, 0 -+; CHECK-NEXT: ld.d $r6, $r4, 8 -+; CHECK-NEXT: beqz $r23, .LBB0_3 -+; CHECK-NEXT: # %bb.1: # %land.lhs.true -+; CHECK-NEXT: ld.w $r4, $r4, 0 -+; CHECK-NEXT: st.d $r6, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: ld.d $r5, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: jirl $ra, $r5, 0 -+; CHECK-NEXT: ld.d $r6, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: beqz $r4, .LBB0_3 -+; CHECK-NEXT: # %bb.2: # %if.then -+; CHECK-NEXT: la.got $r4, errors -+; CHECK-NEXT: # la expanded slot -+; CHECK-NEXT: ld.w $r5, $r4, 0 -+; CHECK-NEXT: addi.w $r5, $r5, 1 -+; CHECK-NEXT: st.w $r5, $r4, 0 -+; CHECK-NEXT: .LBB0_3: # %if.end -+; CHECK-NEXT: move $r4, $r23 -+; CHECK-NEXT: ld.d $r23, $sp, 16 # 8-byte Folded Reload -+; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 32 -+; CHECK-NEXT: jr $r6 -+entry: -+ %compare = getelementptr inbounds i8, i8* %x, i64 8 -+ %0 = bitcast i8* %compare to i32 (i32)** -+ %1 = load i32 (i32)*, i32 (i32)** %0, align 8 -+ %elt = bitcast i8* %y to i32* -+ %2 = load i32, i32* %elt, align 8 -+ %cmp = icmp eq i32 %2, 0 -+ br i1 %cmp, label %if.end, label %land.lhs.true -+ -+land.lhs.true: ; preds = %entry -+ %elt3 = bitcast i8* %x to i32* -+ %3 = load i32, i32* %elt3, align 8 -+ %call4 = tail call signext i32 %1(i32 signext %3) -+ %cmp5 = icmp eq i32 %call4, 0 -+ br i1 %cmp5, label %if.end, label %if.then -+ -+if.then: ; preds = %land.lhs.true -+ %4 = load i32, i32* @errors, align 4 -+ %inc = add nsw i32 %4, 1 -+ store i32 %inc, i32* @errors, align 4 -+ br label %if.end -+ -+if.end: ; preds = %if.then, %land.lhs.true, %entry -+ %call6 = tail call signext i32 %1(i32 signext %2) -+ ret i32 %call6 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll -new file mode 100644 -index 000000000..2b5902d69 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll -@@ -0,0 +1,155 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -+ -+; Perform tail call optimization for global address. -+declare i32 @callee_tail(i32 %i) -+define i32 @caller_tail(i32 %i) { -+; CHECK-LABEL: caller_tail: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: b callee_tail -+entry: -+ %r = tail call i32 @callee_tail(i32 %i) -+ ret i32 %r -+} -+ -+ -+; Do not tail call optimize functions with varargs. -+declare i32 @callee_varargs(i32, ...) -+define void @caller_varargs(i32 %a, i32 %b) { -+; CHECK-LABEL: caller_varargs: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: move $r6, $r5 -+; CHECK-NEXT: move $r7, $r4 -+; CHECK-NEXT: bl callee_varargs -+; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+entry: -+ %call = tail call i32 (i32, ...) @callee_varargs(i32 %a, i32 %b, i32 %b, i32 %a) -+ ret void -+} -+ -+ -+; Do not tail call optimize if stack is used to pass parameters. -+declare i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) -+define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) { -+; CHECK-LABEL: caller_args: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -64 -+; CHECK-NEXT: .cfi_def_cfa_offset 64 -+; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: ld.d $r12, $sp, 64 -+; CHECK-NEXT: ld.d $r13, $sp, 72 -+; CHECK-NEXT: ld.d $r14, $sp, 80 -+; CHECK-NEXT: ld.d $r15, $sp, 88 -+; CHECK-NEXT: ld.d $r16, $sp, 96 -+; CHECK-NEXT: ld.d $r17, $sp, 104 -+; CHECK-NEXT: st.d $r17, $sp, 40 -+; CHECK-NEXT: st.d $r16, $sp, 32 -+; CHECK-NEXT: st.d $r15, $sp, 24 -+; CHECK-NEXT: st.d $r14, $sp, 16 -+; CHECK-NEXT: st.d $r13, $sp, 8 -+; CHECK-NEXT: st.d $r12, $sp, 0 -+; CHECK-NEXT: bl callee_args -+; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 64 -+; CHECK-NEXT: jr $ra -+entry: -+ %r = tail call i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) -+ ret i32 %r -+} -+ -+ -+; Do not tail call optimize for exception-handling functions. -+declare void @callee_interrupt() -+define void @caller_interrupt() #0 { -+; CHECK-LABEL: caller_interrupt: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: bl callee_interrupt -+; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+entry: -+ tail call void @callee_interrupt() -+ ret void -+} -+attributes #0 = { "interrupt"="machine" } -+ -+ -+; Do not tail call optimize functions with byval parameters. -+declare i32 @callee_byval(i32** byval(i32*) %a) -+define i32 @caller_byval() { -+; CHECK-LABEL: caller_byval: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -32 -+; CHECK-NEXT: .cfi_def_cfa_offset 32 -+; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: ld.d $r4, $sp, 16 -+; CHECK-NEXT: st.d $r4, $sp, 0 -+; CHECK-NEXT: bl callee_byval -+; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 32 -+; CHECK-NEXT: jr $ra -+entry: -+ %a = alloca i32* -+ %r = tail call i32 @callee_byval(i32** byval(i32*) %a) -+ ret i32 %r -+} -+ -+ -+; Do not tail call optimize if callee uses structret semantics. -+%struct.A = type { i32 } -+@a = global %struct.A zeroinitializer -+ -+declare void @callee_struct(%struct.A* sret(%struct.A) %a) -+define void @caller_nostruct() { -+; CHECK-LABEL: caller_nostruct: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: la.got $r4, a -+; CHECK-NEXT: # la expanded slot -+; CHECK-NEXT: bl callee_struct -+; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+entry: -+ tail call void @callee_struct(%struct.A* sret(%struct.A) @a) -+ ret void -+} -+ -+ -+; Do not tail call optimize if caller uses structret semantics. -+declare void @callee_nostruct() -+define void @caller_struct(%struct.A* sret(%struct.A) %a) { -+; CHECK-LABEL: caller_struct: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: addi.d $sp, $sp, -16 -+; CHECK-NEXT: .cfi_def_cfa_offset 16 -+; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill -+; CHECK-NEXT: st.d $r23, $sp, 0 # 8-byte Folded Spill -+; CHECK-NEXT: .cfi_offset 1, -8 -+; CHECK-NEXT: .cfi_offset 23, -16 -+; CHECK-NEXT: move $r23, $r4 -+; CHECK-NEXT: bl callee_nostruct -+; CHECK-NEXT: move $r4, $r23 -+; CHECK-NEXT: ld.d $r23, $sp, 0 # 8-byte Folded Reload -+; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload -+; CHECK-NEXT: addi.d $sp, $sp, 16 -+; CHECK-NEXT: jr $ra -+entry: -+ tail call void @callee_nostruct() -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll -new file mode 100644 -index 000000000..68ddaa899 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll -@@ -0,0 +1,35 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -+ -+ -+define void @tail_memcpy(i8* %p, i8* %q, i32 %n) { -+; CHECK-LABEL: tail_memcpy: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: b memcpy -+entry: -+ tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) -+ ret void -+} -+ -+define void @tail_memmove(i8* %p, i8* %q, i32 %n) { -+; CHECK-LABEL: tail_memmove: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: b memmove -+entry: -+ tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) -+ ret void -+} -+ -+define void @tail_memset(i8* %p, i8 %c, i32 %n) { -+; CHECK-LABEL: tail_memset: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: b memset -+entry: -+ tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i1 false) -+ ret void -+} -+ -+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) -+declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) -+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) -+ -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll -new file mode 100644 -index 000000000..984df2cb6 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll -@@ -0,0 +1,13 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -+ -+define void @f() { -+; CHECK-LABEL: f: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: b foo -+entry: -+ tail call void bitcast (void (...)* @foo to void ()*)() -+ ret void -+} -+ -+declare void @foo(...) -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll -new file mode 100644 -index 000000000..06a5886c4 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll -@@ -0,0 +1,9 @@ -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+declare i8* @llvm.thread.pointer() nounwind readnone -+ -+define i8* @thread_pointer() { -+; CHECK: move $r4, $tp -+ %1 = tail call i8* @llvm.thread.pointer() -+ ret i8* %1 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll -new file mode 100644 -index 000000000..d1b5a3a14 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll -@@ -0,0 +1,108 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 < %s | FileCheck %s -+ -+define signext i32 @foo1(i64 %a, i64 %b) { -+; CHECK-LABEL: foo1: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: add.w $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %add = add nsw i32 %conv1, %conv -+ ret i32 %add -+} -+ -+define signext i32 @foo2(i64 %a, i64 %b) { -+; CHECK-LABEL: foo2: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: sub.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %sub = sub nsw i32 %conv, %conv1 -+ ret i32 %sub -+} -+ -+define signext i32 @foo3(i64 %a, i64 %b) { -+; CHECK-LABEL: foo3: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: sll.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %shl = shl i32 %conv, %conv1 -+ ret i32 %shl -+} -+ -+define signext i32 @foo4(i64 %a, i64 %b) { -+; CHECK-LABEL: foo4: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: srl.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %shr = lshr i32 %conv, %conv1 -+ ret i32 %shr -+} -+ -+define signext i32 @foo5(i64 %a, i64 %b) { -+; CHECK-LABEL: foo5: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: mul.w $r4, $r5, $r4 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %mul = mul nsw i32 %conv1, %conv -+ ret i32 %mul -+} -+ -+define signext i32 @foo6(i64 %a, i64 %b) { -+; CHECK-LABEL: foo6: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: sra.w $r4, $r4, $r5 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %shr = ashr i32 %conv, %conv1 -+ ret i32 %shr -+} -+ -+define signext i32 @sdiv(i64 %a, i64 %b) { -+; CHECK-LABEL: sdiv: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: div.w $r4, $r4, $r5 -+; CHECK-NEXT: bne $r5, $zero, 8 -+; CHECK-NEXT: break 7 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %div = sdiv i32 %conv, %conv1 -+ ret i32 %div -+} -+ -+define signext i32 @udiv(i64 %a, i64 %b) { -+; CHECK-LABEL: udiv: -+; CHECK: # %bb.0: # %entry -+; CHECK-NEXT: slli.w $r5, $r5, 0 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: div.wu $r4, $r4, $r5 -+; CHECK-NEXT: bne $r5, $zero, 8 -+; CHECK-NEXT: break 7 -+; CHECK-NEXT: slli.w $r4, $r4, 0 -+; CHECK-NEXT: jr $ra -+entry: -+ %conv = trunc i64 %a to i32 -+ %conv1 = trunc i64 %b to i32 -+ %div = udiv i32 %conv, %conv1 -+ ret i32 %div -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll -new file mode 100644 -index 000000000..d468a361f ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll -@@ -0,0 +1,72 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -march=loongarch64 -o - %s | FileCheck -check-prefix=UNALIGNED %s -+; RUN: llc -march=loongarch64 -mattr=+unaligned-access -o - %s | FileCheck -check-prefix=UNALIGNED %s -+; RUN: llc -march=loongarch64 -mattr=-unaligned-access -o - %s | FileCheck -check-prefix=ALIGNED %s -+ -+define i32 @i32_load(i32* %p) { -+; UNALIGNED-LABEL: i32_load: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.w $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+; -+; ALIGNED-LABEL: i32_load: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.hu $r4, $r4, 2 -+; ALIGNED-NEXT: slli.w $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define signext i32 @i32_sextload(i32* %p) { -+; UNALIGNED-LABEL: i32_sextload: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.w $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+; -+; ALIGNED-LABEL: i32_sextload: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.h $r4, $r4, 2 -+; ALIGNED-NEXT: slli.d $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define zeroext i32 @i32_zextload(i32* %p) { -+; UNALIGNED-LABEL: i32_zextload: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.wu $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+; -+; ALIGNED-LABEL: i32_zextload: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.hu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.hu $r4, $r4, 2 -+; ALIGNED-NEXT: slli.d $r4, $r4, 16 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+ %tmp = load i32, i32* %p, align 2 -+ ret i32 %tmp -+} -+ -+define i64 @i64_load(i64* %p) { -+; UNALIGNED-LABEL: i64_load: -+; UNALIGNED: # %bb.0: -+; UNALIGNED-NEXT: ld.d $r4, $r4, 0 -+; UNALIGNED-NEXT: jr $ra -+; -+; ALIGNED-LABEL: i64_load: -+; ALIGNED: # %bb.0: -+; ALIGNED-NEXT: ld.wu $r5, $r4, 0 -+; ALIGNED-NEXT: ld.wu $r4, $r4, 4 -+; ALIGNED-NEXT: slli.d $r4, $r4, 32 -+; ALIGNED-NEXT: or $r4, $r4, $r5 -+; ALIGNED-NEXT: jr $ra -+ %tmp = load i64, i64* %p, align 4 -+ ret i64 %tmp -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll b/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll -new file mode 100644 -index 000000000..cae3cb3bb ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll -@@ -0,0 +1,250 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -O0 < %s | FileCheck %s -+ -+; This test would previously crash in RegisterScavenging, or with assertions -+; enabled it would fail when RegAllocFast calls clearVirtRegs. This was due to -+; unhandled virt regs in cloned DBG_VALUE_LIST for spills, which are now skipped. -+; https://github.com/llvm/llvm-project/issues/59172 -+ -+target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" -+target triple = "powerpc64le-unknown-linux-gnu" -+ -+; Function Attrs: argmemonly nocallback nofree nounwind willreturn -+declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0 -+ -+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -+declare void @llvm.dbg.value(metadata, metadata, metadata) #1 -+ -+define void @read_to_end(i1 %0) personality ptr null { -+; CHECK-LABEL: read_to_end: -+; CHECK: # %bb.0: -+; CHECK-NEXT: mflr 0 -+; CHECK-NEXT: std 0, 16(1) -+; CHECK-NEXT: stdu 1, -80(1) -+; CHECK-NEXT: .cfi_def_cfa_offset 80 -+; CHECK-NEXT: .cfi_offset lr, 16 -+; CHECK-NEXT: andi. 3, 3, 1 -+; CHECK-NEXT: mfocrf 3, 128 -+; CHECK-NEXT: rlwinm 3, 3, 1, 0, 0 -+; CHECK-NEXT: stw 3, 60(1) -+; CHECK-NEXT: ld 3, 0(0) -+; CHECK-NEXT: std 3, 64(1) # 8-byte Folded Spill -+; CHECK-NEXT: li 3, 0 -+; CHECK-NEXT: std 3, 72(1) # 8-byte Folded Spill -+; CHECK-NEXT: #DEBUG_VALUE: spec_extend:iterator <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_constu 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment 64 64] undef, $x3 -+; CHECK-NEXT: creqv 20, 20, 20 -+; CHECK-NEXT: crxor 20, 1, 20 -+; CHECK-NEXT: bc 12, 20, .LBB0_2 -+; CHECK-NEXT: b .LBB0_1 -+; CHECK-NEXT: .LBB0_1: -+; CHECK-NEXT: addi 1, 1, 80 -+; CHECK-NEXT: ld 0, 16(1) -+; CHECK-NEXT: mtlr 0 -+; CHECK-NEXT: blr -+; CHECK-NEXT: .LBB0_2: -+; CHECK-NEXT: ld 5, 72(1) # 8-byte Folded Reload -+; CHECK-NEXT: ld 4, 64(1) # 8-byte Folded Reload -+; CHECK-NEXT: li 3, 0 -+; CHECK-NEXT: bl memcpy -+; CHECK-NEXT: nop -+; CHECK-NEXT: lwz 4, 60(1) -+; CHECK-NEXT: # implicit-def: $cr5lt -+; CHECK-NEXT: mfocrf 3, 4 -+; CHECK-NEXT: rlwimi 3, 4, 12, 20, 20 -+; CHECK-NEXT: mtocrf 4, 3 -+; CHECK-NEXT: bc 12, 20, .LBB0_4 -+; CHECK-NEXT: b .LBB0_3 -+; CHECK-NEXT: .LBB0_3: -+; CHECK-NEXT: b .LBB0_4 -+; CHECK-NEXT: .LBB0_4: -+; CHECK-NEXT: addi 1, 1, 80 -+; CHECK-NEXT: ld 0, 16(1) -+; CHECK-NEXT: mtlr 0 -+; CHECK-NEXT: blr -+ %2 = load ptr, ptr null, align 8 -+ %3 = sub i64 0, 0 -+ call void @llvm.dbg.value(metadata !DIArgList(ptr %2, i64 %3), metadata !129, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 64)), !dbg !140 -+ br i1 %0, label %4, label %5 -+ -+4: ; preds = %1 -+ ret void -+ -+5: ; preds = %1 -+ tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %2, i64 %3, i1 false) -+ br i1 %0, label %7, label %6 -+ -+6: ; preds = %5 -+ br label %7 -+ -+7: ; preds = %6, %5 -+ ret void -+} -+ -+attributes #0 = { argmemonly nocallback nofree nounwind willreturn } -+attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } -+ -+!llvm.module.flags = !{!0} -+!llvm.dbg.cu = !{!1} -+ -+!0 = !{i32 2, !"Debug Info Version", i32 3} -+!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.67.0-dev)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) -+!2 = !DIFile(filename: "library/std/src/lib.rs/@/std.ff910444-cgu.11", directory: "/home/jistone/rust") -+!3 = !{} -+!4 = !{!5, !12, !18, !23, !28, !34, !43, !49, !52, !58, !64, !68, !77, !81, !86, !90, !98, !102, !106, !111, !117, !124} -+!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) -+!6 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !8, isLocal: true, isDefinition: true) -+!7 = !DIFile(filename: "", directory: "") -+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !9, templateParams: !3, identifier: "1ec913b2a90798f33a12cdc627a17d3d") -+!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "String", scope: !10, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "b616ccc9e18737e903266aae12eea82") -+!10 = !DINamespace(name: "string", scope: !11) -+!11 = !DINamespace(name: "alloc", scope: null) -+!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) -+!13 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !14, isLocal: true, isDefinition: true) -+!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !15, templateParams: !3, identifier: "7f09904511177108b2e94c43effbe403") -+!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "BorrowMutError", scope: !16, file: !7, align: 8, elements: !3, identifier: "acf9edd4524e0ff9a9398905d3ba31a6") -+!16 = !DINamespace(name: "cell", scope: !17) -+!17 = !DINamespace(name: "core", scope: null) -+!18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression()) -+!19 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !20, isLocal: true, isDefinition: true) -+!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !21, templateParams: !3, identifier: "84cb7e6d80fc4c532d8f45aaa75a7ae3") -+!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Error", scope: !22, file: !7, align: 8, elements: !3, identifier: "abcb9fb1fe4fda8598a8687b517935b") -+!22 = !DINamespace(name: "fmt", scope: !17) -+!23 = !DIGlobalVariableExpression(var: !24, expr: !DIExpression()) -+!24 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !25, isLocal: true, isDefinition: true) -+!25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !26, templateParams: !3, identifier: "bafa31943f8233dbf8d2de6a615f899") -+!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromSliceError", scope: !27, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "2dd7cf8d77337f63be7c7f5feb370b37") -+!27 = !DINamespace(name: "array", scope: !17) -+!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression()) -+!29 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !30, isLocal: true, isDefinition: true) -+!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !31, templateParams: !3, identifier: "3292395ea0f5a7e3e88f36db52eb440c") -+!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromIntError", scope: !32, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "5b131d57d001578fbf4fb83f2028eb12") -+!32 = !DINamespace(name: "error", scope: !33) -+!33 = !DINamespace(name: "num", scope: !17) -+!34 = !DIGlobalVariableExpression(var: !35, expr: !DIExpression()) -+!35 = distinct !DIGlobalVariable(name: "OUTPUT_CAPTURE_USED", linkageName: "_ZN3std2io5stdio19OUTPUT_CAPTURE_USED17h6bb564f9f9e20f1bE", scope: !36, file: !39, line: 38, type: !40, isLocal: true, isDefinition: true, align: 8) -+!36 = !DINamespace(name: "stdio", scope: !37) -+!37 = !DINamespace(name: "io", scope: !38) -+!38 = !DINamespace(name: "std", scope: null) -+!39 = !DIFile(filename: "library/std/src/io/stdio.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "6e6a519ce8370e29f07d850a34a413c1") -+!40 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicBool", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "c1cddf0305d4e6a98a8ddd4b6fdb5b91") -+!41 = !DINamespace(name: "atomic", scope: !42) -+!42 = !DINamespace(name: "sync", scope: !17) -+!43 = !DIGlobalVariableExpression(var: !44, expr: !DIExpression()) -+!44 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio5stdin8INSTANCE17h225ddf7c6608f4aaE", scope: !45, file: !39, line: 320, type: !46, isLocal: true, isDefinition: true, align: 64) -+!45 = !DINamespace(name: "stdin", scope: !36) -+!46 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>", scope: !47, file: !7, size: 448, align: 64, elements: !3, templateParams: !3, identifier: "2236c08b0846b8b2f33c235183822718") -+!47 = !DINamespace(name: "once_lock", scope: !48) -+!48 = !DINamespace(name: "sync", scope: !38) -+!49 = !DIGlobalVariableExpression(var: !50, expr: !DIExpression()) -+!50 = distinct !DIGlobalVariable(name: "STDOUT", linkageName: "_ZN3std2io5stdio6STDOUT17hd8472b9eb112f94aE", scope: !36, file: !39, line: 554, type: !51, isLocal: true, isDefinition: true, align: 64) -+!51 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>>", scope: !47, file: !7, size: 512, align: 64, elements: !3, templateParams: !3, identifier: "31535135376bcf9dc80438cb0beaa95") -+!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression()) -+!53 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio6stderr8INSTANCE17he81b75fda1609dccE", scope: !54, file: !39, line: 844, type: !55, isLocal: true, isDefinition: true, align: 64) -+!54 = !DINamespace(name: "stderr", scope: !36) -+!55 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ReentrantMutex>", scope: !56, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "5c48123cbde8afbfd832b70e8bb014b") -+!56 = !DINamespace(name: "remutex", scope: !57) -+!57 = !DINamespace(name: "sys_common", scope: !38) -+!58 = !DIGlobalVariableExpression(var: !59, expr: !DIExpression()) -+!59 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !60, isLocal: true, isDefinition: true) -+!60 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !61, templateParams: !3, identifier: "43681bec3eba7b0defb75fd847230ef3") -+!61 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "eda3cd8f60f00feb7019a3d90d2413dd") -+!62 = !DINamespace(name: "write_fmt", scope: !63) -+!63 = !DINamespace(name: "Write", scope: !37) -+!64 = !DIGlobalVariableExpression(var: !65, expr: !DIExpression()) -+!65 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !66, isLocal: true, isDefinition: true) -+!66 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !67, templateParams: !3, identifier: "2235adf22355a080446df25ada963d8f") -+!67 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "50f418463bae1beffe989359452b170a") -+!68 = !DIGlobalVariableExpression(var: !69, expr: !DIExpression()) -+!69 = distinct !DIGlobalVariable(name: "__KEY", linkageName: "_ZN3std2io5stdio14OUTPUT_CAPTURE7__getit5__KEY17h82ea5b0c4e81236dE", scope: !70, file: !72, line: 331, type: !73, isLocal: true, isDefinition: true, align: 64) -+!70 = !DINamespace(name: "__getit", scope: !71) -+!71 = !DINamespace(name: "OUTPUT_CAPTURE", scope: !36) -+!72 = !DIFile(filename: "library/std/src/thread/local.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "e3766fd5751a888dc2040f63031e944e") -+!73 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Key>>>>>", scope: !74, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "4d1514f685cbd010d7b86d2eef080b6c") -+!74 = !DINamespace(name: "fast", scope: !75) -+!75 = !DINamespace(name: "local", scope: !76) -+!76 = !DINamespace(name: "thread", scope: !38) -+!77 = !DIGlobalVariableExpression(var: !78, expr: !DIExpression()) -+!78 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !79, isLocal: true, isDefinition: true) -+!79 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !80, templateParams: !3, identifier: "1a7c0806435616633a284f48de1194c5") -+!80 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) -+!81 = !DIGlobalVariableExpression(var: !82, expr: !DIExpression()) -+!82 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !83, isLocal: true, isDefinition: true) -+!83 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !84, templateParams: !3, identifier: "8e82e7dafb168f2995a6711175975a8") -+!84 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "PathBuf", scope: !85, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "85bd755ad2187534379df2cc01ef53a0") -+!85 = !DINamespace(name: "path", scope: !38) -+!86 = !DIGlobalVariableExpression(var: !87, expr: !DIExpression()) -+!87 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !88, isLocal: true, isDefinition: true) -+!88 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !89, templateParams: !3, identifier: "a8f7c32dd1df279746df60c6d46ce35e") -+!89 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) -+!90 = !DIGlobalVariableExpression(var: !91, expr: !DIExpression()) -+!91 = distinct !DIGlobalVariable(name: "STATX_STATE", linkageName: "_ZN3std3sys4unix2fs9try_statx11STATX_STATE17h465ade0d62262837E", scope: !92, file: !96, line: 157, type: !97, isLocal: true, isDefinition: true, align: 8) -+!92 = !DINamespace(name: "try_statx", scope: !93) -+!93 = !DINamespace(name: "fs", scope: !94) -+!94 = !DINamespace(name: "unix", scope: !95) -+!95 = !DINamespace(name: "sys", scope: !38) -+!96 = !DIFile(filename: "library/std/src/sys/unix/fs.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "594559328c68ee77afe955cd571273ee") -+!97 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicU8", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "dda3b691bea8e1b5292414dd97926af2") -+!98 = !DIGlobalVariableExpression(var: !99, expr: !DIExpression()) -+!99 = distinct !DIGlobalVariable(name: "<&bool as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !100, isLocal: true, isDefinition: true) -+!100 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&bool as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !101, templateParams: !3, identifier: "5e8d2c48c9cc79c318e2bd28b03e141a") -+!101 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&bool", baseType: !89, size: 64, align: 64, dwarfAddressSpace: 0) -+!102 = !DIGlobalVariableExpression(var: !103, expr: !DIExpression()) -+!103 = distinct !DIGlobalVariable(name: "<&i32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !104, isLocal: true, isDefinition: true) -+!104 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&i32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !105, templateParams: !3, identifier: "d4029746615b6a868ffbc67515d99878") -+!105 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&i32", baseType: !80, size: 64, align: 64, dwarfAddressSpace: 0) -+!106 = !DIGlobalVariableExpression(var: !107, expr: !DIExpression()) -+!107 = distinct !DIGlobalVariable(name: "<&u32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !108, isLocal: true, isDefinition: true) -+!108 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&u32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !109, templateParams: !3, identifier: "178e0e76b9d9178d686381b2d05a7777") -+!109 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u32", baseType: !110, size: 64, align: 64, dwarfAddressSpace: 0) -+!110 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) -+!111 = !DIGlobalVariableExpression(var: !112, expr: !DIExpression()) -+!112 = distinct !DIGlobalVariable(name: "<&core::option::Option as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !113, isLocal: true, isDefinition: true) -+!113 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&core::option::Option as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !114, templateParams: !3, identifier: "7ca8386b4d420d719587fa3255329a7a") -+!114 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&core::option::Option", baseType: !115, size: 64, align: 64, dwarfAddressSpace: 0) -+!115 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Option", scope: !116, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "ad8474e495013fa1e3af4a6b53a05f4b") -+!116 = !DINamespace(name: "option", scope: !17) -+!117 = !DIGlobalVariableExpression(var: !118, expr: !DIExpression()) -+!118 = distinct !DIGlobalVariable(name: "HAS_CLONE3", linkageName: "_ZN3std3sys4unix7process13process_inner66_$LT$impl$u20$std..sys..unix..process..process_common..Command$GT$7do_fork10HAS_CLONE317h7d23eb353ae1c9a8E", scope: !119, file: !123, line: 148, type: !40, isLocal: true, isDefinition: true, align: 8) -+!119 = !DINamespace(name: "do_fork", scope: !120) -+!120 = !DINamespace(name: "{impl#0}", scope: !121) -+!121 = !DINamespace(name: "process_inner", scope: !122) -+!122 = !DINamespace(name: "process", scope: !94) -+!123 = !DIFile(filename: "library/std/src/sys/unix/process/process_unix.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "91761d638041a5dd66c0a64d968debe6") -+!124 = !DIGlobalVariableExpression(var: !125, expr: !DIExpression()) -+!125 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !126, isLocal: true, isDefinition: true) -+!126 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !127, templateParams: !3, identifier: "13903f30d26ee5869ef7a3fc63a2e03d") -+!127 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonZeroI32", scope: !128, file: !7, size: 32, align: 32, elements: !3, templateParams: !3, identifier: "e292f11a32f1ce5cf3b26864e4a0f5e5") -+!128 = !DINamespace(name: "nonzero", scope: !33) -+!129 = !DILocalVariable(name: "iterator", arg: 2, scope: !130, file: !131, line: 83, type: !137) -+!130 = distinct !DISubprogram(name: "spec_extend", linkageName: "_ZN132_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$alloc..vec..spec_extend..SpecExtend$LT$$RF$T$C$core..slice..iter..Iter$LT$T$GT$$GT$$GT$11spec_extend17hb56b69f474ec1e6dE", scope: !132, file: !131, line: 83, type: !135, scopeLine: 83, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) -+!131 = !DIFile(filename: "library/alloc/src/vec/spec_extend.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0614d5dabe9e343254af1b3fa1ec7315") -+!132 = !DINamespace(name: "{impl#4}", scope: !133) -+!133 = !DINamespace(name: "spec_extend", scope: !134) -+!134 = !DINamespace(name: "vec", scope: !11) -+!135 = distinct !DISubroutineType(types: !136) -+!136 = !{null} -+!137 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Iter", scope: !138, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "c31ab6f02ccece1f1a6e93425acabaa1") -+!138 = !DINamespace(name: "iter", scope: !139) -+!139 = !DINamespace(name: "slice", scope: !17) -+!140 = !DILocation(line: 0, scope: !130, inlinedAt: !141) -+!141 = distinct !DILocation(line: 2392, column: 9, scope: !142, inlinedAt: !146) -+!142 = distinct !DISubprogram(name: "extend_from_slice", linkageName: "_ZN5alloc3vec16Vec$LT$T$C$A$GT$17extend_from_slice17hbc8d29f2694fd768E", scope: !144, file: !143, line: 2391, type: !145, scopeLine: 2391, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) -+!143 = !DIFile(filename: "library/alloc/src/vec/mod.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0d69d0c0c11b3e47364cf6be0d07c829") -+!144 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Vec", scope: !134, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "f970dea4d30c1daf847db520fef9390d") -+!145 = distinct !DISubroutineType(types: !136) -+!146 = distinct !DILocation(line: 330, column: 9, scope: !147, inlinedAt: !154) -+!147 = distinct !DILexicalBlock(scope: !149, file: !148, line: 329, column: 9) -+!148 = !DIFile(filename: "library/std/src/io/buffered/bufreader.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "5375e06de487f85ee2f6d21c8a84ce7d") -+!149 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN82_$LT$std..io..buffered..bufreader..BufReader$LT$R$GT$$u20$as$u20$std..io..Read$GT$11read_to_end17h9f09720ee76e6db9E", scope: !150, file: !148, line: 328, type: !153, scopeLine: 328, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) -+!150 = !DINamespace(name: "{impl#3}", scope: !151) -+!151 = !DINamespace(name: "bufreader", scope: !152) -+!152 = !DINamespace(name: "buffered", scope: !37) -+!153 = distinct !DISubroutineType(types: !3) -+!154 = distinct !DILocation(line: 464, column: 9, scope: !155, inlinedAt: !158) -+!155 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN59_$LT$std..io..stdio..StdinLock$u20$as$u20$std..io..Read$GT$11read_to_end17h38999a681cc6c5b5E", scope: !156, file: !39, line: 463, type: !157, scopeLine: 463, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) -+!156 = !DINamespace(name: "{impl#7}", scope: !36) -+!157 = distinct !DISubroutineType(types: !3) -+!158 = distinct !DILocation(line: 430, column: 9, scope: !159) -+!159 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN55_$LT$std..io..stdio..Stdin$u20$as$u20$std..io..Read$GT$11read_to_end17haba70a09681d41d3E", scope: !160, file: !39, line: 429, type: !161, scopeLine: 429, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) -+!160 = !DINamespace(name: "{impl#5}", scope: !36) -+!161 = !DISubroutineType(types: !3) -diff --git a/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll b/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll -new file mode 100644 -index 000000000..25b4eeeca ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll -@@ -0,0 +1,254 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc < %s -mtriple=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC %s -+; RUN: llc < %s -mtriple=sparc64 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC64 %s -+ -+;; Structs up to six registers in size can be returned in registers. -+;; Note that the maximum return size and member placement is NOT -+;; compatible with the C ABI - see SparcCallingConv.td. -+define { i32, i32 } @ret_i32_pair(i32 %a0, i32 %a1, i32* %p, i32* %q) { -+; SPARC-LABEL: ret_i32_pair: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -96, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: ld [%i2], %i0 -+; SPARC-NEXT: st %g0, [%i2] -+; SPARC-NEXT: ld [%i3], %i1 -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: ret_i32_pair: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -128, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: ld [%i2], %i0 -+; SPARC64-NEXT: st %g0, [%i2] -+; SPARC64-NEXT: ld [%i3], %i1 -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %r1 = load i32, i32* %p -+ %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 0 -+ store i32 0, i32* %p -+ %r2 = load i32, i32* %q -+ %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 1 -+ ret { i32, i32 } %rv2 -+} -+ -+define void @call_ret_i32_pair(i32* %i0) { -+; SPARC-LABEL: call_ret_i32_pair: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -96, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: call ret_i32_pair -+; SPARC-NEXT: nop -+; SPARC-NEXT: st %o0, [%i0] -+; SPARC-NEXT: st %o1, [%i0] -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: call_ret_i32_pair: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -176, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: call ret_i32_pair -+; SPARC64-NEXT: nop -+; SPARC64-NEXT: st %o0, [%i0] -+; SPARC64-NEXT: st %o1, [%i0] -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %rv = call { i32, i32 } @ret_i32_pair(i32 undef, i32 undef, -+ i32* undef, i32* undef) -+ %e0 = extractvalue { i32, i32 } %rv, 0 -+ store volatile i32 %e0, i32* %i0 -+ %e1 = extractvalue { i32, i32 } %rv, 1 -+ store i32 %e1, i32* %i0 -+ ret void -+} -+ -+;; Functions returning structs more than six registers' worth of space -+;; should be automatically treated as an sret function. -+declare { [16 x i32] } @ret_i32_arr(i32 %input) -+ -+define i32 @call_ret_i32_arr(i32 %0) { -+; SPARC-LABEL: call_ret_i32_arr: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -160, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: add %fp, -64, %i1 -+; SPARC-NEXT: st %i1, [%sp+64] -+; SPARC-NEXT: mov %i0, %o0 -+; SPARC-NEXT: call ret_i32_arr -+; SPARC-NEXT: nop -+; SPARC-NEXT: unimp 64 -+; SPARC-NEXT: ld [%fp+-4], %i0 -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: call_ret_i32_arr: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -240, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: add %fp, 1983, %o0 -+; SPARC64-NEXT: mov %i0, %o1 -+; SPARC64-NEXT: call ret_i32_arr -+; SPARC64-NEXT: nop -+; SPARC64-NEXT: ld [%fp+2043], %i0 -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %2 = call { [16 x i32] } @ret_i32_arr(i32 %0) -+ %3 = extractvalue { [16 x i32] } %2, 0 -+ %4 = extractvalue [16 x i32] %3, 15 -+ ret i32 %4 -+} -+ -+;; Structs up to six registers in size can be returned in registers. -+;; Note that the maximum return size and member placement is NOT -+;; compatible with the C ABI - see SparcCallingConv.td. -+define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) { -+; SPARC-LABEL: ret_i64_pair: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -96, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: mov %g0, %i4 -+; SPARC-NEXT: ldd [%i2], %i0 -+; SPARC-NEXT: mov %i4, %i5 -+; SPARC-NEXT: std %i4, [%i2] -+; SPARC-NEXT: ldd [%i3], %i2 -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: ret_i64_pair: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -128, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: ldx [%i2], %i0 -+; SPARC64-NEXT: stx %g0, [%i2] -+; SPARC64-NEXT: ldx [%i3], %i1 -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %r1 = load i64, i64* %p -+ %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0 -+ store i64 0, i64* %p -+ %r2 = load i64, i64* %q -+ %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1 -+ ret { i64, i64 } %rv2 -+} -+ -+define void @call_ret_i64_pair(i64* %i0) { -+; SPARC-LABEL: call_ret_i64_pair: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -96, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: call ret_i64_pair -+; SPARC-NEXT: nop -+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1 -+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3 -+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1 -+; SPARC-NEXT: std %o0, [%i0] -+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3 -+; SPARC-NEXT: std %o2, [%i0] -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: call_ret_i64_pair: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -176, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: call ret_i64_pair -+; SPARC64-NEXT: nop -+; SPARC64-NEXT: stx %o0, [%i0] -+; SPARC64-NEXT: stx %o1, [%i0] -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef, -+ i64* undef, i64* undef) -+ %e0 = extractvalue { i64, i64 } %rv, 0 -+ store volatile i64 %e0, i64* %i0 -+ %e1 = extractvalue { i64, i64 } %rv, 1 -+ store i64 %e1, i64* %i0 -+ ret void -+} -+ -+;; Functions returning structs more than six registers' worth of space -+;; should be automatically treated as an sret function. -+declare { [16 x i64] } @ret_i64_arr(i64 %input) -+ -+define i64 @call_ret_i64_arr(i64 %0) { -+; SPARC-LABEL: call_ret_i64_arr: -+; SPARC: .cfi_startproc -+; SPARC-NEXT: ! %bb.0: -+; SPARC-NEXT: save %sp, -224, %sp -+; SPARC-NEXT: .cfi_def_cfa_register %fp -+; SPARC-NEXT: .cfi_window_save -+; SPARC-NEXT: .cfi_register %o7, %i7 -+; SPARC-NEXT: add %fp, -128, %i2 -+; SPARC-NEXT: st %i2, [%sp+64] -+; SPARC-NEXT: mov %i0, %o0 -+; SPARC-NEXT: mov %i1, %o1 -+; SPARC-NEXT: call ret_i64_arr -+; SPARC-NEXT: nop -+; SPARC-NEXT: unimp 128 -+; SPARC-NEXT: ldd [%fp+-8], %i0 -+; SPARC-NEXT: restore -+; SPARC-NEXT: retl -+; SPARC-NEXT: nop -+; -+; SPARC64-LABEL: call_ret_i64_arr: -+; SPARC64: .cfi_startproc -+; SPARC64-NEXT: ! %bb.0: -+; SPARC64-NEXT: save %sp, -304, %sp -+; SPARC64-NEXT: .cfi_def_cfa_register %fp -+; SPARC64-NEXT: .cfi_window_save -+; SPARC64-NEXT: .cfi_register %o7, %i7 -+; SPARC64-NEXT: add %fp, 1919, %o0 -+; SPARC64-NEXT: mov %i0, %o1 -+; SPARC64-NEXT: call ret_i64_arr -+; SPARC64-NEXT: nop -+; SPARC64-NEXT: ldx [%fp+2039], %i0 -+; SPARC64-NEXT: restore -+; SPARC64-NEXT: retl -+; SPARC64-NEXT: nop -+ %2 = call { [16 x i64] } @ret_i64_arr(i64 %0) -+ %3 = extractvalue { [16 x i64] } %2, 0 -+ %4 = extractvalue [16 x i64] %3, 15 -+ ret i64 %4 -+} -diff --git a/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll b/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll -new file mode 100644 -index 000000000..33e501ca8 ---- /dev/null -+++ b/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll -@@ -0,0 +1,112 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -opaque-pointers | FileCheck %s --check-prefix=I386 -+; -+; Make sure we don't zero out %eax when both %ah and %al are used. -+; -+; PR1766: https://github.com/ClangBuiltLinux/linux/issues/1766 -+ -+%struct.maple_subtree_state = type { ptr } -+ -+@mas_data_end_type = dso_local local_unnamed_addr global i32 0, align 4 -+@ma_meta_end_mn_0_0_0_0_0_0 = dso_local local_unnamed_addr global i8 0, align 1 -+@mt_pivots_0 = dso_local local_unnamed_addr global i8 0, align 1 -+@mas_data_end___trans_tmp_2 = dso_local local_unnamed_addr global ptr null, align 4 -+@mt_slots_0 = dso_local local_unnamed_addr global i8 0, align 1 -+ -+define dso_local zeroext i1 @test1(ptr nocapture noundef readonly %0) local_unnamed_addr "zero-call-used-regs"="used-gpr" nounwind { -+; I386-LABEL: test1: -+; I386: # %bb.0: -+; I386-NEXT: pushl %ebx -+; I386-NEXT: subl $24, %esp -+; I386-NEXT: movl {{[0-9]+}}(%esp), %eax -+; I386-NEXT: movl (%eax), %eax -+; I386-NEXT: movzbl (%eax), %ebx -+; I386-NEXT: calll bar -+; I386-NEXT: testb %al, %al -+; I386-NEXT: # implicit-def: $al -+; I386-NEXT: # kill: killed $al -+; I386-NEXT: je .LBB0_6 -+; I386-NEXT: # %bb.1: -+; I386-NEXT: cmpl $0, mas_data_end_type -+; I386-NEXT: je .LBB0_3 -+; I386-NEXT: # %bb.2: -+; I386-NEXT: movzbl ma_meta_end_mn_0_0_0_0_0_0, %eax -+; I386-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -+; I386-NEXT: jmp .LBB0_6 -+; I386-NEXT: .LBB0_3: -+; I386-NEXT: movb mt_pivots_0, %ah -+; I386-NEXT: movb %ah, %al -+; I386-NEXT: decb %al -+; I386-NEXT: movl mas_data_end___trans_tmp_2, %ecx -+; I386-NEXT: movsbl %al, %edx -+; I386-NEXT: cmpl $0, (%ecx,%edx,4) -+; I386-NEXT: je .LBB0_5 -+; I386-NEXT: # %bb.4: -+; I386-NEXT: movb %al, %ah -+; I386-NEXT: .LBB0_5: -+; I386-NEXT: movb %ah, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -+; I386-NEXT: .LBB0_6: -+; I386-NEXT: movb mt_slots_0, %bh -+; I386-NEXT: leal {{[0-9]+}}(%esp), %eax -+; I386-NEXT: movl %eax, (%esp) -+; I386-NEXT: calll baz -+; I386-NEXT: subl $4, %esp -+; I386-NEXT: cmpb %bh, %bl -+; I386-NEXT: jae .LBB0_8 -+; I386-NEXT: # %bb.7: -+; I386-NEXT: movsbl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 1-byte Folded Reload -+; I386-NEXT: movl %eax, (%esp) -+; I386-NEXT: calll gaz -+; I386-NEXT: .LBB0_8: -+; I386-NEXT: movb $1, %al -+; I386-NEXT: addl $24, %esp -+; I386-NEXT: popl %ebx -+; I386-NEXT: xorl %ecx, %ecx -+; I386-NEXT: xorl %edx, %edx -+; I386-NEXT: retl -+ %2 = alloca %struct.maple_subtree_state, align 4 -+ %3 = load ptr, ptr %0, align 4 -+ %4 = load i8, ptr %3, align 1 -+ %5 = tail call zeroext i1 @bar() -+ br i1 %5, label %6, label %20 -+ -+6: ; preds = %1 -+ %7 = load i32, ptr @mas_data_end_type, align 4 -+ %8 = icmp eq i32 %7, 0 -+ br i1 %8, label %11, label %9 -+ -+9: ; preds = %6 -+ %10 = load i8, ptr @ma_meta_end_mn_0_0_0_0_0_0, align 1 -+ br label %20 -+ -+11: ; preds = %6 -+ %12 = load i8, ptr @mt_pivots_0, align 1 -+ %13 = add i8 %12, -1 -+ %14 = load ptr, ptr @mas_data_end___trans_tmp_2, align 4 -+ %15 = sext i8 %13 to i32 -+ %16 = getelementptr inbounds [1 x i32], ptr %14, i32 0, i32 %15 -+ %17 = load i32, ptr %16, align 4 -+ %18 = icmp eq i32 %17, 0 -+ %19 = select i1 %18, i8 %12, i8 %13 -+ br label %20 -+ -+20: ; preds = %11, %9, %1 -+ %21 = phi i8 [ undef, %1 ], [ %10, %9 ], [ %19, %11 ] -+ %22 = load i8, ptr @mt_slots_0, align 1 -+ call void @baz(ptr nonnull sret(%struct.maple_subtree_state) align 4 %2) -+ %23 = icmp ult i8 %4, %22 -+ br i1 %23, label %24, label %25 -+ -+24: ; preds = %20 -+ call void @gaz(i8 noundef signext %21) -+ br label %25 -+ -+25: ; preds = %20, %24 -+ ret i1 true -+} -+ -+declare dso_local zeroext i1 @bar(...) local_unnamed_addr -+ -+declare dso_local void @baz(ptr sret(%struct.maple_subtree_state) align 4, ...) local_unnamed_addr -+ -+declare dso_local void @gaz(i8 noundef signext) local_unnamed_addr -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s b/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s -new file mode 100644 -index 000000000..2ef26ac4b ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s -@@ -0,0 +1,25 @@ -+# RUN: llvm-mc -filetype=obj -triple loongarch64 < %s \ -+# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s -+ -+# alpha and main are 8 byte alignment -+# but the alpha function's size is 4 -+# So assembler will insert a nop to make sure 8 byte alignment. -+ -+ .text -+ .p2align 3 -+ .type alpha,@function -+alpha: -+# BB#0: -+ addi.d $sp, $sp, -16 -+# CHECK-INST: nop -+.Lfunc_end0: -+ .size alpha, .Lfunc_end0-alpha -+ # -- End function -+ .globl main -+ .p2align 3 -+ .type main,@function -+main: # @main -+# BB#0: -+.Lfunc_end1: -+ .size main, .Lfunc_end1-main -+ # -- End function -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s b/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s -new file mode 100644 -index 000000000..7e61a5ba5 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s -@@ -0,0 +1,7 @@ -+# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 | FileCheck %s -+ -+# CHECK: error: expected memory with constant 0 offset -+amadd_db.d $a1, $t5, $s6, 1 -+ -+# CHECK: error: unexpected token in argument list -+amadd_db.d $a1, $t5, $s6, a -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/atomic.s b/src/llvm-project/llvm/test/MC/LoongArch/atomic.s -new file mode 100644 -index 000000000..10a406550 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/atomic.s -@@ -0,0 +1,12 @@ -+# RUN: llvm-mc %s --triple=loongarch64 --show-encoding | \ -+# RUN: FileCheck --check-prefixes=ASM,ASM-AND-OBJ %s -+# RUN: llvm-mc %s --triple=loongarch64 --filetype=obj | llvm-objdump -d - | \ -+# RUN: FileCheck --check-prefixes=ASM-AND-OBJ %s -+ -+# ASM-AND-OBJ: amadd_db.d $r5, $r17, $r29, 0 -+# ASM: encoding: [0xa5,0xc7,0x6a,0x38] -+amadd_db.d $a1, $t5, $s6, 0 -+ -+# ASM-AND-OBJ: amadd_db.d $r5, $r17, $r29, 0 -+# ASM: encoding: [0xa5,0xc7,0x6a,0x38] -+amadd_db.d $a1, $t5, $s6 -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s b/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s -new file mode 100644 -index 000000000..d35fe7e77 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s -@@ -0,0 +1,40 @@ -+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s \ -+# RUN: | llvm-readobj -r - | FileCheck %s -+ -+# Check that subtraction expressions are emitted as two relocations -+ -+.globl G1 -+.globl G2 -+.L1: -+G1: -+nop -+.L2: -+G2: -+ -+.data -+.8byte .L2-.L1 # CHECK: 0x0 R_LARCH_ADD64 .L2 0x0 -+ # CHECK: 0x0 R_LARCH_SUB64 .L1 0x0 -+.8byte G2-G1 # CHECK: 0x8 R_LARCH_ADD64 G2 0x0 -+ # CHECK: 0x8 R_LARCH_SUB64 G1 0x0 -+.4byte .L2-.L1 # CHECK: 0x10 R_LARCH_ADD32 .L2 0x0 -+ # CHECK: 0x10 R_LARCH_SUB32 .L1 0x0 -+.4byte G2-G1 # CHECK: 0x14 R_LARCH_ADD32 G2 0x0 -+ # CHECK: 0x14 R_LARCH_SUB32 G1 0x0 -+.2byte .L2-.L1 # CHECK: 0x18 R_LARCH_ADD16 .L2 0x0 -+ # CHECK: 0x18 R_LARCH_SUB16 .L1 0x0 -+.2byte G2-G1 # CHECK: 0x1A R_LARCH_ADD16 G2 0x0 -+ # CHECK: 0x1A R_LARCH_SUB16 G1 0x0 -+.byte .L2-.L1 # CHECK: 0x1C R_LARCH_ADD8 .L2 0x0 -+ # CHECK: 0x1C R_LARCH_SUB8 .L1 0x0 -+.byte G2-G1 # CHECK: 0x1D R_LARCH_ADD8 G2 0x0 -+ # CHECK: 0x1D R_LARCH_SUB8 G1 0x0 -+ -+.section .rodata.str.1 -+.L.str: -+.asciz "string" -+ -+.rodata -+.Lreltable: -+.word .L.str-.Lreltable # CHECK: 0x0 R_LARCH_ADD32 .L.str 0x0 -+ # CHECK: 0x0 R_LARCH_SUB32 .Lreltable 0x0 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/invalid.s b/src/llvm-project/llvm/test/MC/LoongArch/invalid.s -new file mode 100644 -index 000000000..e0fc7ce4b ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/invalid.s -@@ -0,0 +1,50 @@ -+# RUN: not llvm-mc %s -triple=loongarch64-unknown-linux-gnu 2>&1 | FileCheck %s -+.text -+csrxchg $r6, $r0, 214 # CHECK: :[[@LINE]]:1: error: invalid operand ($zero) for instruction -+csrxchg $r6, $r1, 214 # CHECK: :[[@LINE]]:1: error: invalid operand ($r1) for instruction -+ -+## out-of-bound immediate -+### simm16 << 2 -+beq $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+beq $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bne $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bne $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+blt $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+blt $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bge $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bge $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bltu $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bltu $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bgeu $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bgeu $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+### simm21 << 2 -+beqz $r9, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+beqz $r9, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bnez $r9, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bnez $r9, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bceqz $fcc6, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bceqz $fcc6, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bcnez $fcc6, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bcnez $fcc6, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+### simm26 << 2 -+b -0x8000000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+b 0x7FFFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bl -0x8000000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+bl 0x7FFFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range -+ -+## unaligned immediate -+### simm16 << 2 -+beq $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bne $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+blt $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bge $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bltu $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bgeu $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+### simm21 << 2 -+beqz $r9, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bnez $r9, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bceqz $fcc6, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bcnez $fcc6, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+### simm26 << 2 -+b 0x7FFFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -+bl 0x7FFFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg -index 2b5a4893e..6223fc691 100644 ---- a/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg -+++ b/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg -@@ -1,2 +1,3 @@ - if not 'LoongArch' in config.root.targets: - config.unsupported = True -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s b/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s -new file mode 100644 -index 000000000..eca76ac69 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s -@@ -0,0 +1,168 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: la.pcrel $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: (symbol)+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] -+# CHECK: # fixup A - offset: 0, value: (symbol)+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: (symbol)+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup C - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup E - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup G - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.local $a0, symbol -+ -+# CHECK: la.got $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.global $a0, symbol -+ -+# CHECK: la.pcrel $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: (symbol)+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] -+# CHECK: # fixup A - offset: 0, value: (symbol)+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: (symbol)+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup C - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup E - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup G - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.pcrel $a0, symbol -+ -+# CHECK: la.got $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.got $a0, symbol -+ -+# CHECK: la.tls.le $r4, symbol # encoding: [0x04,0x00,0x00,0x14] -+# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL -+# CHECK: # fixup B - offset: 0, value: 32, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup D - offset: 0, value: 44, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0x80,0x03] -+# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL -+# CHECK: # fixup B - offset: 0, value: 4095, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_AND -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_U_10_12 -+# CHECK: # la expanded slot # encoding: [0x04,0x00,0x00,0x16] -+# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL -+# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup D - offset: 0, value: 44, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0x00,0x03] -+# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL -+# CHECK: # fixup B - offset: 0, value: 52, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.tls.le $a0, symbol -+ -+# CHECK: la.tls.ie $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.tls.ie $a0, symbol -+ -+# CHECK: la.tls.gd $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.tls.ld $a0, symbol -+ -+# CHECK: la.tls.gd $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 -+# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] -+# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL -+# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD -+# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD -+# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR -+# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE -+# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL -+# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB -+# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 -+la.tls.gd $a0, symbol -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s b/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s -new file mode 100644 -index 000000000..b1a7c58ba ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s -@@ -0,0 +1,773 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu | FileCheck %s -+li.w $a0, 0x00000000 # CHECK: ori $r4, $zero, 0 -+li.w $a0, 0x000007ff # CHECK: ori $r4, $zero, 2047 -+li.w $a0, 0x00000800 # CHECK: ori $r4, $zero, 2048 -+li.w $a0, 0x00000fff # CHECK: ori $r4, $zero, 4095 -+li.w $a0, 0x7ffff000 # CHECK: lu12i.w $r4, 524287 -+li.w $a0, 0x7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+li.w $a0, 0x7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+li.w $a0, 0x7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+li.w $a0, 0x80000000 # CHECK: lu12i.w $r4, -524288 -+li.w $a0, 0x800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+li.w $a0, 0x80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+li.w $a0, 0x80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+li.w $a0, 0xfffff000 # CHECK: lu12i.w $r4, -1 -+li.w $a0, 0xfffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+li.w $a0, 0xfffff800 # CHECK: addi.w $r4, $zero, -2048 -+li.w $a0, 0xffffffff # CHECK: addi.w $r4, $zero, -1 -+li.d $a0, 0x0000000000000000 # CHECK: addi.d $r4, $zero, 0 -+li.d $a0, 0x00000000000007ff # CHECK: addi.d $r4, $zero, 2047 -+li.d $a0, 0x0000000000000800 # CHECK: ori $r4, $zero, 2048 -+li.d $a0, 0x0000000000000fff # CHECK: ori $r4, $zero, 4095 -+li.d $a0, 0x000000007ffff000 # CHECK: lu12i.w $r4, 524287 -+li.d $a0, 0x000000007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+li.d $a0, 0x000000007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+li.d $a0, 0x000000007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+li.d $a0, 0x0000000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x00000000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x0000000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x0000000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x00000000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x00000000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x00000000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x00000000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 0 -+li.d $a0, 0x0007ffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007fffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007fffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007fffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0007ffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 524287 -+li.d $a0, 0x0008000000000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x0008000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x0008000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000800007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000800007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000800007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000800007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x0008000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x0008000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x0008000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x00080000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000ffffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000ffffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000ffffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x000fffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu52i.d $r4, $r4, 0 -+li.d $a0, 0x7ff0000000000000 # CHECK: lu52i.d $r4, $zero, 2047 -+li.d $a0, 0x7ff00000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff0000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff0000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff000007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff000007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff000007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff000007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff0000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff00000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff0000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff0000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff00000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff00000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff00000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff00000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7fffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7fffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7fffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff7ffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000000000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff800007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff800007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff800007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff800007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff8000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ff80000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ffffffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ffffffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7ffffffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x7fffffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu52i.d $r4, $r4, 2047 -+li.d $a0, 0x8000000000000000 # CHECK: lu52i.d $r4, $zero, -2048 -+li.d $a0, 0x80000000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8000000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8000000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800000007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800000007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800000007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800000007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8000000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80000000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8000000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8000000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80000000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80000000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80000000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80000000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007fffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007fffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007fffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8007ffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000000000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800800007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800800007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800800007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800800007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x8008000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x80080000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800ffffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800ffffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800ffffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0x800fffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu52i.d $r4, $r4, -2048 -+li.d $a0, 0xfff0000000000000 # CHECK: lu52i.d $r4, $zero, -1 -+li.d $a0, 0xfff00000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff0000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff0000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff000007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff000007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff000007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff000007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff0000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff00000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff0000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff0000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff00000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff00000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff00000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff00000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 0 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff80000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7fffffffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7fffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7fffffffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff7ffffffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, 524287 -+ # CHECK: lu52i.d $r4, $r4, -1 -+li.d $a0, 0xfff8000000000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff8000000000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff8000000000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff800007ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff800007ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff800007ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff800007fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff8000080000000 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff8000080000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff8000080000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000fffff000 # CHECK: lu12i.w $r4, -1 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000fffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000fffff800 # CHECK: addi.w $r4, $zero, -2048 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xfff80000ffffffff # CHECK: addi.w $r4, $zero, -1 -+ # CHECK: lu32i.d $r4, -524288 -+li.d $a0, 0xffffffff00000000 # CHECK: ori $r4, $zero, 0 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff000007ff # CHECK: ori $r4, $zero, 2047 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff00000800 # CHECK: ori $r4, $zero, 2048 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff00000fff # CHECK: ori $r4, $zero, 4095 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff7ffff000 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff7ffff7ff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2047 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff7ffff800 # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 2048 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff7fffffff # CHECK: lu12i.w $r4, 524287 -+ # CHECK: ori $r4, $r4, 4095 -+ # CHECK: lu32i.d $r4, -1 -+li.d $a0, 0xffffffff80000000 # CHECK: lu12i.w $r4, -524288 -+li.d $a0, 0xffffffff800007ff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2047 -+li.d $a0, 0xffffffff80000800 # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 2048 -+li.d $a0, 0xffffffff80000fff # CHECK: lu12i.w $r4, -524288 -+ # CHECK: ori $r4, $r4, 4095 -+li.d $a0, 0xfffffffffffff000 # CHECK: lu12i.w $r4, -1 -+li.d $a0, 0xfffffffffffff7ff # CHECK: lu12i.w $r4, -1 -+ # CHECK: ori $r4, $r4, 2047 -+li.d $a0, 0xfffffffffffff800 # CHECK: addi.d $r4, $zero, -2048 -+li.d $a0, 0xffffffffffffffff # CHECK: addi.d $r4, $zero, -1 -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s -new file mode 100644 -index 000000000..ed44180bf ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s -@@ -0,0 +1,33 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: slti $r27, $ra, 235 -+# CHECK: encoding: [0x3b,0xac,0x03,0x02] -+slti $r27, $ra, 235 -+ -+# CHECK: sltui $zero, $r8, 162 -+# CHECK: encoding: [0x00,0x89,0x42,0x02] -+sltui $zero, $r8, 162 -+ -+# CHECK: addi.w $r5, $r7, 246 -+# CHECK: encoding: [0xe5,0xd8,0x83,0x02] -+addi.w $r5, $r7, 246 -+ -+# CHECK: addi.d $r28, $r6, 75 -+# CHECK: encoding: [0xdc,0x2c,0xc1,0x02] -+addi.d $r28, $r6, 75 -+ -+# CHECK: lu52i.d $r13, $r4, 195 -+# CHECK: encoding: [0x8d,0x0c,0x03,0x03] -+lu52i.d $r13, $r4, 195 -+ -+# CHECK: andi $r25, $zero, 106 -+# CHECK: encoding: [0x19,0xa8,0x41,0x03] -+andi $r25, $zero, 106 -+ -+# CHECK: ori $r17, $r5, 47 -+# CHECK: encoding: [0xb1,0xbc,0x80,0x03] -+ori $r17, $r5, 47 -+ -+# CHECK: xori $r18, $r23, 99 -+# CHECK: encoding: [0xf2,0x8e,0xc1,0x03] -+xori $r18, $r23, 99 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s -new file mode 100644 -index 000000000..1418bb677 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s -@@ -0,0 +1,53 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: fmadd.s $f3, $f16, $f3, $f15 -+# CHECK: encoding: [0x03,0x8e,0x17,0x08] -+fmadd.s $f3, $f16, $f3, $f15 -+ -+# CHECK: fmadd.d $f21, $f24, $f28, $f24 -+# CHECK: encoding: [0x15,0x73,0x2c,0x08] -+fmadd.d $f21, $f24, $f28, $f24 -+ -+# CHECK: fmsub.s $f23, $f11, $f21, $f4 -+# CHECK: encoding: [0x77,0x55,0x52,0x08] -+fmsub.s $f23, $f11, $f21, $f4 -+ -+# CHECK: fmsub.d $f6, $f18, $f20, $f27 -+# CHECK: encoding: [0x46,0xd2,0x6d,0x08] -+fmsub.d $f6, $f18, $f20, $f27 -+ -+# CHECK: fnmadd.s $f29, $f1, $f24, $f20 -+# CHECK: encoding: [0x3d,0x60,0x9a,0x08] -+fnmadd.s $f29, $f1, $f24, $f20 -+ -+# CHECK: fnmadd.d $f25, $f13, $f19, $f30 -+# CHECK: encoding: [0xb9,0x4d,0xaf,0x08] -+fnmadd.d $f25, $f13, $f19, $f30 -+ -+# CHECK: fnmsub.s $f8, $f4, $f24, $f25 -+# CHECK: encoding: [0x88,0xe0,0xdc,0x08] -+fnmsub.s $f8, $f4, $f24, $f25 -+ -+# CHECK: fnmsub.d $f30, $f26, $f7, $f24 -+# CHECK: encoding: [0x5e,0x1f,0xec,0x08] -+fnmsub.d $f30, $f26, $f7, $f24 -+ -+# CHECK: fcmp.ceq.s $fcc7, $f17, $f29 -+# CHECK: encoding: [0x27,0x76,0x12,0x0c] -+fcmp.ceq.s $fcc7, $f17, $f29 -+ -+# CHECK: fcmp.ceq.d $fcc4, $f12, $f9 -+# CHECK: encoding: [0x84,0x25,0x22,0x0c] -+fcmp.ceq.d $fcc4, $f12, $f9 -+ -+# CHECK: fcmp.cult.s $fcc0, $f0, $f1 -+# CHECK: encoding: [0x00,0x04,0x15,0x0c] -+fcmp.cult.s $fcc0, $f0, $f1 -+ -+# CHECK: fcmp.cult.d $fcc2, $f3, $f4 -+# CHECK: encoding: [0x62,0x10,0x25,0x0c] -+fcmp.cult.d $fcc2, $f3, $f4 -+ -+# CHECK: fsel $f18, $f20, $f21, $fcc4 -+# CHECK: encoding: [0x92,0x56,0x02,0x0d] -+fsel $f18, $f20, $f21, $fcc4 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s -new file mode 100644 -index 000000000..d7b3bbb7d ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s -@@ -0,0 +1,33 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: addu16i.d $r9, $r23, 23 -+# CHECK: encoding: [0xe9,0x5e,0x00,0x10] -+addu16i.d $r9, $r23, 23 -+ -+# CHECK: lu12i.w $r16, 49 -+# CHECK: encoding: [0x30,0x06,0x00,0x14] -+lu12i.w $r16, 49 -+ -+# CHECK: lu12i.w $r4, -1 -+# CHECK: encoding: [0xe4,0xff,0xff,0x15] -+lu12i.w $r4, -1 -+ -+# CHECK: lu32i.d $sp, 196 -+# CHECK: encoding: [0x83,0x18,0x00,0x16] -+lu32i.d $sp, 196 -+ -+# CHECK: pcaddi $r9, 187 -+# CHECK: encoding: [0x69,0x17,0x00,0x18] -+pcaddi $r9, 187 -+ -+# CHECK: pcalau12i $r10, 89 -+# CHECK: encoding: [0x2a,0x0b,0x00,0x1a] -+pcalau12i $r10, 89 -+ -+# CHECK: pcaddu12i $zero, 37 -+# CHECK: encoding: [0xa0,0x04,0x00,0x1c] -+pcaddu12i $zero, 37 -+ -+# CHECK: pcaddu18i $r12, 26 -+# CHECK: encoding: [0x4c,0x03,0x00,0x1e] -+pcaddu18i $r12, 26 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s -new file mode 100644 -index 000000000..256e70b6d ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s -@@ -0,0 +1,155 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding \ -+# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM %s -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -filetype=obj \ -+# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-ASM-AND-OBJ %s -+ -+## random operands -+# CHECK-ASM-AND-OBJ: beqz $r9, 96 -+# CHECK-ASM: encoding: [0x20,0x61,0x00,0x40] -+beqz $r9, 96 -+ -+# CHECK-ASM-AND-OBJ: bnez $sp, 212 -+# CHECK-ASM: encoding: [0x60,0xd4,0x00,0x44] -+bnez $sp, 212 -+ -+# CHECK-ASM-AND-OBJ: bceqz $fcc6, 12 -+# CHECK-ASM: encoding: [0xc0,0x0c,0x00,0x48] -+bceqz $fcc6, 12 -+ -+# CHECK-ASM-AND-OBJ: bcnez $fcc6, 72 -+# CHECK-ASM: encoding: [0xc0,0x49,0x00,0x48] -+bcnez $fcc6, 72 -+ -+# CHECK-ASM-AND-OBJ: b 248 -+# CHECK-ASM: encoding: [0x00,0xf8,0x00,0x50] -+b 248 -+ -+# CHECK-ASM-AND-OBJ: bl 236 -+# CHECK-ASM: encoding: [0x00,0xec,0x00,0x54] -+bl 236 -+ -+# CHECK-ASM-AND-OBJ: beq $r10, $r7, 176 -+# CHECK-ASM: encoding: [0x47,0xb1,0x00,0x58] -+beq $r10, $r7, 176 -+ -+# CHECK-ASM-AND-OBJ: bne $r25, $ra, 136 -+# CHECK-ASM: encoding: [0x21,0x8b,0x00,0x5c] -+bne $r25, $ra, 136 -+ -+# CHECK-ASM-AND-OBJ: blt $r15, $r30, 168 -+# CHECK-ASM: encoding: [0xfe,0xa9,0x00,0x60] -+blt $r15, $r30, 168 -+ -+# CHECK-ASM-AND-OBJ: bge $r12, $r15, 148 -+# CHECK-ASM: encoding: [0x8f,0x95,0x00,0x64] -+bge $r12, $r15, 148 -+ -+# CHECK-ASM-AND-OBJ: bltu $r17, $r5, 4 -+# CHECK-ASM: encoding: [0x25,0x06,0x00,0x68] -+bltu $r17, $r5, 4 -+ -+# CHECK-ASM-AND-OBJ: bgeu $r6, $r23, 140 -+# CHECK-ASM: encoding: [0xd7,0x8c,0x00,0x6c] -+bgeu $r6, $r23, 140 -+ -+ -+## immediate lower/upper boundary -+### simm16 << 2 -+# CHECK-ASM-AND-OBJ: beq $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x5a] -+beq $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: beq $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x59] -+beq $r10, $r7, 0x1FFFC -+ -+# CHECK-ASM-AND-OBJ: bne $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x5e] -+bne $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: bne $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x5d] -+bne $r10, $r7, 0x1FFFC -+ -+# CHECK-ASM-AND-OBJ: blt $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x62] -+blt $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: blt $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x61] -+blt $r10, $r7, 0x1FFFC -+ -+# CHECK-ASM-AND-OBJ: bge $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x66] -+bge $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: bge $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x65] -+bge $r10, $r7, 0x1FFFC -+ -+# CHECK-ASM-AND-OBJ: bltu $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x6a] -+bltu $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: bltu $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x69] -+bltu $r10, $r7, 0x1FFFC -+ -+# CHECK-ASM-AND-OBJ: bgeu $r10, $r7, -131072 -+# CHECK-ASM: encoding: [0x47,0x01,0x00,0x6e] -+bgeu $r10, $r7, -0x20000 -+ -+# CHECK-ASM-AND-OBJ: bgeu $r10, $r7, 131068 -+# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x6d] -+bgeu $r10, $r7, 0x1FFFC -+ -+### simm21 << 2 -+# CHECK-ASM-AND-OBJ: beqz $r9, -4194304 -+# CHECK-ASM: encoding: [0x30,0x01,0x00,0x40] -+beqz $r9, -0x400000 -+ -+# CHECK-ASM-AND-OBJ: beqz $r9, 4194300 -+# CHECK-ASM: encoding: [0x2f,0xfd,0xff,0x43] -+beqz $r9, 0x3FFFFC -+ -+# CHECK-ASM-AND-OBJ: bnez $r9, -4194304 -+# CHECK-ASM: encoding: [0x30,0x01,0x00,0x44] -+bnez $r9, -0x400000 -+ -+# CHECK-ASM-AND-OBJ: bnez $r9, 4194300 -+# CHECK-ASM: encoding: [0x2f,0xfd,0xff,0x47] -+bnez $r9, 0x3FFFFC -+ -+# CHECK-ASM-AND-OBJ: bceqz $fcc6, -4194304 -+# CHECK-ASM: encoding: [0xd0,0x00,0x00,0x48] -+bceqz $fcc6, -0x400000 -+ -+# CHECK-ASM-AND-OBJ: bceqz $fcc6, 4194300 -+# CHECK-ASM: encoding: [0xcf,0xfc,0xff,0x4b] -+bceqz $fcc6, 0x3FFFFC -+ -+# CHECK-ASM-AND-OBJ: bcnez $fcc6, -4194304 -+# CHECK-ASM: encoding: [0xd0,0x01,0x00,0x48] -+bcnez $fcc6, -0x400000 -+ -+# CHECK-ASM-AND-OBJ: bcnez $fcc6, 4194300 -+# CHECK-ASM: encoding: [0xcf,0xfd,0xff,0x4b] -+bcnez $fcc6, 0x3FFFFC -+ -+### simm26 << 2 -+# CHECK-ASM-AND-OBJ: b -134217728 -+# CHECK-ASM: encoding: [0x00,0x02,0x00,0x50] -+b -0x8000000 -+ -+# CHECK-ASM-AND-OBJ: b 134217724 -+# CHECK-ASM: encoding: [0xff,0xfd,0xff,0x53] -+b 0x7FFFFFC -+ -+# CHECK-ASM-AND-OBJ: bl -134217728 -+# CHECK-ASM: encoding: [0x00,0x02,0x00,0x54] -+bl -0x8000000 -+ -+# CHECK-ASM-AND-OBJ: bl 134217724 -+# CHECK-ASM: encoding: [0xff,0xfd,0xff,0x57] -+bl 0x7FFFFFC -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s -new file mode 100644 -index 000000000..05ecefdc1 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s -@@ -0,0 +1,297 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: fadd.s $f29, $f15, $f25 -+# CHECK: encoding: [0xfd,0xe5,0x00,0x01] -+fadd.s $f29, $f15, $f25 -+ -+# CHECK: fadd.d $f25, $f7, $f13 -+# CHECK: encoding: [0xf9,0x34,0x01,0x01] -+fadd.d $f25, $f7, $f13 -+ -+# CHECK: fsub.s $f14, $f6, $f31 -+# CHECK: encoding: [0xce,0xfc,0x02,0x01] -+fsub.s $f14, $f6, $f31 -+ -+# CHECK: fsub.d $f29, $f1, $f18 -+# CHECK: encoding: [0x3d,0x48,0x03,0x01] -+fsub.d $f29, $f1, $f18 -+ -+# CHECK: fmul.s $f0, $f7, $f17 -+# CHECK: encoding: [0xe0,0xc4,0x04,0x01] -+fmul.s $f0, $f7, $f17 -+ -+# CHECK: fmul.d $f4, $f30, $f7 -+# CHECK: encoding: [0xc4,0x1f,0x05,0x01] -+fmul.d $f4, $f30, $f7 -+ -+# CHECK: fdiv.s $f20, $f24, $f19 -+# CHECK: encoding: [0x14,0xcf,0x06,0x01] -+fdiv.s $f20, $f24, $f19 -+ -+# CHECK: fdiv.d $f3, $f25, $f28 -+# CHECK: encoding: [0x23,0x73,0x07,0x01] -+fdiv.d $f3, $f25, $f28 -+ -+# CHECK: fmax.s $f22, $f6, $f27 -+# CHECK: encoding: [0xd6,0xec,0x08,0x01] -+fmax.s $f22, $f6, $f27 -+ -+# CHECK: fmax.d $f11, $f26, $f13 -+# CHECK: encoding: [0x4b,0x37,0x09,0x01] -+fmax.d $f11, $f26, $f13 -+ -+# CHECK: fmin.s $f14, $f10, $f19 -+# CHECK: encoding: [0x4e,0xcd,0x0a,0x01] -+fmin.s $f14, $f10, $f19 -+ -+# CHECK: fmin.d $f1, $f13, $f27 -+# CHECK: encoding: [0xa1,0x6d,0x0b,0x01] -+fmin.d $f1, $f13, $f27 -+ -+# CHECK: fmaxa.s $f9, $f27, $f31 -+# CHECK: encoding: [0x69,0xff,0x0c,0x01] -+fmaxa.s $f9, $f27, $f31 -+ -+# CHECK: fmaxa.d $f24, $f13, $f4 -+# CHECK: encoding: [0xb8,0x11,0x0d,0x01] -+fmaxa.d $f24, $f13, $f4 -+ -+# CHECK: fmina.s $f15, $f18, $f1 -+# CHECK: encoding: [0x4f,0x86,0x0e,0x01] -+fmina.s $f15, $f18, $f1 -+ -+# CHECK: fmina.d $f18, $f10, $f0 -+# CHECK: encoding: [0x52,0x01,0x0f,0x01] -+fmina.d $f18, $f10, $f0 -+ -+# CHECK: fscaleb.s $f21, $f23, $f6 -+# CHECK: encoding: [0xf5,0x9a,0x10,0x01] -+fscaleb.s $f21, $f23, $f6 -+ -+# CHECK: fscaleb.d $f12, $f14, $f26 -+# CHECK: encoding: [0xcc,0x69,0x11,0x01] -+fscaleb.d $f12, $f14, $f26 -+ -+# CHECK: fcopysign.s $f13, $f24, $f23 -+# CHECK: encoding: [0x0d,0xdf,0x12,0x01] -+fcopysign.s $f13, $f24, $f23 -+ -+# CHECK: fcopysign.d $f16, $f26, $f6 -+# CHECK: encoding: [0x50,0x1b,0x13,0x01] -+fcopysign.d $f16, $f26, $f6 -+ -+# CHECK: fabs.s $f28, $f12 -+# CHECK: encoding: [0x9c,0x05,0x14,0x01] -+fabs.s $f28, $f12 -+ -+# CHECK: fabs.d $f23, $f3 -+# CHECK: encoding: [0x77,0x08,0x14,0x01] -+fabs.d $f23, $f3 -+ -+# CHECK: fneg.s $f21, $f24 -+# CHECK: encoding: [0x15,0x17,0x14,0x01] -+fneg.s $f21, $f24 -+ -+# CHECK: fneg.d $f11, $f26 -+# CHECK: encoding: [0x4b,0x1b,0x14,0x01] -+fneg.d $f11, $f26 -+ -+# CHECK: flogb.s $f31, $f23 -+# CHECK: encoding: [0xff,0x26,0x14,0x01] -+flogb.s $f31, $f23 -+ -+# CHECK: flogb.d $f21, $f29 -+# CHECK: encoding: [0xb5,0x2b,0x14,0x01] -+flogb.d $f21, $f29 -+ -+# CHECK: fclass.s $f20, $f9 -+# CHECK: encoding: [0x34,0x35,0x14,0x01] -+fclass.s $f20, $f9 -+ -+# CHECK: fclass.d $f19, $f2 -+# CHECK: encoding: [0x53,0x38,0x14,0x01] -+fclass.d $f19, $f2 -+ -+# CHECK: fsqrt.s $f27, $f18 -+# CHECK: encoding: [0x5b,0x46,0x14,0x01] -+fsqrt.s $f27, $f18 -+ -+# CHECK: fsqrt.d $f2, $f11 -+# CHECK: encoding: [0x62,0x49,0x14,0x01] -+fsqrt.d $f2, $f11 -+ -+# CHECK: frecip.s $f17, $f27 -+# CHECK: encoding: [0x71,0x57,0x14,0x01] -+frecip.s $f17, $f27 -+ -+# CHECK: frecip.d $f27, $f27 -+# CHECK: encoding: [0x7b,0x5b,0x14,0x01] -+frecip.d $f27, $f27 -+ -+# CHECK: frsqrt.s $f25, $f12 -+# CHECK: encoding: [0x99,0x65,0x14,0x01] -+frsqrt.s $f25, $f12 -+ -+# CHECK: frsqrt.d $f22, $f3 -+# CHECK: encoding: [0x76,0x68,0x14,0x01] -+frsqrt.d $f22, $f3 -+ -+# CHECK: fmov.s $f13, $f23 -+# CHECK: encoding: [0xed,0x96,0x14,0x01] -+fmov.s $f13, $f23 -+ -+# CHECK: fmov.d $f30, $f9 -+# CHECK: encoding: [0x3e,0x99,0x14,0x01] -+fmov.d $f30, $f9 -+ -+# CHECK: movgr2fr.w $f6, $tp -+# CHECK: encoding: [0x46,0xa4,0x14,0x01] -+movgr2fr.w $f6, $tp -+ -+# CHECK: movgr2fr.d $f30, $r11 -+# CHECK: encoding: [0x7e,0xa9,0x14,0x01] -+movgr2fr.d $f30, $r11 -+ -+# CHECK: movgr2frh.w $f23, $r26 -+# CHECK: encoding: [0x57,0xaf,0x14,0x01] -+movgr2frh.w $f23, $r26 -+ -+# CHECK: movfr2gr.s $r10, $f22 -+# CHECK: encoding: [0xca,0xb6,0x14,0x01] -+movfr2gr.s $r10, $f22 -+ -+# CHECK: movfr2gr.d $r26, $f17 -+# CHECK: encoding: [0x3a,0xba,0x14,0x01] -+movfr2gr.d $r26, $f17 -+ -+# CHECK: movfrh2gr.s $sp, $f26 -+# CHECK: encoding: [0x43,0xbf,0x14,0x01] -+movfrh2gr.s $sp, $f26 -+ -+# CHECK: movfr2cf $fcc4, $f11 -+# CHECK: encoding: [0x64,0xd1,0x14,0x01] -+movfr2cf $fcc4, $f11 -+ -+# CHECK: movcf2fr $f16, $fcc0 -+# CHECK: encoding: [0x10,0xd4,0x14,0x01] -+movcf2fr $f16, $fcc0 -+ -+# CHECK: movgr2cf $fcc5, $ra -+# CHECK: encoding: [0x25,0xd8,0x14,0x01] -+movgr2cf $fcc5, $ra -+ -+# CHECK: movcf2gr $r21, $fcc7 -+# CHECK: encoding: [0xf5,0xdc,0x14,0x01] -+movcf2gr $r21, $fcc7 -+ -+# CHECK: fcvt.s.d $f12, $f19 -+# CHECK: encoding: [0x6c,0x1a,0x19,0x01] -+fcvt.s.d $f12, $f19 -+ -+# CHECK: fcvt.d.s $f10, $f6 -+# CHECK: encoding: [0xca,0x24,0x19,0x01] -+fcvt.d.s $f10, $f6 -+ -+# CHECK: ftintrm.w.s $f16, $f16 -+# CHECK: encoding: [0x10,0x06,0x1a,0x01] -+ftintrm.w.s $f16, $f16 -+ -+# CHECK: ftintrm.w.d $f7, $f8 -+# CHECK: encoding: [0x07,0x09,0x1a,0x01] -+ftintrm.w.d $f7, $f8 -+ -+# CHECK: ftintrm.l.s $f24, $f10 -+# CHECK: encoding: [0x58,0x25,0x1a,0x01] -+ftintrm.l.s $f24, $f10 -+ -+# CHECK: ftintrm.l.d $f9, $f9 -+# CHECK: encoding: [0x29,0x29,0x1a,0x01] -+ftintrm.l.d $f9, $f9 -+ -+# CHECK: ftintrp.w.s $f14, $f31 -+# CHECK: encoding: [0xee,0x47,0x1a,0x01] -+ftintrp.w.s $f14, $f31 -+ -+# CHECK: ftintrp.w.d $f12, $f3 -+# CHECK: encoding: [0x6c,0x48,0x1a,0x01] -+ftintrp.w.d $f12, $f3 -+ -+# CHECK: ftintrp.l.s $f0, $f16 -+# CHECK: encoding: [0x00,0x66,0x1a,0x01] -+ftintrp.l.s $f0, $f16 -+ -+# CHECK: ftintrp.l.d $f4, $f29 -+# CHECK: encoding: [0xa4,0x6b,0x1a,0x01] -+ftintrp.l.d $f4, $f29 -+ -+# CHECK: ftintrz.w.s $f4, $f29 -+# CHECK: encoding: [0xa4,0x87,0x1a,0x01] -+ftintrz.w.s $f4, $f29 -+ -+# CHECK: ftintrz.w.d $f25, $f24 -+# CHECK: encoding: [0x19,0x8b,0x1a,0x01] -+ftintrz.w.d $f25, $f24 -+ -+# CHECK: ftintrz.l.s $f23, $f5 -+# CHECK: encoding: [0xb7,0xa4,0x1a,0x01] -+ftintrz.l.s $f23, $f5 -+ -+# CHECK: ftintrz.l.d $f3, $f10 -+# CHECK: encoding: [0x43,0xa9,0x1a,0x01] -+ftintrz.l.d $f3, $f10 -+ -+# CHECK: ftintrne.w.s $f4, $f17 -+# CHECK: encoding: [0x24,0xc6,0x1a,0x01] -+ftintrne.w.s $f4, $f17 -+ -+# CHECK: ftintrne.w.d $f31, $f12 -+# CHECK: encoding: [0x9f,0xc9,0x1a,0x01] -+ftintrne.w.d $f31, $f12 -+ -+# CHECK: ftintrne.l.s $f22, $f27 -+# CHECK: encoding: [0x76,0xe7,0x1a,0x01] -+ftintrne.l.s $f22, $f27 -+ -+# CHECK: ftintrne.l.d $f28, $f6 -+# CHECK: encoding: [0xdc,0xe8,0x1a,0x01] -+ftintrne.l.d $f28, $f6 -+ -+# CHECK: ftint.w.s $f21, $f13 -+# CHECK: encoding: [0xb5,0x05,0x1b,0x01] -+ftint.w.s $f21, $f13 -+ -+# CHECK: ftint.w.d $f3, $f14 -+# CHECK: encoding: [0xc3,0x09,0x1b,0x01] -+ftint.w.d $f3, $f14 -+ -+# CHECK: ftint.l.s $f31, $f24 -+# CHECK: encoding: [0x1f,0x27,0x1b,0x01] -+ftint.l.s $f31, $f24 -+ -+# CHECK: ftint.l.d $f16, $f24 -+# CHECK: encoding: [0x10,0x2b,0x1b,0x01] -+ftint.l.d $f16, $f24 -+ -+# CHECK: ffint.s.w $f30, $f5 -+# CHECK: encoding: [0xbe,0x10,0x1d,0x01] -+ffint.s.w $f30, $f5 -+ -+# CHECK: ffint.s.l $f6, $f5 -+# CHECK: encoding: [0xa6,0x18,0x1d,0x01] -+ffint.s.l $f6, $f5 -+ -+# CHECK: ffint.d.w $f24, $f18 -+# CHECK: encoding: [0x58,0x22,0x1d,0x01] -+ffint.d.w $f24, $f18 -+ -+# CHECK: ffint.d.l $f23, $f26 -+# CHECK: encoding: [0x57,0x2b,0x1d,0x01] -+ffint.d.l $f23, $f26 -+ -+# CHECK: frint.s $f5, $f17 -+# CHECK: encoding: [0x25,0x46,0x1e,0x01] -+frint.s $f5, $f17 -+ -+# CHECK: frint.d $f29, $f2 -+# CHECK: encoding: [0x5d,0x48,0x1e,0x01] -+frint.d $f29, $f2 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s -new file mode 100644 -index 000000000..cc78662d5 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s -@@ -0,0 +1,369 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: clo.w $ra, $sp -+# CHECK: encoding: [0x61,0x10,0x00,0x00] -+clo.w $ra, $sp -+ -+# CHECK: clz.w $r7, $r10 -+# CHECK: encoding: [0x47,0x15,0x00,0x00] -+clz.w $r7, $r10 -+ -+# CHECK: cto.w $tp, $r6 -+# CHECK: encoding: [0xc2,0x18,0x00,0x00] -+cto.w $tp, $r6 -+ -+# CHECK: ctz.w $r5, $r22 -+# CHECK: encoding: [0xc5,0x1e,0x00,0x00] -+ctz.w $r5, $r22 -+ -+# CHECK: clo.d $r29, $ra -+# CHECK: encoding: [0x3d,0x20,0x00,0x00] -+clo.d $r29, $ra -+ -+# CHECK: clz.d $r26, $r26 -+# CHECK: encoding: [0x5a,0x27,0x00,0x00] -+clz.d $r26, $r26 -+ -+# CHECK: cto.d $r18, $r20 -+# CHECK: encoding: [0x92,0x2a,0x00,0x00] -+cto.d $r18, $r20 -+ -+# CHECK: ctz.d $r17, $r10 -+# CHECK: encoding: [0x51,0x2d,0x00,0x00] -+ctz.d $r17, $r10 -+ -+# CHECK: revb.2h $r20, $r11 -+# CHECK: encoding: [0x74,0x31,0x00,0x00] -+revb.2h $r20, $r11 -+ -+# CHECK: revb.4h $r13, $r19 -+# CHECK: encoding: [0x6d,0x36,0x00,0x00] -+revb.4h $r13, $r19 -+ -+# CHECK: revb.2w $r28, $r27 -+# CHECK: encoding: [0x7c,0x3b,0x00,0x00] -+revb.2w $r28, $r27 -+ -+# CHECK: revb.d $zero, $r23 -+# CHECK: encoding: [0xe0,0x3e,0x00,0x00] -+revb.d $zero, $r23 -+ -+# CHECK: revh.2w $r28, $r10 -+# CHECK: encoding: [0x5c,0x41,0x00,0x00] -+revh.2w $r28, $r10 -+ -+# CHECK: revh.d $r9, $r7 -+# CHECK: encoding: [0xe9,0x44,0x00,0x00] -+revh.d $r9, $r7 -+ -+# CHECK: bitrev.4b $r21, $r27 -+# CHECK: encoding: [0x75,0x4b,0x00,0x00] -+bitrev.4b $r21, $r27 -+ -+# CHECK: bitrev.8b $r13, $r25 -+# CHECK: encoding: [0x2d,0x4f,0x00,0x00] -+bitrev.8b $r13, $r25 -+ -+# CHECK: bitrev.w $r25, $r5 -+# CHECK: encoding: [0xb9,0x50,0x00,0x00] -+bitrev.w $r25, $r5 -+ -+# CHECK: bitrev.d $r19, $r23 -+# CHECK: encoding: [0xf3,0x56,0x00,0x00] -+bitrev.d $r19, $r23 -+ -+# CHECK: ext.w.h $r23, $r23 -+# CHECK: encoding: [0xf7,0x5a,0x00,0x00] -+ext.w.h $r23, $r23 -+ -+# CHECK: ext.w.b $r20, $r18 -+# CHECK: encoding: [0x54,0x5e,0x00,0x00] -+ext.w.b $r20, $r18 -+ -+# CHECK: rdtimel.w $r24, $r4 -+# CHECK: encoding: [0x98,0x60,0x00,0x00] -+rdtimel.w $r24, $r4 -+ -+# CHECK: rdtimeh.w $r11, $r5 -+# CHECK: encoding: [0xab,0x64,0x00,0x00] -+rdtimeh.w $r11, $r5 -+ -+# CHECK: rdtime.d $tp, $ra -+# CHECK: encoding: [0x22,0x68,0x00,0x00] -+rdtime.d $tp, $ra -+ -+# CHECK: cpucfg $sp, $ra -+# CHECK: encoding: [0x23,0x6c,0x00,0x00] -+cpucfg $sp, $ra -+ -+# CHECK: asrtle.d $r21, $r19 -+# CHECK: encoding: [0xa0,0x4e,0x01,0x00] -+asrtle.d $r21, $r19 -+ -+# CHECK: asrtgt.d $ra, $r19 -+# CHECK: encoding: [0x20,0xcc,0x01,0x00] -+asrtgt.d $ra, $r19 -+ -+# CHECK: alsl.w $tp, $r17, $tp, 4 -+# CHECK: encoding: [0x22,0x8a,0x05,0x00] -+alsl.w $tp, $r17, $tp, 4 -+ -+# CHECK: bytepick.w $r29, $zero, $r16, 0 -+# CHECK: encoding: [0x1d,0x40,0x08,0x00] -+bytepick.w $r29, $zero, $r16, 0 -+ -+# CHECK: bytepick.d $r15, $r17, $r20, 4 -+# CHECK: encoding: [0x2f,0x52,0x0e,0x00] -+bytepick.d $r15, $r17, $r20, 4 -+ -+# CHECK: add.w $r9, $ra, $r31 -+# CHECK: encoding: [0x29,0x7c,0x10,0x00] -+add.w $r9, $ra, $r31 -+ -+# CHECK: add.d $tp, $r18, $r27 -+# CHECK: encoding: [0x42,0xee,0x10,0x00] -+add.d $tp, $r18, $r27 -+ -+# CHECK: sub.w $r21, $r25, $r19 -+# CHECK: encoding: [0x35,0x4f,0x11,0x00] -+sub.w $r21, $r25, $r19 -+ -+# CHECK: sub.d $r7, $r12, $r7 -+# CHECK: encoding: [0x87,0x9d,0x11,0x00] -+sub.d $r7, $r12, $r7 -+ -+# CHECK: slt $r29, $r26, $tp -+# CHECK: encoding: [0x5d,0x0b,0x12,0x00] -+slt $r29, $r26, $tp -+ -+# CHECK: sltu $r11, $r21, $r29 -+# CHECK: encoding: [0xab,0xf6,0x12,0x00] -+sltu $r11, $r21, $r29 -+ -+# CHECK: maskeqz $r20, $r11, $r18 -+# CHECK: encoding: [0x74,0x49,0x13,0x00] -+maskeqz $r20, $r11, $r18 -+ -+# CHECK: masknez $r20, $r13, $r26 -+# CHECK: encoding: [0xb4,0xe9,0x13,0x00] -+masknez $r20, $r13, $r26 -+ -+# CHECK: nor $r5, $r18, $r5 -+# CHECK: encoding: [0x45,0x16,0x14,0x00] -+nor $r5, $r18, $r5 -+ -+# CHECK: and $r19, $r31, $ra -+# CHECK: encoding: [0xf3,0x87,0x14,0x00] -+and $r19, $r31, $ra -+ -+# CHECK: or $r17, $r16, $r30 -+# CHECK: encoding: [0x11,0x7a,0x15,0x00] -+or $r17, $r16, $r30 -+ -+# CHECK: xor $r15, $r19, $r8 -+# CHECK: encoding: [0x6f,0xa2,0x15,0x00] -+xor $r15, $r19, $r8 -+ -+# CHECK: orn $tp, $sp, $r25 -+# CHECK: encoding: [0x62,0x64,0x16,0x00] -+orn $tp, $sp, $r25 -+ -+# CHECK: andn $r28, $r25, $r5 -+# CHECK: encoding: [0x3c,0x97,0x16,0x00] -+andn $r28, $r25, $r5 -+ -+# CHECK: sll.w $r24, $r27, $r23 -+# CHECK: encoding: [0x78,0x5f,0x17,0x00] -+sll.w $r24, $r27, $r23 -+ -+# CHECK: srl.w $r31, $r17, $r7 -+# CHECK: encoding: [0x3f,0x9e,0x17,0x00] -+srl.w $r31, $r17, $r7 -+ -+# CHECK: sra.w $r12, $r28, $r10 -+# CHECK: encoding: [0x8c,0x2b,0x18,0x00] -+sra.w $r12, $r28, $r10 -+ -+# CHECK: sll.d $r20, $r15, $sp -+# CHECK: encoding: [0xf4,0x8d,0x18,0x00] -+sll.d $r20, $r15, $sp -+ -+# CHECK: srl.d $r14, $r25, $zero -+# CHECK: encoding: [0x2e,0x03,0x19,0x00] -+srl.d $r14, $r25, $zero -+ -+# CHECK: sra.d $r7, $r22, $r31 -+# CHECK: encoding: [0xc7,0xfe,0x19,0x00] -+sra.d $r7, $r22, $r31 -+ -+# CHECK: rotr.w $ra, $r26, $r18 -+# CHECK: encoding: [0x41,0x4b,0x1b,0x00] -+rotr.w $ra, $r26, $r18 -+ -+# CHECK: rotr.d $r31, $sp, $ra -+# CHECK: encoding: [0x7f,0x84,0x1b,0x00] -+rotr.d $r31, $sp, $ra -+ -+# CHECK: mul.w $r4, $r18, $sp -+# CHECK: encoding: [0x44,0x0e,0x1c,0x00] -+mul.w $r4, $r18, $sp -+ -+# CHECK: mulh.w $r27, $r23, $zero -+# CHECK: encoding: [0xfb,0x82,0x1c,0x00] -+mulh.w $r27, $r23, $zero -+ -+# CHECK: mulh.wu $r10, $r17, $r24 -+# CHECK: encoding: [0x2a,0x62,0x1d,0x00] -+mulh.wu $r10, $r17, $r24 -+ -+# CHECK: mul.d $ra, $r14, $r24 -+# CHECK: encoding: [0xc1,0xe1,0x1d,0x00] -+mul.d $ra, $r14, $r24 -+ -+# CHECK: mulh.d $r28, $ra, $r27 -+# CHECK: encoding: [0x3c,0x6c,0x1e,0x00] -+mulh.d $r28, $ra, $r27 -+ -+# CHECK: mulh.du $r13, $r27, $r29 -+# CHECK: encoding: [0x6d,0xf7,0x1e,0x00] -+mulh.du $r13, $r27, $r29 -+ -+# CHECK: mulw.d.w $r27, $r6, $r17 -+# CHECK: encoding: [0xdb,0x44,0x1f,0x00] -+mulw.d.w $r27, $r6, $r17 -+ -+# CHECK: mulw.d.wu $r17, $r22, $r30 -+# CHECK: encoding: [0xd1,0xfa,0x1f,0x00] -+mulw.d.wu $r17, $r22, $r30 -+ -+# CHECK: div.w $r30, $r13, $r25 -+# CHECK: encoding: [0xbe,0x65,0x20,0x00] -+div.w $r30, $r13, $r25 -+ -+# CHECK: mod.w $ra, $r26, $r10 -+# CHECK: encoding: [0x41,0xab,0x20,0x00] -+mod.w $ra, $r26, $r10 -+ -+# CHECK: div.wu $r19, $r23, $zero -+# CHECK: encoding: [0xf3,0x02,0x21,0x00] -+div.wu $r19, $r23, $zero -+ -+# CHECK: mod.wu $r27, $r9, $r17 -+# CHECK: encoding: [0x3b,0xc5,0x21,0x00] -+mod.wu $r27, $r9, $r17 -+ -+# CHECK: div.d $r23, $r6, $r21 -+# CHECK: encoding: [0xd7,0x54,0x22,0x00] -+div.d $r23, $r6, $r21 -+ -+# CHECK: mod.d $r16, $sp, $r15 -+# CHECK: encoding: [0x70,0xbc,0x22,0x00] -+mod.d $r16, $sp, $r15 -+ -+# CHECK: div.du $r31, $r24, $r14 -+# CHECK: encoding: [0x1f,0x3b,0x23,0x00] -+div.du $r31, $r24, $r14 -+ -+# CHECK: mod.du $r25, $r23, $r24 -+# CHECK: encoding: [0xf9,0xe2,0x23,0x00] -+mod.du $r25, $r23, $r24 -+ -+# CHECK: crc.w.b.w $r24, $r7, $tp -+# CHECK: encoding: [0xf8,0x08,0x24,0x00] -+crc.w.b.w $r24, $r7, $tp -+ -+# CHECK: crc.w.h.w $r31, $r10, $r18 -+# CHECK: encoding: [0x5f,0xc9,0x24,0x00] -+crc.w.h.w $r31, $r10, $r18 -+ -+# CHECK: crc.w.w.w $r28, $r6, $r10 -+# CHECK: encoding: [0xdc,0x28,0x25,0x00] -+crc.w.w.w $r28, $r6, $r10 -+ -+# CHECK: crc.w.d.w $r28, $r11, $r31 -+# CHECK: encoding: [0x7c,0xfd,0x25,0x00] -+crc.w.d.w $r28, $r11, $r31 -+ -+# CHECK: crcc.w.b.w $r15, $r18, $sp -+# CHECK: encoding: [0x4f,0x0e,0x26,0x00] -+crcc.w.b.w $r15, $r18, $sp -+ -+# CHECK: crcc.w.h.w $r21, $r29, $r18 -+# CHECK: encoding: [0xb5,0xcb,0x26,0x00] -+crcc.w.h.w $r21, $r29, $r18 -+ -+# CHECK: crcc.w.w.w $r17, $r14, $r13 -+# CHECK: encoding: [0xd1,0x35,0x27,0x00] -+crcc.w.w.w $r17, $r14, $r13 -+ -+# CHECK: crcc.w.d.w $r30, $r21, $r27 -+# CHECK: encoding: [0xbe,0xee,0x27,0x00] -+crcc.w.d.w $r30, $r21, $r27 -+ -+# CHECK: break 23 -+# CHECK: encoding: [0x17,0x00,0x2a,0x00] -+break 23 -+ -+# CHECK: syscall 2 -+# CHECK: encoding: [0x02,0x00,0x2b,0x00] -+syscall 2 -+ -+# CHECK: alsl.d $r17, $r11, $r5, 3 -+# CHECK: encoding: [0x71,0x15,0x2d,0x00] -+alsl.d $r17, $r11, $r5, 3 -+ -+# CHECK: slli.w $r26, $r18, 0 -+# CHECK: encoding: [0x5a,0x82,0x40,0x00] -+slli.w $r26, $r18, 0 -+ -+# CHECK: slli.d $r10, $r31, 39 -+# CHECK: encoding: [0xea,0x9f,0x41,0x00] -+slli.d $r10, $r31, 39 -+ -+# CHECK: srli.w $r10, $r14, 30 -+# CHECK: encoding: [0xca,0xf9,0x44,0x00] -+srli.w $r10, $r14, 30 -+ -+# CHECK: srli.d $r31, $r22, 38 -+# CHECK: encoding: [0xdf,0x9a,0x45,0x00] -+srli.d $r31, $r22, 38 -+ -+# CHECK: srai.w $r8, $r17, 24 -+# CHECK: encoding: [0x28,0xe2,0x48,0x00] -+srai.w $r8, $r17, 24 -+ -+# CHECK: srai.d $r9, $r21, 27 -+# CHECK: encoding: [0xa9,0x6e,0x49,0x00] -+srai.d $r9, $r21, 27 -+ -+# CHECK: rotri.w $r23, $r20, 23 -+# CHECK: encoding: [0x97,0xde,0x4c,0x00] -+rotri.w $r23, $r20, 23 -+ -+# CHECK: rotri.d $r29, $zero, 7 -+# CHECK: encoding: [0x1d,0x1c,0x4d,0x00] -+rotri.d $r29, $zero, 7 -+ -+# CHECK: bstrins.w $r8, $r11, 7, 2 -+# CHECK: encoding: [0x68,0x09,0x67,0x00] -+bstrins.w $r8, $r11, 7, 2 -+ -+# CHECK: bstrins.d $r8, $r11, 7, 2 -+# CHECK: encoding: [0x68,0x09,0x87,0x00] -+bstrins.d $r8, $r11, 7, 2 -+ -+# CHECK: bstrpick.w $ra, $r9, 10, 4 -+# CHECK: encoding: [0x21,0x91,0x6a,0x00] -+bstrpick.w $ra, $r9, 10, 4 -+ -+# CHECK: bstrpick.d $r31, $r27, 39, 22 -+# CHECK: encoding: [0x7f,0x5b,0xe7,0x00] -+bstrpick.d $r31, $r27, 39, 22 -+ -+# CHECK: cpucfg $sp, $r8 -+# CHECK: encoding: [0x03,0x6d,0x00,0x00] -+cpucfg $sp, $r8 -+ -+# CHECK: alsl.wu $r19, $r8, $r25, 1 -+# CHECK: encoding: [0x13,0x65,0x06,0x00] -+alsl.wu $r19, $r8, $r25, 1 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s -new file mode 100644 -index 000000000..30ea88c99 ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s -@@ -0,0 +1,405 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: dbar 0 -+# CHECK: encoding: [0x00,0x00,0x72,0x38] -+dbar 0 -+ -+# CHECK: ibar 0 -+# CHECK: encoding: [0x00,0x80,0x72,0x38] -+ibar 0 -+ -+# CHECK: ll.w $tp, $r27, 220 -+# CHECK: encoding: [0x62,0xdf,0x00,0x20] -+ll.w $tp, $r27, 220 -+ -+# CHECK: sc.w $r19, $r14, 56 -+# CHECK: encoding: [0xd3,0x39,0x00,0x21] -+sc.w $r19, $r14, 56 -+ -+# CHECK: ll.d $r25, $r27, 16 -+# CHECK: encoding: [0x79,0x13,0x00,0x22] -+ll.d $r25, $r27, 16 -+ -+# CHECK: sc.d $r17, $r17, 244 -+# CHECK: encoding: [0x31,0xf6,0x00,0x23] -+sc.d $r17, $r17, 244 -+ -+# CHECK: ldptr.w $r26, $r6, 60 -+# CHECK: encoding: [0xda,0x3c,0x00,0x24] -+ldptr.w $r26, $r6, 60 -+ -+# CHECK: stptr.w $r28, $r5, 216 -+# CHECK: encoding: [0xbc,0xd8,0x00,0x25] -+stptr.w $r28, $r5, 216 -+ -+# CHECK: ldptr.d $r5, $r29, 244 -+# CHECK: encoding: [0xa5,0xf7,0x00,0x26] -+ldptr.d $r5, $r29, 244 -+ -+# CHECK: stptr.d $r14, $r24, 196 -+# CHECK: encoding: [0x0e,0xc7,0x00,0x27] -+stptr.d $r14, $r24, 196 -+ -+# CHECK: ld.b $r24, $r8, 21 -+# CHECK: encoding: [0x18,0x55,0x00,0x28] -+ld.b $r24, $r8, 21 -+ -+# CHECK: ld.h $r7, $r18, 80 -+# CHECK: encoding: [0x47,0x42,0x41,0x28] -+ld.h $r7, $r18, 80 -+ -+# CHECK: ld.w $r18, $r26, 92 -+# CHECK: encoding: [0x52,0x73,0x81,0x28] -+ld.w $r18, $r26, 92 -+ -+# CHECK: ld.d $r18, $r20, 159 -+# CHECK: encoding: [0x92,0x7e,0xc2,0x28] -+ld.d $r18, $r20, 159 -+ -+# CHECK: st.b $sp, $r7, 95 -+# CHECK: encoding: [0xe3,0x7c,0x01,0x29] -+st.b $sp, $r7, 95 -+ -+# CHECK: st.h $r25, $r16, 122 -+# CHECK: encoding: [0x19,0xea,0x41,0x29] -+st.h $r25, $r16, 122 -+ -+# CHECK: st.w $r13, $r13, 175 -+# CHECK: encoding: [0xad,0xbd,0x82,0x29] -+st.w $r13, $r13, 175 -+ -+# CHECK: st.d $r30, $r30, 60 -+# CHECK: encoding: [0xde,0xf3,0xc0,0x29] -+st.d $r30, $r30, 60 -+ -+# CHECK: ld.bu $r13, $r13, 150 -+# CHECK: encoding: [0xad,0x59,0x02,0x2a] -+ld.bu $r13, $r13, 150 -+ -+# CHECK: ld.hu $r18, $r29, 198 -+# CHECK: encoding: [0xb2,0x1b,0x43,0x2a] -+ld.hu $r18, $r29, 198 -+ -+# CHECK: ld.wu $r14, $r19, 31 -+# CHECK: encoding: [0x6e,0x7e,0x80,0x2a] -+ld.wu $r14, $r19, 31 -+ -+# CHECK: fld.s $f23, $r15, 250 -+# CHECK: encoding: [0xf7,0xe9,0x03,0x2b] -+fld.s $f23, $r15, 250 -+ -+# CHECK: fst.s $f30, $r19, 230 -+# CHECK: encoding: [0x7e,0x9a,0x43,0x2b] -+fst.s $f30, $r19, 230 -+ -+# CHECK: fld.d $f22, $r17, 114 -+# CHECK: encoding: [0x36,0xca,0x81,0x2b] -+fld.d $f22, $r17, 114 -+ -+# CHECK: fst.d $f28, $r7, 198 -+# CHECK: encoding: [0xfc,0x18,0xc3,0x2b] -+fst.d $f28, $r7, 198 -+ -+# CHECK: ldx.b $r24, $ra, $tp -+# CHECK: encoding: [0x38,0x08,0x00,0x38] -+ldx.b $r24, $ra, $tp -+ -+# CHECK: ldx.h $r22, $r22, $r17 -+# CHECK: encoding: [0xd6,0x46,0x04,0x38] -+ldx.h $r22, $r22, $r17 -+ -+# CHECK: ldx.w $r25, $r11, $r23 -+# CHECK: encoding: [0x79,0x5d,0x08,0x38] -+ldx.w $r25, $r11, $r23 -+ -+# CHECK: ldx.d $r18, $r23, $r20 -+# CHECK: encoding: [0xf2,0x52,0x0c,0x38] -+ldx.d $r18, $r23, $r20 -+ -+# CHECK: stx.b $r19, $ra, $sp -+# CHECK: encoding: [0x33,0x0c,0x10,0x38] -+stx.b $r19, $ra, $sp -+ -+# CHECK: stx.h $zero, $r28, $r26 -+# CHECK: encoding: [0x80,0x6b,0x14,0x38] -+stx.h $zero, $r28, $r26 -+ -+# CHECK: stx.w $r7, $r4, $r31 -+# CHECK: encoding: [0x87,0x7c,0x18,0x38] -+stx.w $r7, $r4, $r31 -+ -+# CHECK: stx.d $r7, $r31, $r10 -+# CHECK: encoding: [0xe7,0x2b,0x1c,0x38] -+stx.d $r7, $r31, $r10 -+ -+# CHECK: ldx.bu $r11, $r9, $r9 -+# CHECK: encoding: [0x2b,0x25,0x20,0x38] -+ldx.bu $r11, $r9, $r9 -+ -+# CHECK: ldx.hu $r22, $r23, $r27 -+# CHECK: encoding: [0xf6,0x6e,0x24,0x38] -+ldx.hu $r22, $r23, $r27 -+ -+# CHECK: ldx.wu $r8, $r24, $r28 -+# CHECK: encoding: [0x08,0x73,0x28,0x38] -+ldx.wu $r8, $r24, $r28 -+ -+# CHECK: fldx.s $f1, $r15, $r19 -+# CHECK: encoding: [0xe1,0x4d,0x30,0x38] -+fldx.s $f1, $r15, $r19 -+ -+# CHECK: fldx.d $f27, $r13, $r31 -+# CHECK: encoding: [0xbb,0x7d,0x34,0x38] -+fldx.d $f27, $r13, $r31 -+ -+# CHECK: fstx.s $f26, $sp, $r22 -+# CHECK: encoding: [0x7a,0x58,0x38,0x38] -+fstx.s $f26, $sp, $r22 -+ -+# CHECK: fstx.d $f6, $r15, $r17 -+# CHECK: encoding: [0xe6,0x45,0x3c,0x38] -+fstx.d $f6, $r15, $r17 -+ -+# CHECK: amswap_db.w $r6, $r12, $r24, 0 -+# CHECK: encoding: [0x06,0x33,0x69,0x38] -+amswap_db.w $r6, $r12, $r24, 0 -+ -+# CHECK: amswap_db.d $tp, $r14, $r22, 0 -+# CHECK: encoding: [0xc2,0xba,0x69,0x38] -+amswap_db.d $tp, $r14, $r22, 0 -+ -+# CHECK: amadd_db.w $r8, $r12, $r21, 0 -+# CHECK: encoding: [0xa8,0x32,0x6a,0x38] -+amadd_db.w $r8, $r12, $r21, 0 -+ -+# CHECK: amadd_db.d $r5, $r17, $r29, 0 -+# CHECK: encoding: [0xa5,0xc7,0x6a,0x38] -+amadd_db.d $r5, $r17, $r29, 0 -+ -+# CHECK: amand_db.w $r4, $r19, $r22, 0 -+# CHECK: encoding: [0xc4,0x4e,0x6b,0x38] -+amand_db.w $r4, $r19, $r22, 0 -+ -+# CHECK: amand_db.d $r10, $r18, $r29, 0 -+# CHECK: encoding: [0xaa,0xcb,0x6b,0x38] -+amand_db.d $r10, $r18, $r29, 0 -+ -+# CHECK: amor_db.w $r6, $r16, $r23, 0 -+# CHECK: encoding: [0xe6,0x42,0x6c,0x38] -+amor_db.w $r6, $r16, $r23, 0 -+ -+# CHECK: amor_db.d $sp, $r16, $r24, 0 -+# CHECK: encoding: [0x03,0xc3,0x6c,0x38] -+amor_db.d $sp, $r16, $r24, 0 -+ -+# CHECK: amxor_db.w $tp, $r15, $r23, 0 -+# CHECK: encoding: [0xe2,0x3e,0x6d,0x38] -+amxor_db.w $tp, $r15, $r23, 0 -+ -+# CHECK: amxor_db.d $r8, $r20, $r28, 0 -+# CHECK: encoding: [0x88,0xd3,0x6d,0x38] -+amxor_db.d $r8, $r20, $r28, 0 -+ -+# CHECK: ammax_db.w $ra, $r11, $r23, 0 -+# CHECK: encoding: [0xe1,0x2e,0x6e,0x38] -+ammax_db.w $ra, $r11, $r23, 0 -+ -+# CHECK: ammax_db.d $r9, $r20, $r27, 0 -+# CHECK: encoding: [0x69,0xd3,0x6e,0x38] -+ammax_db.d $r9, $r20, $r27, 0 -+ -+# CHECK: ammin_db.w $r9, $r14, $r23, 0 -+# CHECK: encoding: [0xe9,0x3a,0x6f,0x38] -+ammin_db.w $r9, $r14, $r23, 0 -+ -+# CHECK: ammin_db.d $r9, $r13, $r22, 0 -+# CHECK: encoding: [0xc9,0xb6,0x6f,0x38] -+ammin_db.d $r9, $r13, $r22, 0 -+ -+# CHECK: ammax_db.wu $r9, $r11, $r22, 0 -+# CHECK: encoding: [0xc9,0x2e,0x70,0x38] -+ammax_db.wu $r9, $r11, $r22, 0 -+ -+# CHECK: ammax_db.du $r6, $r16, $r25, 0 -+# CHECK: encoding: [0x26,0xc3,0x70,0x38] -+ammax_db.du $r6, $r16, $r25, 0 -+ -+# CHECK: ammin_db.wu $r8, $r18, $r30, 0 -+# CHECK: encoding: [0xc8,0x4b,0x71,0x38] -+ammin_db.wu $r8, $r18, $r30, 0 -+ -+# CHECK: ammin_db.du $r7, $r16, $r25, 0 -+# CHECK: encoding: [0x27,0xc3,0x71,0x38] -+ammin_db.du $r7, $r16, $r25, 0 -+ -+# CHECK: amswap.w $r6, $r12, $r24, 0 -+# CHECK: encoding: [0x06,0x33,0x60,0x38] -+amswap.w $r6, $r12, $r24, 0 -+ -+# CHECK: amswap.d $tp, $r14, $r22, 0 -+# CHECK: encoding: [0xc2,0xba,0x60,0x38] -+amswap.d $tp, $r14, $r22, 0 -+ -+# CHECK: amadd.w $r8, $r12, $r21, 0 -+# CHECK: encoding: [0xa8,0x32,0x61,0x38] -+amadd.w $r8, $r12, $r21, 0 -+ -+# CHECK: amadd.d $r5, $r17, $r29, 0 -+# CHECK: encoding: [0xa5,0xc7,0x61,0x38] -+amadd.d $r5, $r17, $r29, 0 -+ -+# CHECK: amand.w $r4, $r19, $r22, 0 -+# CHECK: encoding: [0xc4,0x4e,0x62,0x38] -+amand.w $r4, $r19, $r22, 0 -+ -+# CHECK: amand.d $r10, $r18, $r29, 0 -+# CHECK: encoding: [0xaa,0xcb,0x62,0x38] -+amand.d $r10, $r18, $r29, 0 -+ -+# CHECK: amor.w $r6, $r16, $r23, 0 -+# CHECK: encoding: [0xe6,0x42,0x63,0x38] -+amor.w $r6, $r16, $r23, 0 -+ -+# CHECK: amor.d $sp, $r16, $r24, 0 -+# CHECK: encoding: [0x03,0xc3,0x63,0x38] -+amor.d $sp, $r16, $r24, 0 -+ -+# CHECK: amxor.w $tp, $r15, $r23, 0 -+# CHECK: encoding: [0xe2,0x3e,0x64,0x38] -+amxor.w $tp, $r15, $r23, 0 -+ -+# CHECK: amxor.d $r8, $r20, $r28, 0 -+# CHECK: encoding: [0x88,0xd3,0x64,0x38] -+amxor.d $r8, $r20, $r28, 0 -+ -+# CHECK: ammax.w $ra, $r11, $r23, 0 -+# CHECK: encoding: [0xe1,0x2e,0x65,0x38] -+ammax.w $ra, $r11, $r23, 0 -+ -+# CHECK: ammax.d $r9, $r20, $r27, 0 -+# CHECK: encoding: [0x69,0xd3,0x65,0x38] -+ammax.d $r9, $r20, $r27, 0 -+ -+# CHECK: ammin.w $r9, $r14, $r23, 0 -+# CHECK: encoding: [0xe9,0x3a,0x66,0x38] -+ammin.w $r9, $r14, $r23, 0 -+ -+# CHECK: ammin.d $r9, $r13, $r22, 0 -+# CHECK: encoding: [0xc9,0xb6,0x66,0x38] -+ammin.d $r9, $r13, $r22, 0 -+ -+# CHECK: ammax.wu $r9, $r11, $r22, 0 -+# CHECK: encoding: [0xc9,0x2e,0x67,0x38] -+ammax.wu $r9, $r11, $r22, 0 -+ -+# CHECK: ammax.du $r6, $r16, $r25, 0 -+# CHECK: encoding: [0x26,0xc3,0x67,0x38] -+ammax.du $r6, $r16, $r25, 0 -+ -+# CHECK: ammin.wu $r8, $r18, $r30, 0 -+# CHECK: encoding: [0xc8,0x4b,0x68,0x38] -+ammin.wu $r8, $r18, $r30, 0 -+ -+# CHECK: ammin.du $r7, $r16, $r25, 0 -+# CHECK: encoding: [0x27,0xc3,0x68,0x38] -+ammin.du $r7, $r16, $r25, 0 -+ -+# CHECK: fldgt.s $f3, $r27, $r13 -+# CHECK: encoding: [0x63,0x37,0x74,0x38] -+fldgt.s $f3, $r27, $r13 -+ -+# CHECK: fldgt.d $f26, $r5, $r31 -+# CHECK: encoding: [0xba,0xfc,0x74,0x38] -+fldgt.d $f26, $r5, $r31 -+ -+# CHECK: fldle.s $f24, $r29, $r17 -+# CHECK: encoding: [0xb8,0x47,0x75,0x38] -+fldle.s $f24, $r29, $r17 -+ -+# CHECK: fldle.d $f3, $r15, $r22 -+# CHECK: encoding: [0xe3,0xd9,0x75,0x38] -+fldle.d $f3, $r15, $r22 -+ -+# CHECK: fstgt.s $f31, $r13, $r30 -+# CHECK: encoding: [0xbf,0x79,0x76,0x38] -+fstgt.s $f31, $r13, $r30 -+ -+# CHECK: fstgt.d $f13, $r11, $r26 -+# CHECK: encoding: [0x6d,0xe9,0x76,0x38] -+fstgt.d $f13, $r11, $r26 -+ -+# CHECK: fstle.s $f13, $r13, $r7 -+# CHECK: encoding: [0xad,0x1d,0x77,0x38] -+fstle.s $f13, $r13, $r7 -+ -+# CHECK: fstle.d $f18, $r9, $r13 -+# CHECK: encoding: [0x32,0xb5,0x77,0x38] -+fstle.d $f18, $r9, $r13 -+ -+# CHECK: preld 10, $zero, 23 -+# CHECK: encoding: [0x0a,0x5c,0xc0,0x2a] -+preld 10, $zero, 23 -+ -+# CHECK: ldgt.b $r6, $r6, $r29 -+# CHECK: encoding: [0xc6,0x74,0x78,0x38] -+ldgt.b $r6, $r6, $r29 -+ -+# CHECK: ldgt.h $r5, $r31, $ra -+# CHECK: encoding: [0xe5,0x87,0x78,0x38] -+ldgt.h $r5, $r31, $ra -+ -+# CHECK: ldgt.w $r15, $r26, $r8 -+# CHECK: encoding: [0x4f,0x23,0x79,0x38] -+ldgt.w $r15, $r26, $r8 -+ -+# CHECK: ldgt.d $r23, $r25, $r31 -+# CHECK: encoding: [0x37,0xff,0x79,0x38] -+ldgt.d $r23, $r25, $r31 -+ -+# CHECK: ldle.b $r9, $r12, $r15 -+# CHECK: encoding: [0x89,0x3d,0x7a,0x38] -+ldle.b $r9, $r12, $r15 -+ -+# CHECK: ldle.h $r11, $r11, $r23 -+# CHECK: encoding: [0x6b,0xdd,0x7a,0x38] -+ldle.h $r11, $r11, $r23 -+ -+# CHECK: ldle.w $r24, $tp, $tp -+# CHECK: encoding: [0x58,0x08,0x7b,0x38] -+ldle.w $r24, $tp, $tp -+ -+# CHECK: ldle.d $r20, $r15, $r16 -+# CHECK: encoding: [0xf4,0xc1,0x7b,0x38] -+ldle.d $r20, $r15, $r16 -+ -+# CHECK: stgt.b $r27, $r19, $r20 -+# CHECK: encoding: [0x7b,0x52,0x7c,0x38] -+stgt.b $r27, $r19, $r20 -+ -+# CHECK: stgt.h $r16, $r4, $r6 -+# CHECK: encoding: [0x90,0x98,0x7c,0x38] -+stgt.h $r16, $r4, $r6 -+ -+# CHECK: stgt.w $r31, $r28, $r14 -+# CHECK: encoding: [0x9f,0x3b,0x7d,0x38] -+stgt.w $r31, $r28, $r14 -+ -+# CHECK: stgt.d $r30, $r21, $r24 -+# CHECK: encoding: [0xbe,0xe2,0x7d,0x38] -+stgt.d $r30, $r21, $r24 -+ -+# CHECK: stle.b $r10, $r4, $r16 -+# CHECK: encoding: [0x8a,0x40,0x7e,0x38] -+stle.b $r10, $r4, $r16 -+ -+# CHECK: stle.h $r17, $r17, $r21 -+# CHECK: encoding: [0x31,0xd6,0x7e,0x38] -+stle.h $r17, $r17, $r21 -+ -+# CHECK: stle.w $r23, $r28, $r29 -+# CHECK: encoding: [0x97,0x77,0x7f,0x38] -+stle.w $r23, $r28, $r29 -+ -+# CHECK: stle.d $r25, $r24, $r29 -+# CHECK: encoding: [0x19,0xf7,0x7f,0x38] -+stle.d $r25, $r24, $r29 -+ -diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s -new file mode 100644 -index 000000000..57a252a8d ---- /dev/null -+++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s -@@ -0,0 +1,125 @@ -+# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s -+# CHECK: csrrd $r26, 30 -+# CHECK: encoding: [0x1a,0x78,0x00,0x04] -+csrrd $r26, 30 -+ -+# CHECK: csrwr $r24, 194 -+# CHECK: encoding: [0x38,0x08,0x03,0x04] -+csrwr $r24, 194 -+ -+# CHECK: csrxchg $r6, $r27, 214 -+# CHECK: encoding: [0x66,0x5b,0x03,0x04] -+csrxchg $r6, $r27, 214 -+ -+# CHECK: cacop 0, $r10, 27 -+# CHECK: encoding: [0x40,0x6d,0x00,0x06] -+cacop 0, $r10, 27 -+ -+# CHECK: lddir $r12, $r30, 92 -+# CHECK: encoding: [0xcc,0x73,0x41,0x06] -+lddir $r12, $r30, 92 -+ -+# CHECK: ldpte $r18, 200 -+# CHECK: encoding: [0x40,0x22,0x47,0x06] -+ldpte $r18, 200 -+ -+# CHECK: iocsrrd.b $r26, $r24 -+# CHECK: encoding: [0x1a,0x03,0x48,0x06] -+iocsrrd.b $r26, $r24 -+ -+# CHECK: iocsrrd.h $r5, $r27 -+# CHECK: encoding: [0x65,0x07,0x48,0x06] -+iocsrrd.h $r5, $r27 -+ -+# CHECK: iocsrrd.w $r10, $r20 -+# CHECK: encoding: [0x8a,0x0a,0x48,0x06] -+iocsrrd.w $r10, $r20 -+ -+# CHECK: iocsrrd.d $r17, $r25 -+# CHECK: encoding: [0x31,0x0f,0x48,0x06] -+iocsrrd.d $r17, $r25 -+ -+# CHECK: iocsrwr.b $r4, $r23 -+# CHECK: encoding: [0xe4,0x12,0x48,0x06] -+iocsrwr.b $r4, $r23 -+ -+# CHECK: iocsrwr.h $r11, $zero -+# CHECK: encoding: [0x0b,0x14,0x48,0x06] -+iocsrwr.h $r11, $zero -+ -+# CHECK: iocsrwr.w $r20, $r26 -+# CHECK: encoding: [0x54,0x1b,0x48,0x06] -+iocsrwr.w $r20, $r26 -+ -+# CHECK: iocsrwr.d $r20, $r7 -+# CHECK: encoding: [0xf4,0x1c,0x48,0x06] -+iocsrwr.d $r20, $r7 -+ -+# CHECK: tlbclr -+# CHECK: encoding: [0x00,0x20,0x48,0x06] -+tlbclr -+ -+# CHECK: tlbflush -+# CHECK: encoding: [0x00,0x24,0x48,0x06] -+tlbflush -+ -+# CHECK: tlbsrch -+# CHECK: encoding: [0x00,0x28,0x48,0x06] -+tlbsrch -+ -+# CHECK: tlbrd -+# CHECK: encoding: [0x00,0x2c,0x48,0x06] -+tlbrd -+ -+# CHECK: tlbwr -+# CHECK: encoding: [0x00,0x30,0x48,0x06] -+tlbwr -+ -+# CHECK: tlbfill -+# CHECK: encoding: [0x00,0x34,0x48,0x06] -+tlbfill -+ -+# CHECK: ertn -+# CHECK: encoding: [0x00,0x38,0x48,0x06] -+ertn -+ -+# CHECK: idle 204 -+# CHECK: encoding: [0xcc,0x80,0x48,0x06] -+idle 204 -+ -+# CHECK: invtlb 16, $r29, $r25 -+# CHECK: encoding: [0xb0,0xe7,0x49,0x06] -+invtlb 16, $r29, $r25 -+ -+# CHECK: rdtimel.w $r30, $r19 -+# CHECK: encoding: [0x7e,0x62,0x00,0x00] -+rdtimel.w $r30, $r19 -+ -+# CHECK: rdtimeh.w $r19, $r14 -+# CHECK: encoding: [0xd3,0x65,0x00,0x00] -+rdtimeh.w $r19, $r14 -+ -+# CHECK: rdtime.d $tp, $r15 -+# CHECK: encoding: [0xe2,0x69,0x00,0x00] -+rdtime.d $tp, $r15 -+ -+# CHECK: asrtle.d $r12, $r17 -+# CHECK: encoding: [0x80,0x45,0x01,0x00] -+asrtle.d $r12, $r17 -+ -+# CHECK: asrtgt.d $r20, $r20 -+# CHECK: encoding: [0x80,0xd2,0x01,0x00] -+asrtgt.d $r20, $r20 -+ -+# CHECK: break 199 -+# CHECK: encoding: [0xc7,0x00,0x2a,0x00] -+break 199 -+ -+# CHECK: dbcl 201 -+# CHECK: encoding: [0xc9,0x80,0x2a,0x00] -+dbcl 201 -+ -+# CHECK: syscall 100 -+# CHECK: encoding: [0x64,0x00,0x2b,0x00] -+syscall 100 -+ -diff --git a/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test b/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test -deleted file mode 100644 -index 01680841d..000000000 ---- a/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test -+++ /dev/null -@@ -1,26 +0,0 @@ --## Test that when writing to a closed stdout, LLVM tools finish with a non-zero --## exit code and an error message on stderr. The test uses llvm-cxxfilt, but --## it's a logic from the default SIGPIPE handler, so it applies to all the tools. --## This is required for UNIX03 conformance. -- --# UNSUPPORTED: system-windows -- --# RUN: not %python %s llvm-cxxfilt 2>&1 | FileCheck %s --# CHECK: error: write on a pipe with no reader -- --import subprocess --import sys -- --with subprocess.Popen([sys.argv[1]], stdout=subprocess.PIPE, stdin=subprocess.PIPE) as process: -- process.stdout.close() -- -- # llvm-cxxfilt with no extra arguments runs interactively and writes input -- # to output. Writing continuously to stdin should trigger SIGPIPE when the -- # subprocess attempts to write out bytes to a closed stdout. -- try: -- while True: -- process.stdin.write("foo\n".encode("utf-8")) -- except BrokenPipeError: -- # Clear stdin, pipe is broken and closing it on cleanup will raise an exception. -- process.stdin = None --sys.exit(process.returncode) -diff --git a/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg -deleted file mode 100644 -index 31902e060..000000000 ---- a/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg -+++ /dev/null -@@ -1,5 +0,0 @@ --config.suffixes = ['.ll'] -- --targets = set(config.root.targets_to_build.split()) --if not 'LoongArch' in targets: -- config.unsupported = True -diff --git a/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll b/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll -new file mode 100644 -index 000000000..188210782 ---- /dev/null -+++ b/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll -@@ -0,0 +1,38 @@ -+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature -+; RUN: opt -passes=globalopt -S < %s | FileCheck %s -+ -+define i32 @main(ptr %a) { -+; CHECK-LABEL: define {{[^@]+}}@main -+; CHECK-SAME: (ptr [[A:%.*]]) local_unnamed_addr { -+; CHECK-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ ptr, i32 }>, align 4 -+; CHECK-NEXT: store ptr [[A]], ptr [[ARGMEM]], align 8 -+; CHECK-NEXT: [[G0:%.*]] = getelementptr inbounds <{ ptr, i32 }>, ptr [[ARGMEM]], i32 0, i32 1 -+; CHECK-NEXT: store i32 5, ptr [[G0]], align 4 -+; CHECK-NEXT: [[CALL3:%.*]] = call i32 (ptr, ...) @i(ptr inalloca(ptr) [[ARGMEM]]) -+; CHECK-NEXT: ret i32 [[CALL3]] -+; -+ %argmem = alloca inalloca <{ ptr, i32 }>, align 4 -+ store ptr %a, ptr %argmem, align 8 -+ %g0 = getelementptr inbounds <{ ptr, i32 }>, ptr %argmem, i32 0, i32 1 -+ store i32 5, ptr %g0, align 4 -+ %call3 = call i32 (ptr, ...) @i(ptr inalloca(ptr) %argmem) -+ ret i32 %call3 -+} -+ -+define internal i32 @i(ptr inalloca(ptr) %a, ...) { -+; CHECK-LABEL: define {{[^@]+}}@i -+; CHECK-SAME: (ptr inalloca(ptr) [[A:%.*]], ...) unnamed_addr { -+; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4 -+; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) -+; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[AP]], align 4 -+; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 -+; CHECK-NEXT: ret i32 [[L]] -+; -+ %ap = alloca ptr, align 4 -+ call void @llvm.va_start(ptr %ap) -+ %argp.cur = load ptr, ptr %ap, align 4 -+ %l = load i32, ptr %argp.cur, align 4 -+ ret i32 %l -+} -+ -+declare void @llvm.va_start(ptr) -diff --git a/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll b/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll -new file mode 100644 -index 000000000..b3e305583 ---- /dev/null -+++ b/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll -@@ -0,0 +1,31 @@ -+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -+; Check that function calls involving conversion from/to byval aren't transformed. -+; RUN: opt < %s -passes=instcombine -S | FileCheck %s -+ -+%Foo = type { i64 } -+define i64 @foo (ptr byval(%Foo) %foo) { -+; CHECK-LABEL: @foo( -+; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[FOO:%.*]], align 4 -+; CHECK-NEXT: ret i64 [[TMP1]] -+; -+ %1 = load i64, ptr %foo, align 4 -+ ret i64 %1 -+} -+ -+define i64 @bar(i64 %0) { -+; CHECK-LABEL: @bar( -+; CHECK-NEXT: [[TMP2:%.*]] = tail call i64 @foo(i64 [[TMP0:%.*]]) -+; CHECK-NEXT: ret i64 [[TMP2]] -+; -+ %2 = tail call i64 @foo(i64 %0) -+ ret i64 %2 -+} -+ -+define i64 @qux(ptr byval(%Foo) %qux) { -+; CHECK-LABEL: @qux( -+; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @bar(ptr nonnull byval([[FOO:%.*]]) [[QUX:%.*]]) -+; CHECK-NEXT: ret i64 [[TMP1]] -+; -+ %1 = tail call i64 @bar(ptr byval(%Foo) %qux) -+ ret i64 %1 -+} -diff --git a/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll b/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll -new file mode 100644 -index 000000000..4b0bc908e ---- /dev/null -+++ b/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll -@@ -0,0 +1,125 @@ -+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -+; RUN: opt -force-vector-width=4 -force-vector-interleave=1 -passes='loop-vectorize,loop-load-elim' -S %s | FileCheck %s -+ -+@glob.1 = external global [100 x double] -+@glob.2 = external global [100 x double] -+ -+define void @g(ptr %dst.1, ptr %start, i64 %N) { -+; CHECK-LABEL: @g( -+; CHECK-NEXT: loop.1.lver.check: -+; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[N:%.*]], 3 -+; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 16 -+; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr @glob.2, i64 [[TMP1]] -+; CHECK-NEXT: [[UGLYGEP2:%.*]] = getelementptr i8, ptr [[DST_1:%.*]], i64 8 -+; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr @glob.2, [[UGLYGEP2]] -+; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[DST_1]], [[UGLYGEP]] -+; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] -+; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[LOOP_1_PH_LVER_ORIG:%.*]], label [[LOOP_1_PH:%.*]] -+; CHECK: loop.1.ph.lver.orig: -+; CHECK-NEXT: br label [[LOOP_1_LVER_ORIG:%.*]] -+; CHECK: loop.1.lver.orig: -+; CHECK-NEXT: [[IV_LVER_ORIG:%.*]] = phi i64 [ 0, [[LOOP_1_PH_LVER_ORIG]] ], [ [[IV_NEXT_LVER_ORIG:%.*]], [[LOOP_1_LVER_ORIG]] ] -+; CHECK-NEXT: [[PTR_IV_1_LVER_ORIG:%.*]] = phi ptr [ @glob.1, [[LOOP_1_PH_LVER_ORIG]] ], [ [[PTR_IV_1_NEXT_LVER_ORIG:%.*]], [[LOOP_1_LVER_ORIG]] ] -+; CHECK-NEXT: [[GEP_IV_LVER_ORIG:%.*]] = getelementptr inbounds double, ptr @glob.2, i64 [[IV_LVER_ORIG]] -+; CHECK-NEXT: [[L_1_LVER_ORIG:%.*]] = load double, ptr [[GEP_IV_LVER_ORIG]], align 8 -+; CHECK-NEXT: [[GEP_IV_1_LVER_ORIG:%.*]] = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 [[IV_LVER_ORIG]] -+; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_IV_1_LVER_ORIG]], align 8 -+; CHECK-NEXT: store double 0.000000e+00, ptr [[DST_1]], align 8 -+; CHECK-NEXT: [[PTR_IV_1_NEXT_LVER_ORIG]] = getelementptr inbounds double, ptr [[PTR_IV_1_LVER_ORIG]], i64 1 -+; CHECK-NEXT: [[IV_NEXT_LVER_ORIG]] = add nuw nsw i64 [[IV_LVER_ORIG]], 1 -+; CHECK-NEXT: [[EXITCOND_NOT_LVER_ORIG:%.*]] = icmp eq i64 [[IV_LVER_ORIG]], [[N]] -+; CHECK-NEXT: br i1 [[EXITCOND_NOT_LVER_ORIG]], label [[LOOP_2_PH_LOOPEXIT:%.*]], label [[LOOP_1_LVER_ORIG]] -+; CHECK: loop.1.ph: -+; CHECK-NEXT: [[LOAD_INITIAL:%.*]] = load double, ptr @glob.2, align 8 -+; CHECK-NEXT: br label [[LOOP_1:%.*]] -+; CHECK: loop.1: -+; CHECK-NEXT: [[STORE_FORWARDED:%.*]] = phi double [ [[LOAD_INITIAL]], [[LOOP_1_PH]] ], [ 0.000000e+00, [[LOOP_1]] ] -+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[LOOP_1_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_1]] ] -+; CHECK-NEXT: [[PTR_IV_1:%.*]] = phi ptr [ @glob.1, [[LOOP_1_PH]] ], [ [[PTR_IV_1_NEXT:%.*]], [[LOOP_1]] ] -+; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds double, ptr @glob.2, i64 [[IV]] -+; CHECK-NEXT: [[L_1:%.*]] = load double, ptr [[GEP_IV]], align 8 -+; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 [[IV]] -+; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_IV_1]], align 8 -+; CHECK-NEXT: store double 0.000000e+00, ptr [[DST_1]], align 8 -+; CHECK-NEXT: [[PTR_IV_1_NEXT]] = getelementptr inbounds double, ptr [[PTR_IV_1]], i64 1 -+; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 -+; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[N]] -+; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[LOOP_2_PH_LOOPEXIT3:%.*]], label [[LOOP_1]] -+; CHECK: loop.2.ph.loopexit: -+; CHECK-NEXT: [[LCSSA_PTR_IV_1_PH:%.*]] = phi ptr [ [[PTR_IV_1_LVER_ORIG]], [[LOOP_1_LVER_ORIG]] ] -+; CHECK-NEXT: br label [[LOOP_2_PH:%.*]] -+; CHECK: loop.2.ph.loopexit3: -+; CHECK-NEXT: [[LCSSA_PTR_IV_1_PH4:%.*]] = phi ptr [ [[PTR_IV_1]], [[LOOP_1]] ] -+; CHECK-NEXT: br label [[LOOP_2_PH]] -+; CHECK: loop.2.ph: -+; CHECK-NEXT: [[LCSSA_PTR_IV_1:%.*]] = phi ptr [ [[LCSSA_PTR_IV_1_PH]], [[LOOP_2_PH_LOOPEXIT]] ], [ [[LCSSA_PTR_IV_1_PH4]], [[LOOP_2_PH_LOOPEXIT3]] ] -+; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 -+; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] -+; CHECK: vector.ph: -+; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 -+; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] -+; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[N_VEC]], 8 -+; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[LCSSA_PTR_IV_1]], i64 [[TMP2]] -+; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] -+; CHECK: vector.body: -+; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -+; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0 -+; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[TMP3]], 8 -+; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[LCSSA_PTR_IV_1]], i64 [[TMP4]] -+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr double, ptr [[NEXT_GEP]], i32 0 -+; CHECK-NEXT: store <4 x double> zeroinitializer, ptr [[TMP5]], align 8 -+; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -+; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -+; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] -+; CHECK: middle.block: -+; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] -+; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] -+; CHECK: scalar.ph: -+; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_2_PH]] ] -+; CHECK-NEXT: [[BC_RESUME_VAL1:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[LCSSA_PTR_IV_1]], [[LOOP_2_PH]] ] -+; CHECK-NEXT: br label [[LOOP_2:%.*]] -+; CHECK: loop.2: -+; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_2_NEXT:%.*]], [[LOOP_2]] ] -+; CHECK-NEXT: [[PTR_IV_2:%.*]] = phi ptr [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[PTR_IV_2_NEXT:%.*]], [[LOOP_2]] ] -+; CHECK-NEXT: store double 0.000000e+00, ptr [[PTR_IV_2]], align 8 -+; CHECK-NEXT: [[PTR_IV_2_NEXT]] = getelementptr inbounds double, ptr [[PTR_IV_2]], i64 1 -+; CHECK-NEXT: [[IV_2_NEXT]] = add nuw nsw i64 [[IV_2]], 1 -+; CHECK-NEXT: [[EXITCOND_1_NOT:%.*]] = icmp eq i64 [[IV_2_NEXT]], [[N]] -+; CHECK-NEXT: br i1 [[EXITCOND_1_NOT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_2]], !llvm.loop [[LOOP2:![0-9]+]] -+; CHECK: exit.loopexit: -+; CHECK-NEXT: br label [[EXIT]] -+; CHECK: exit: -+; CHECK-NEXT: ret void -+; -+entry: -+ br label %loop.1 -+ -+loop.1: -+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.1 ] -+ %ptr.iv.1 = phi ptr [ @glob.1, %entry ], [ %ptr.iv.1.next, %loop.1 ] -+ %gep.iv = getelementptr inbounds double, ptr @glob.2, i64 %iv -+ %l.1 = load double, ptr %gep.iv, align 8 -+ %gep.iv.1 = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 %iv -+ store double 0.000000e+00, ptr %gep.iv.1, align 8 -+ store double 0.000000e+00, ptr %dst.1, align 8 -+ %ptr.iv.1.next = getelementptr inbounds double, ptr %ptr.iv.1, i64 1 -+ %iv.next = add nuw nsw i64 %iv, 1 -+ %exitcond.not = icmp eq i64 %iv, %N -+ br i1 %exitcond.not, label %loop.2.ph, label %loop.1 -+ -+loop.2.ph: -+ %lcssa.ptr.iv.1 = phi ptr [ %ptr.iv.1, %loop.1 ] -+ br label %loop.2 -+ -+loop.2: -+ %iv.2 = phi i64 [ 0, %loop.2.ph ] , [ %iv.2.next, %loop.2 ] -+ %ptr.iv.2 = phi ptr [ %lcssa.ptr.iv.1, %loop.2.ph ], [ %ptr.iv.2.next, %loop.2 ] -+ store double 0.000000e+00, ptr %ptr.iv.2, align 8 -+ %ptr.iv.2.next = getelementptr inbounds double, ptr %ptr.iv.2, i64 1 -+ %iv.2.next = add nuw nsw i64 %iv.2, 1 -+ %exitcond.1.not = icmp eq i64 %iv.2.next, %N -+ br i1 %exitcond.1.not, label %exit, label %loop.2 -+ -+exit: -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll b/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll -new file mode 100644 -index 000000000..32ca12ee7 ---- /dev/null -+++ b/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll -@@ -0,0 +1,141 @@ -+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -+; RUN: opt -passes=loop-vectorize -S %s | FileCheck %s -+ -+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -+target triple = "aarch64-unknown-linux-gnu" -+ -+; Make sure LV does not crash when analyzing potential interleave groups with -+; accesses where the typesize doesn't match to allocsize. -+define void @pr58722_load_interleave_group(ptr %src, ptr %dst) { -+; CHECK-LABEL: @pr58722_load_interleave_group( -+; CHECK-NEXT: entry: -+; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]] -+; CHECK: vector.memcheck: -+; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 40004 -+; CHECK-NEXT: [[UGLYGEP1:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 80007 -+; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[DST]], [[UGLYGEP1]] -+; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SRC]], [[UGLYGEP]] -+; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] -+; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] -+; CHECK: vector.ph: -+; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] -+; CHECK: vector.body: -+; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -+; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 1 -+; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 2 -+; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 3 -+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP0]] -+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP1]] -+; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP2]] -+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP3]] -+; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP4]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x i32> poison, i32 [[TMP8]], i32 0 -+; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP9]], i32 1 -+; CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP6]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP7]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> poison, i32 [[TMP12]], i32 0 -+; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x i32> [[TMP14]], i32 [[TMP13]], i32 1 -+; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 -+; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i64 1 -+; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 1 -+; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i64 1 -+; CHECK-NEXT: [[TMP20:%.*]] = load i24, ptr [[TMP16]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP21:%.*]] = load i24, ptr [[TMP17]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP22:%.*]] = insertelement <2 x i24> poison, i24 [[TMP20]], i32 0 -+; CHECK-NEXT: [[TMP23:%.*]] = insertelement <2 x i24> [[TMP22]], i24 [[TMP21]], i32 1 -+; CHECK-NEXT: [[TMP24:%.*]] = load i24, ptr [[TMP18]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP25:%.*]] = load i24, ptr [[TMP19]], align 4, !alias.scope !0 -+; CHECK-NEXT: [[TMP26:%.*]] = insertelement <2 x i24> poison, i24 [[TMP24]], i32 0 -+; CHECK-NEXT: [[TMP27:%.*]] = insertelement <2 x i24> [[TMP26]], i24 [[TMP25]], i32 1 -+; CHECK-NEXT: [[TMP28:%.*]] = zext <2 x i24> [[TMP23]] to <2 x i32> -+; CHECK-NEXT: [[TMP29:%.*]] = zext <2 x i24> [[TMP27]] to <2 x i32> -+; CHECK-NEXT: [[TMP30:%.*]] = add <2 x i32> [[TMP11]], [[TMP28]] -+; CHECK-NEXT: [[TMP31:%.*]] = add <2 x i32> [[TMP15]], [[TMP29]] -+; CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP0]] -+; CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP2]] -+; CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds i32, ptr [[TMP32]], i32 0 -+; CHECK-NEXT: store <2 x i32> [[TMP30]], ptr [[TMP34]], align 4, !alias.scope !3, !noalias !0 -+; CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds i32, ptr [[TMP32]], i32 2 -+; CHECK-NEXT: store <2 x i32> [[TMP31]], ptr [[TMP35]], align 4, !alias.scope !3, !noalias !0 -+; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -+; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10000 -+; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] -+; CHECK: middle.block: -+; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 10001, 10000 -+; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] -+; CHECK: scalar.ph: -+; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 10000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_MEMCHECK]] ] -+; CHECK-NEXT: br label [[LOOP:%.*]] -+; CHECK: loop: -+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -+; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV]] -+; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP_IV]], align 4 -+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[GEP_IV]], i64 1 -+; CHECK-NEXT: [[V2:%.*]] = load i24, ptr [[GEP]], align 4 -+; CHECK-NEXT: [[V2_EXT:%.*]] = zext i24 [[V2]] to i32 -+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[V1]], [[V2_EXT]] -+; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] -+; CHECK-NEXT: store i32 [[SUM]], ptr [[GEP_DST]], align 4 -+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 -+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV]], 10000 -+; CHECK-NEXT: br i1 [[CMP]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] -+; CHECK: exit: -+; CHECK-NEXT: ret void -+; -+entry: -+ br label %loop -+ -+loop: -+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] -+ %gep.iv = getelementptr inbounds i64, ptr %src, i64 %iv -+ %v1 = load i32, ptr %gep.iv, align 4 -+ %gep = getelementptr inbounds i32, ptr %gep.iv, i64 1 -+ %v2 = load i24, ptr %gep, align 4 -+ %v2.ext = zext i24 %v2 to i32 -+ %sum = add i32 %v1, %v2.ext -+ %gep.dst = getelementptr inbounds i32, ptr %dst, i64 %iv -+ store i32 %sum, ptr %gep.dst -+ %iv.next = add i64 %iv, 1 -+ %cmp = icmp eq i64 %iv, 10000 -+ br i1 %cmp, label %exit, label %loop -+ -+exit: -+ ret void -+} -+ -+define void @pr58722_store_interleave_group(ptr %src, ptr %dst) { -+; CHECK-LABEL: @pr58722_store_interleave_group( -+; CHECK-NEXT: entry: -+; CHECK-NEXT: br label [[LOOP:%.*]] -+; CHECK: loop: -+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -+; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i32 [[IV]] -+; CHECK-NEXT: store i32 [[IV]], ptr [[GEP_IV]], align 4 -+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[GEP_IV]], i64 1 -+; CHECK-NEXT: [[TRUNC_IV:%.*]] = trunc i32 [[IV]] to i24 -+; CHECK-NEXT: store i24 [[TRUNC_IV]], ptr [[GEP]], align 4 -+; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 2 -+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[IV]], 10000 -+; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] -+; CHECK: exit: -+; CHECK-NEXT: ret void -+; -+entry: -+ br label %loop -+ -+loop: -+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] -+ %gep.iv = getelementptr inbounds i64, ptr %src, i32 %iv -+ store i32 %iv, ptr %gep.iv -+ %gep = getelementptr inbounds i64, ptr %gep.iv, i64 1 -+ %trunc.iv = trunc i32 %iv to i24 -+ store i24 %trunc.iv, ptr %gep -+ %iv.next = add i32 %iv, 2 -+ %cmp = icmp eq i32 %iv, 10000 -+ br i1 %cmp, label %exit, label %loop -+ -+exit: -+ ret void -+} -diff --git a/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll b/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll -new file mode 100644 -index 000000000..7893da340 ---- /dev/null -+++ b/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll -@@ -0,0 +1,41 @@ -+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -+; RUN: opt -passes=sroa < %s -S | FileCheck %s -+ -+define void @f(i1 %i) { -+; CHECK-LABEL: @f( -+; CHECK-NEXT: [[A1:%.*]] = alloca i64, align 8 -+; CHECK-NEXT: [[A2:%.*]] = alloca i64, align 8 -+; CHECK-NEXT: br i1 [[I:%.*]], label [[BB1:%.*]], label [[BB:%.*]] -+; CHECK: bb: -+; CHECK-NEXT: br label [[BB2:%.*]] -+; CHECK: bb1: -+; CHECK-NEXT: br label [[BB2]] -+; CHECK: bb2: -+; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ [[A1]], [[BB1]] ], [ [[A2]], [[BB]] ] -+; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP3]], align 4 -+; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 -+; CHECK-NEXT: call void @use32(i32 [[TMP5]]) -+; CHECK-NEXT: call void @use64(i64 [[TMP4]]) -+; CHECK-NEXT: ret void -+; -+ %a1 = alloca i64 -+ %a2 = alloca i64 -+ br i1 %i, label %bb1, label %bb -+ -+bb: -+ br label %bb2 -+ -+bb1: -+ br label %bb2 -+ -+bb2: -+ %tmp3 = phi ptr [ %a1, %bb1 ], [ %a2, %bb ] -+ %tmp5 = load i32, ptr %tmp3 -+ %tmp4 = load i64, ptr %tmp3 -+ call void @use32(i32 %tmp5) -+ call void @use64(i64 %tmp4) -+ ret void -+} -+ -+declare void @use32(i32) -+declare void @use64(i64) -diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected -index 692941b50..306b22ebb 100644 ---- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected -+++ b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected -@@ -1,13 +1,13 @@ - ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py - ; Check that we accept functions with '$' in the name. - --; RUN: llc -mtriple=loongarch32-unknown-linux < %s | FileCheck %s -+; RUN: llc -mtriple=loongarch64-unknown-linux < %s | FileCheck %s - - define hidden i32 @"_Z54bar$ompvariant$bar"() { - ; CHECK-LABEL: _Z54bar$ompvariant$bar: - ; CHECK: # %bb.0: # %entry --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: jirl $zero, $ra, 0 -+; CHECK-NEXT: ori $r4, $zero, 2 -+; CHECK-NEXT: jr $ra - entry: - ret i32 2 - } -diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected -deleted file mode 100644 -index 5d091d735..000000000 ---- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected -+++ /dev/null -@@ -1,148 +0,0 @@ --; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --include-generated-funcs --; RUN: llc --enable-machine-outliner --mtriple=loongarch32-unknown-linux < %s | FileCheck %s --@x = dso_local global i32 0, align 4 -- --define dso_local i32 @check_boundaries() #0 { -- %1 = alloca i32, align 4 -- %2 = alloca i32, align 4 -- %3 = alloca i32, align 4 -- %4 = alloca i32, align 4 -- %5 = alloca i32, align 4 -- store i32 0, ptr %1, align 4 -- store i32 0, ptr %2, align 4 -- %6 = load i32, ptr %2, align 4 -- %7 = icmp ne i32 %6, 0 -- br i1 %7, label %9, label %8 -- -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- br label %10 -- -- store i32 1, ptr %4, align 4 -- br label %10 -- -- %11 = load i32, ptr %2, align 4 -- %12 = icmp ne i32 %11, 0 -- br i1 %12, label %14, label %13 -- -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- br label %15 -- -- store i32 1, ptr %4, align 4 -- br label %15 -- -- ret i32 0 --} -- --define dso_local i32 @main() #0 { -- %1 = alloca i32, align 4 -- %2 = alloca i32, align 4 -- %3 = alloca i32, align 4 -- %4 = alloca i32, align 4 -- %5 = alloca i32, align 4 -- -- store i32 0, ptr %1, align 4 -- store i32 0, ptr @x, align 4 -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- store i32 1, ptr @x, align 4 -- call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"() -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- ret i32 0 --} -- --attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } --; CHECK-LABEL: check_boundaries: --; CHECK: # %bb.0: --; CHECK-NEXT: addi.w $sp, $sp, -32 --; CHECK-NEXT: .cfi_def_cfa_offset 32 --; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill --; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill --; CHECK-NEXT: .cfi_offset 1, -4 --; CHECK-NEXT: .cfi_offset 22, -8 --; CHECK-NEXT: addi.w $fp, $sp, 32 --; CHECK-NEXT: .cfi_def_cfa 22, 0 --; CHECK-NEXT: st.w $zero, $fp, -16 --; CHECK-NEXT: st.w $zero, $fp, -12 --; CHECK-NEXT: bnez $zero, .LBB0_2 --; CHECK-NEXT: b .LBB0_1 --; CHECK-NEXT: .LBB0_2: --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: .LBB0_3: --; CHECK-NEXT: ld.w $a0, $fp, -16 --; CHECK-NEXT: bne $a0, $zero, .LBB0_5 --; CHECK-NEXT: b .LBB0_4 --; CHECK-NEXT: .LBB0_5: --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: .LBB0_6: --; CHECK-NEXT: move $a0, $zero --; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload --; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload --; CHECK-NEXT: addi.w $sp, $sp, 32 --; CHECK-NEXT: jirl $zero, $ra, 0 --; CHECK-NEXT: .LBB0_1: --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 3 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: ori $a0, $zero, 4 --; CHECK-NEXT: st.w $a0, $fp, -28 --; CHECK-NEXT: b .LBB0_3 --; CHECK-NEXT: .LBB0_4: --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 3 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: ori $a0, $zero, 4 --; CHECK-NEXT: st.w $a0, $fp, -28 --; CHECK-NEXT: b .LBB0_6 --; --; CHECK-LABEL: main: --; CHECK: # %bb.0: --; CHECK-NEXT: addi.w $sp, $sp, -32 --; CHECK-NEXT: .cfi_def_cfa_offset 32 --; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill --; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill --; CHECK-NEXT: .cfi_offset 1, -4 --; CHECK-NEXT: .cfi_offset 22, -8 --; CHECK-NEXT: addi.w $fp, $sp, 32 --; CHECK-NEXT: .cfi_def_cfa 22, 0 --; CHECK-NEXT: pcalau12i $a0, x --; CHECK-NEXT: addi.w $a0, $a0, x --; CHECK-NEXT: ori $a1, $zero, 1 --; CHECK-NEXT: st.w $a1, $a0, 0 --; CHECK-NEXT: st.w $zero, $fp, -12 --; CHECK-NEXT: st.w $a1, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a2, $zero, 3 --; CHECK-NEXT: st.w $a2, $fp, -24 --; CHECK-NEXT: ori $a3, $zero, 4 --; CHECK-NEXT: st.w $a3, $fp, -28 --; CHECK-NEXT: #APP --; CHECK-NEXT: #NO_APP --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: st.w $a1, $fp, -16 --; CHECK-NEXT: st.w $a2, $fp, -24 --; CHECK-NEXT: st.w $a3, $fp, -28 --; CHECK-NEXT: move $a0, $zero --; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload --; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload --; CHECK-NEXT: addi.w $sp, $sp, 32 --; CHECK-NEXT: jirl $zero, $ra, 0 -diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected -deleted file mode 100644 -index d4edfe5e0..000000000 ---- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected -+++ /dev/null -@@ -1,147 +0,0 @@ --; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py --; RUN: llc --enable-machine-outliner --mtriple=loongarch32-unknown-linux < %s | FileCheck %s --@x = dso_local global i32 0, align 4 -- --define dso_local i32 @check_boundaries() #0 { --; CHECK-LABEL: check_boundaries: --; CHECK: # %bb.0: --; CHECK-NEXT: addi.w $sp, $sp, -32 --; CHECK-NEXT: .cfi_def_cfa_offset 32 --; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill --; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill --; CHECK-NEXT: .cfi_offset 1, -4 --; CHECK-NEXT: .cfi_offset 22, -8 --; CHECK-NEXT: addi.w $fp, $sp, 32 --; CHECK-NEXT: .cfi_def_cfa 22, 0 --; CHECK-NEXT: st.w $zero, $fp, -16 --; CHECK-NEXT: st.w $zero, $fp, -12 --; CHECK-NEXT: bnez $zero, .LBB0_2 --; CHECK-NEXT: b .LBB0_1 --; CHECK-NEXT: .LBB0_2: --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: .LBB0_3: --; CHECK-NEXT: ld.w $a0, $fp, -16 --; CHECK-NEXT: bne $a0, $zero, .LBB0_5 --; CHECK-NEXT: b .LBB0_4 --; CHECK-NEXT: .LBB0_5: --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: .LBB0_6: --; CHECK-NEXT: move $a0, $zero --; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload --; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload --; CHECK-NEXT: addi.w $sp, $sp, 32 --; CHECK-NEXT: jirl $zero, $ra, 0 --; CHECK-NEXT: .LBB0_1: --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 3 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: ori $a0, $zero, 4 --; CHECK-NEXT: st.w $a0, $fp, -28 --; CHECK-NEXT: b .LBB0_3 --; CHECK-NEXT: .LBB0_4: --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a0, $zero, 1 --; CHECK-NEXT: st.w $a0, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 3 --; CHECK-NEXT: st.w $a0, $fp, -24 --; CHECK-NEXT: ori $a0, $zero, 4 --; CHECK-NEXT: st.w $a0, $fp, -28 --; CHECK-NEXT: b .LBB0_6 -- %1 = alloca i32, align 4 -- %2 = alloca i32, align 4 -- %3 = alloca i32, align 4 -- %4 = alloca i32, align 4 -- %5 = alloca i32, align 4 -- store i32 0, ptr %1, align 4 -- store i32 0, ptr %2, align 4 -- %6 = load i32, ptr %2, align 4 -- %7 = icmp ne i32 %6, 0 -- br i1 %7, label %9, label %8 -- -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- br label %10 -- -- store i32 1, ptr %4, align 4 -- br label %10 -- -- %11 = load i32, ptr %2, align 4 -- %12 = icmp ne i32 %11, 0 -- br i1 %12, label %14, label %13 -- -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- br label %15 -- -- store i32 1, ptr %4, align 4 -- br label %15 -- -- ret i32 0 --} -- --define dso_local i32 @main() #0 { --; CHECK-LABEL: main: --; CHECK: # %bb.0: --; CHECK-NEXT: addi.w $sp, $sp, -32 --; CHECK-NEXT: .cfi_def_cfa_offset 32 --; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill --; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill --; CHECK-NEXT: .cfi_offset 1, -4 --; CHECK-NEXT: .cfi_offset 22, -8 --; CHECK-NEXT: addi.w $fp, $sp, 32 --; CHECK-NEXT: .cfi_def_cfa 22, 0 --; CHECK-NEXT: pcalau12i $a0, x --; CHECK-NEXT: addi.w $a0, $a0, x --; CHECK-NEXT: ori $a1, $zero, 1 --; CHECK-NEXT: st.w $a1, $a0, 0 --; CHECK-NEXT: st.w $zero, $fp, -12 --; CHECK-NEXT: st.w $a1, $fp, -16 --; CHECK-NEXT: ori $a0, $zero, 2 --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: ori $a2, $zero, 3 --; CHECK-NEXT: st.w $a2, $fp, -24 --; CHECK-NEXT: ori $a3, $zero, 4 --; CHECK-NEXT: st.w $a3, $fp, -28 --; CHECK-NEXT: #APP --; CHECK-NEXT: #NO_APP --; CHECK-NEXT: st.w $a0, $fp, -20 --; CHECK-NEXT: st.w $a1, $fp, -16 --; CHECK-NEXT: st.w $a2, $fp, -24 --; CHECK-NEXT: st.w $a3, $fp, -28 --; CHECK-NEXT: move $a0, $zero --; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload --; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload --; CHECK-NEXT: addi.w $sp, $sp, 32 --; CHECK-NEXT: jirl $zero, $ra, 0 -- %1 = alloca i32, align 4 -- %2 = alloca i32, align 4 -- %3 = alloca i32, align 4 -- %4 = alloca i32, align 4 -- %5 = alloca i32, align 4 -- -- store i32 0, ptr %1, align 4 -- store i32 0, ptr @x, align 4 -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- store i32 1, ptr @x, align 4 -- call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"() -- store i32 1, ptr %2, align 4 -- store i32 2, ptr %3, align 4 -- store i32 3, ptr %4, align 4 -- store i32 4, ptr %5, align 4 -- ret i32 0 --} -- --attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } -diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test -deleted file mode 100644 -index 2209d3036..000000000 ---- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test -+++ /dev/null -@@ -1,17 +0,0 @@ --# REQUIRES: loongarch-registered-target -- --## Check that generated functions are included. --# RUN: cp -f %S/Inputs/loongarch_generated_funcs.ll %t.ll && %update_llc_test_checks --include-generated-funcs %t.ll --# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.generated.expected -- --## Check that running the script again does not change the result: --# RUN: %update_llc_test_checks --include-generated-funcs %t.ll --# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.generated.expected -- --## Check that generated functions are not included. --# RUN: cp -f %S/Inputs/loongarch_generated_funcs.ll %t.ll && %update_llc_test_checks %t.ll --# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.nogenerated.expected -- --## Check that running the script again does not change the result: --# RUN: %update_llc_test_checks %t.ll --# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.nogenerated.expected -diff --git a/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test b/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test -deleted file mode 100644 -index b66273640..000000000 ---- a/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test -+++ /dev/null -@@ -1,64 +0,0 @@ --## Check llvm-readobj is able to decode all possible LoongArch e_flags field values. -- --# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S --# RUN: llvm-readobj -h %t-lp64s | FileCheck --check-prefix=READOBJ-LP64S %s --# RUN: llvm-readelf -h %t-lp64s | FileCheck --check-prefix=READELF-LP64S --match-full-lines %s -- --# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F --# RUN: llvm-readobj -h %t-lp64f | FileCheck --check-prefix=READOBJ-LP64F %s --# RUN: llvm-readelf -h %t-lp64f | FileCheck --check-prefix=READELF-LP64F --match-full-lines %s -- --# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D --# RUN: llvm-readobj -h %t-lp64d | FileCheck --check-prefix=READOBJ-LP64D %s --# RUN: llvm-readelf -h %t-lp64d | FileCheck --check-prefix=READELF-LP64D --match-full-lines %s -- --# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S --# RUN: llvm-readobj -h %t-ilp32s | FileCheck --check-prefix=READOBJ-ILP32S %s --# RUN: llvm-readelf -h %t-ilp32s | FileCheck --check-prefix=READELF-ILP32S --match-full-lines %s -- --# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F --# RUN: llvm-readobj -h %t-ilp32f | FileCheck --check-prefix=READOBJ-ILP32F %s --# RUN: llvm-readelf -h %t-ilp32f | FileCheck --check-prefix=READELF-ILP32F --match-full-lines %s -- --# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D --# RUN: llvm-readobj -h %t-ilp32d | FileCheck --check-prefix=READOBJ-ILP32D %s --# RUN: llvm-readelf -h %t-ilp32d | FileCheck --check-prefix=READELF-ILP32D --match-full-lines %s -- --# READOBJ-LP64S: Flags [ (0x1) --# READOBJ-LP64S-NEXT: EF_LOONGARCH_BASE_ABI_LP64S (0x1) --# READOBJ-LP64S-NEXT: ] -- --# READOBJ-LP64F: Flags [ (0x2) --# READOBJ-LP64F-NEXT: EF_LOONGARCH_BASE_ABI_LP64F (0x2) --# READOBJ-LP64F-NEXT: ] -- --# READOBJ-LP64D: Flags [ (0x3) --# READOBJ-LP64D-NEXT: EF_LOONGARCH_BASE_ABI_LP64D (0x3) --# READOBJ-LP64D-NEXT: ] -- --# READOBJ-ILP32S: Flags [ (0x5) --# READOBJ-ILP32S-NEXT: EF_LOONGARCH_BASE_ABI_ILP32S (0x5) --# READOBJ-ILP32S-NEXT: ] -- --# READOBJ-ILP32F: Flags [ (0x6) --# READOBJ-ILP32F-NEXT: EF_LOONGARCH_BASE_ABI_ILP32F (0x6) --# READOBJ-ILP32F-NEXT: ] -- --# READOBJ-ILP32D: Flags [ (0x7) --# READOBJ-ILP32D-NEXT: EF_LOONGARCH_BASE_ABI_ILP32D (0x7) --# READOBJ-ILP32D-NEXT: ] -- --# READELF-LP64S: Flags: 0x1, LP64, SOFT-FLOAT --# READELF-LP64F: Flags: 0x2, LP64, SINGLE-FLOAT --# READELF-LP64D: Flags: 0x3, LP64, DOUBLE-FLOAT --# READELF-ILP32S: Flags: 0x5, ILP32, SOFT-FLOAT --# READELF-ILP32F: Flags: 0x6, ILP32, SINGLE-FLOAT --# READELF-ILP32D: Flags: 0x7, ILP32, DOUBLE-FLOAT -- ----- !ELF --FileHeader: -- Class: ELFCLASS[[CLASS]] -- Data: ELFDATA2LSB -- Type: ET_EXEC -- Machine: EM_LOONGARCH -- Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] -diff --git a/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml b/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml -deleted file mode 100644 -index e4c4c292e..000000000 ---- a/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml -+++ /dev/null -@@ -1,29 +0,0 @@ --## Check obj2yaml is able to decode all possible LoongArch e_flags field values. -- --# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S --# RUN: obj2yaml %t-lp64s | FileCheck -DFLAG=LP64S %s -- --# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F --# RUN: obj2yaml %t-lp64f | FileCheck -DFLAG=LP64F %s -- --# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D --# RUN: obj2yaml %t-lp64d | FileCheck -DFLAG=LP64D %s -- --# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S --# RUN: obj2yaml %t-ilp32s | FileCheck -DFLAG=ILP32S %s -- --# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F --# RUN: obj2yaml %t-ilp32f | FileCheck -DFLAG=ILP32F %s -- --# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D --# RUN: obj2yaml %t-ilp32d | FileCheck -DFLAG=ILP32D %s -- --# CHECK: Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] -- ----- !ELF --FileHeader: -- Class: ELFCLASS[[CLASS]] -- Data: ELFDATA2LSB -- Type: ET_EXEC -- Machine: EM_LOONGARCH -- Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] -diff --git a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt -index a255c1c5d..38028cd3d 100644 ---- a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt -+++ b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt -@@ -40,6 +40,4 @@ if(APPLE) - target_link_libraries(dsymutil PRIVATE "-framework CoreFoundation") - endif(APPLE) - --if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB) -- target_link_libraries(dsymutil PRIVATE atomic) --endif() -+target_link_libraries(dsymutil PRIVATE ${LLVM_ATOMIC_LIB}) -diff --git a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt -index aa5aa2025..6faee031a 100644 ---- a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt -+++ b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt -@@ -17,9 +17,14 @@ add_llvm_tool(llvm-config - # Compute the substitution values for various items. - get_property(SUPPORT_SYSTEM_LIBS TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) - get_property(WINDOWSMANIFEST_SYSTEM_LIBS TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS) -+ - foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) - if(MSVC) -- set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") -+ if(IS_ABSOLUTE ${l}) -+ set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}") -+ else() -+ set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") -+ endif() - else() - if (l MATCHES "^-") - # If it's an option, pass it without changes. -@@ -34,6 +39,7 @@ foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) - endif() - endif() - endforeach() -+ - string(REPLACE ";" " " SYSTEM_LIBS "${SYSTEM_LIBS}") - - # Fetch target specific compile options, e.g. RTTI option -diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp -index ba7bae96a..ae2dec5d1 100644 ---- a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp -+++ b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp -@@ -1648,15 +1648,6 @@ const EnumEntry ElfHeaderAVRFlags[] = { - ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"), - }; - --const EnumEntry ElfHeaderLoongArchFlags[] = { -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32S, "ILP32, SOFT-FLOAT"), -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32F, "ILP32, SINGLE-FLOAT"), -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32D, "ILP32, DOUBLE-FLOAT"), -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64S, "LP64, SOFT-FLOAT"), -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64F, "LP64, SINGLE-FLOAT"), -- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64D, "LP64, DOUBLE-FLOAT"), --}; -- - - const EnumEntry ElfSymOtherFlags[] = { - LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), -@@ -3366,9 +3357,6 @@ template void GNUELFDumper::printFileHeaders() { - else if (e.e_machine == EM_AVR) - ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderAVRFlags), - unsigned(ELF::EF_AVR_ARCH_MASK)); -- else if (e.e_machine == EM_LOONGARCH) -- ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), -- unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); - Str = "0x" + utohexstr(e.e_flags); - if (!ElfFlags.empty()) - Str = Str + ", " + ElfFlags; -@@ -6519,9 +6507,6 @@ template void LLVMELFDumper::printFileHeaders() { - else if (E.e_machine == EM_AVR) - W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAVRFlags), - unsigned(ELF::EF_AVR_ARCH_MASK)); -- else if (E.e_machine == EM_LOONGARCH) -- W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), -- unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); - else - W.printFlags("Flags", E.e_flags); - W.printNumber("HeaderSize", E.e_ehsize); -diff --git a/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn b/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn -index c8506d9ef..7431a507c 100644 ---- a/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn -+++ b/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn -@@ -1,7 +1,7 @@ - import("//llvm/utils/gn/build/compiled_action.gni") - - compiled_action("Confusables.inc") { -- tool = "ConfusableTable:make-confusable-table" -+ tool = "ConfusableTable:clang-tidy-confusable-chars-gen" - inputs = [ "ConfusableTable/confusables.txt" ] - outputs = [ "$target_gen_dir/$target_name" ] - args = [ -diff --git a/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni b/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni -index ac79ba5bb..d485a133f 100644 ---- a/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni -+++ b/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni -@@ -1,4 +1,4 @@ - llvm_version_major = 15 - llvm_version_minor = 0 --llvm_version_patch = 2 -+llvm_version_patch = 7 - llvm_version = "$llvm_version_major.$llvm_version_minor.$llvm_version_patch" -diff --git a/src/llvm-project/llvm/utils/lit/lit/__init__.py b/src/llvm-project/llvm/utils/lit/lit/__init__.py -index 2ee97f578..928d6db8d 100644 ---- a/src/llvm-project/llvm/utils/lit/lit/__init__.py -+++ b/src/llvm-project/llvm/utils/lit/lit/__init__.py -@@ -2,7 +2,7 @@ - - __author__ = 'Daniel Dunbar' - __email__ = 'daniel@minormatter.com' --__versioninfo__ = (15, 0, 2) -+__versioninfo__ = (15, 0, 7) - __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' - - __all__ = [] -diff --git a/src/llvm-project/llvm/utils/lit/lit/llvm/config.py b/src/llvm-project/llvm/utils/lit/lit/llvm/config.py -index b65316128..7dae83733 100644 ---- a/src/llvm-project/llvm/utils/lit/lit/llvm/config.py -+++ b/src/llvm-project/llvm/utils/lit/lit/llvm/config.py -@@ -609,7 +609,7 @@ class LLVMConfig(object): - self.with_environment('PATH', paths, append_path=True) - - lib_dir_props = [self.config.name.lower() + '_libs_dir', -- 'lld_libs_dir', 'llvm_libs_dir'] -+ 'lld_libs_dir', 'llvm_shlib_dir', 'llvm_libs_dir'] - lib_paths = [getattr(self.config, pp) for pp in lib_dir_props - if getattr(self.config, pp, None)] - --- -2.41.0 - diff --git a/0006-rust-add-loongarch64-support.patch b/0006-rust-add-loongarch64-support.patch deleted file mode 100644 index 2b91418..0000000 --- a/0006-rust-add-loongarch64-support.patch +++ /dev/null @@ -1,1691 +0,0 @@ -From d81a20d98d9fd47edb762a1716b65d4bfeffae60 Mon Sep 17 00:00:00 2001 -From: WANG Rui -Date: Wed, 26 Apr 2023 14:26:58 +0800 -Subject: [PATCH 6/6] rust: add loongarch64 support - ---- - compiler/rustc_ast_lowering/src/asm.rs | 1 + - .../rustc_codegen_gcc/example/alloc_system.rs | 1 + - compiler/rustc_codegen_gcc/src/asm.rs | 5 + - compiler/rustc_codegen_llvm/src/asm.rs | 17 + - .../rustc_codegen_ssa/src/back/metadata.rs | 6 + - .../rustc_codegen_ssa/src/target_features.rs | 6 + - compiler/rustc_feature/src/active.rs | 1 + - compiler/rustc_hir_analysis/src/collect.rs | 1 + - compiler/rustc_llvm/build.rs | 3 +- - .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 + - compiler/rustc_llvm/src/lib.rs | 8 + - compiler/rustc_span/src/symbol.rs | 1 + - .../rustc_target/src/abi/call/loongarch.rs | 342 ++++++++++++++++++ - compiler/rustc_target/src/abi/call/mod.rs | 2 + - compiler/rustc_target/src/asm/loongarch.rs | 131 +++++++ - compiler/rustc_target/src/asm/mod.rs | 44 +++ - .../src/spec/loongarch64_unknown_linux_gnu.rs | 18 + - compiler/rustc_target/src/spec/mod.rs | 2 + - library/std/src/env.rs | 1 + - library/std/src/os/linux/raw.rs | 1 + - library/std/src/personality/gcc.rs | 3 + - library/std/src/sys/common/alloc.rs | 1 + - library/unwind/src/libunwind.rs | 3 + - src/bootstrap/bootstrap.py | 1 + - src/bootstrap/lib.rs | 2 +- - src/bootstrap/native.rs | 2 +- - src/ci/github-actions/ci.yml | 3 + - src/doc/rustc/src/platform-support.md | 1 + - src/librustdoc/clean/cfg.rs | 1 + - src/test/assembly/asm/loongarch-types.rs | 194 ++++++++++ - .../codegen/abi-main-signature-16bit-c-int.rs | 1 + - src/test/codegen/call-llvm-intrinsics.rs | 1 + - src/test/codegen/global_asm.rs | 1 + - src/test/codegen/global_asm_include.rs | 1 + - src/test/codegen/global_asm_x2.rs | 1 + - .../loongarch-abi/call-llvm-intrinsics.rs | 30 ++ - .../codegen/repr-transparent-aggregates-1.rs | 1 + - .../codegen/repr-transparent-aggregates-2.rs | 1 + - src/test/codegen/repr-transparent.rs | 1 + - .../atomic-lock-free/Makefile | 4 + - src/test/ui/abi/stack-probes-lto.rs | 1 + - src/test/ui/cfg/conditional-compile-arch.rs | 3 + - src/test/ui/check-cfg/compact-values.stderr | 2 +- - src/test/ui/process/nofile-limit.rs | 3 +- - src/test/ui/target-feature/gate.rs | 2 + - .../ui/target-feature/invalid-attribute.rs | 1 + - src/tools/build-manifest/src/main.rs | 2 + - src/tools/clippy/tests/ui/asm_syntax.rs | 1 + - src/tools/compiletest/src/common.rs | 2 +- - 49 files changed, 862 insertions(+), 6 deletions(-) - create mode 100644 compiler/rustc_target/src/abi/call/loongarch.rs - create mode 100644 compiler/rustc_target/src/asm/loongarch.rs - create mode 100644 compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs - create mode 100644 src/test/assembly/asm/loongarch-types.rs - create mode 100644 src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs - -diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs -index 450cdf246..260a0b24b 100644 ---- a/compiler/rustc_ast_lowering/src/asm.rs -+++ b/compiler/rustc_ast_lowering/src/asm.rs -@@ -44,6 +44,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { - | asm::InlineAsmArch::AArch64 - | asm::InlineAsmArch::RiscV32 - | asm::InlineAsmArch::RiscV64 -+ | asm::InlineAsmArch::LoongArch64 - ); - if !is_stable && !self.tcx.features().asm_experimental_arch { - feature_err( -diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs -index 89661918d..df960c4b8 100644 ---- a/compiler/rustc_codegen_gcc/example/alloc_system.rs -+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs -@@ -21,6 +21,7 @@ - const MIN_ALIGN: usize = 8; - #[cfg(all(any(target_arch = "x86_64", - target_arch = "aarch64", -+ target_arch = "loongarch64", - target_arch = "mips64", - target_arch = "s390x", - target_arch = "sparc64")))] -diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs -index c346dbd63..58563ac9a 100644 ---- a/compiler/rustc_codegen_gcc/src/asm.rs -+++ b/compiler/rustc_codegen_gcc/src/asm.rs -@@ -582,6 +582,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { - InlineAsmRegClass::Avr(_) => unimplemented!(), - InlineAsmRegClass::Bpf(_) => unimplemented!(), - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(), -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => unimplemented!(), -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => unimplemented!(), - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(), - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(), - InlineAsmRegClass::Msp430(_) => unimplemented!(), -@@ -646,6 +648,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl - InlineAsmRegClass::Avr(_) => unimplemented!(), - InlineAsmRegClass::Bpf(_) => unimplemented!(), - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::Msp430(_) => unimplemented!(), -@@ -773,6 +777,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option - InlineAsmRegClass::Avr(_) => unimplemented!(), - InlineAsmRegClass::Bpf(_) => unimplemented!(), - InlineAsmRegClass::Hexagon(_) => unimplemented!(), -+ InlineAsmRegClass::LoongArch(_) => unimplemented!(), - InlineAsmRegClass::Mips(_) => unimplemented!(), - InlineAsmRegClass::Msp430(_) => unimplemented!(), - InlineAsmRegClass::Nvptx(_) => unimplemented!(), -diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs -index 017513721..2d380f1c4 100644 ---- a/compiler/rustc_codegen_llvm/src/asm.rs -+++ b/compiler/rustc_codegen_llvm/src/asm.rs -@@ -235,6 +235,18 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { - InlineAsmArch::Msp430 => { - constraints.push("~{sr}".to_string()); - } -+ InlineAsmArch::LoongArch64 => { -+ constraints.extend_from_slice(&[ -+ "~{$fcc0}".to_string(), -+ "~{$fcc1}".to_string(), -+ "~{$fcc2}".to_string(), -+ "~{$fcc3}".to_string(), -+ "~{$fcc4}".to_string(), -+ "~{$fcc5}".to_string(), -+ "~{$fcc6}".to_string(), -+ "~{$fcc7}".to_string(), -+ ]); -+ } - } - } - if !options.contains(InlineAsmOptions::NOMEM) { -@@ -614,6 +626,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("LLVM backend does not support SPIR-V") - } -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::Err => unreachable!(), - } - .to_string(), -@@ -708,6 +722,7 @@ fn modifier_to_llvm( - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("LLVM backend does not support SPIR-V") - } -+ InlineAsmRegClass::LoongArch(_) => None, - InlineAsmRegClass::Err => unreachable!(), - } - } -@@ -782,6 +797,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("LLVM backend does not support SPIR-V") - } -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), -+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), - InlineAsmRegClass::Err => unreachable!(), - } - } -diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs -index 99ddd1764..ae639d064 100644 ---- a/compiler/rustc_codegen_ssa/src/back/metadata.rs -+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs -@@ -121,6 +121,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Architecture::Msp430, - "hexagon" => Architecture::Hexagon, - "bpf" => Architecture::Bpf, -+ "loongarch64" => Architecture::LoongArch64, - // Unsupported architecture. - _ => return None, - }; -@@ -172,6 +173,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option { -+ // copied from `loongarch64-linux-gnu-gcc foo.c -c` -+ let e_flags = elf::EF_LARCH_ABI; -+ e_flags -+ } - _ => 0, - }; - // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` -diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs -index 83407ee8f..93d5b79c4 100644 ---- a/compiler/rustc_codegen_ssa/src/target_features.rs -+++ b/compiler/rustc_codegen_ssa/src/target_features.rs -@@ -209,6 +209,10 @@ const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ - // tidy-alphabetical-end - ]; - -+const LOONGARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ -+ ("fp64", Some(sym::loongarch64_target_feature)), -+]; -+ - const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ - // tidy-alphabetical-start - ("altivec", Some(sym::powerpc_target_feature)), -@@ -292,6 +296,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Opt - "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, - "bpf" => BPF_ALLOWED_FEATURES, -+ "loongarch64" => LOONGARCH64_ALLOWED_FEATURES, - _ => &[], - } - } -diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs -index 647ccdec7..546a24164 100644 ---- a/compiler/rustc_feature/src/active.rs -+++ b/compiler/rustc_feature/src/active.rs -@@ -254,6 +254,7 @@ declare_features! ( - (active, ermsb_target_feature, "1.49.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - (active, hexagon_target_feature, "1.27.0", Some(44839), None), -+ (active, loongarch64_target_feature, "1.57.0", Some(44839), None), - (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), -diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs -index 346d2e2fc..083f661c8 100644 ---- a/compiler/rustc_hir_analysis/src/collect.rs -+++ b/compiler/rustc_hir_analysis/src/collect.rs -@@ -1538,6 +1538,7 @@ fn from_target_feature( - let allowed = match feature_gate.as_ref().copied() { - Some(sym::arm_target_feature) => rust_features.arm_target_feature, - Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, -+ Some(sym::loongarch64_target_feature) => rust_features.loongarch64_target_feature, - Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, - Some(sym::mips_target_feature) => rust_features.mips_target_feature, - Some(sym::riscv_target_feature) => rust_features.riscv_target_feature, -diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs -index 28e092c1e..c0c60bc0c 100644 ---- a/compiler/rustc_llvm/build.rs -+++ b/compiler/rustc_llvm/build.rs -@@ -10,6 +10,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[ - "aarch64", - "amdgpu", - "avr", -+ "loongarch", - "m68k", - "mips", - "powerpc", -@@ -240,7 +241,7 @@ fn main() { - } else if target.contains("windows-gnu") { - println!("cargo:rustc-link-lib=shell32"); - println!("cargo:rustc-link-lib=uuid"); -- } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") { -+ } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") || target.contains("loongarch") { - println!("cargo:rustc-link-lib=z"); - } else if target.starts_with("arm") - || target.starts_with("mips-") -diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp -index 18d37d95a..ac91ee420 100644 ---- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp -+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp -@@ -166,6 +166,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { - #define SUBTARGET_HEXAGON - #endif - -+#ifdef LLVM_COMPONENT_LOONGARCH -+#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch) -+#else -+#define SUBTARGET_LOONGARCH -+#endif -+ - #define GEN_SUBTARGETS \ - SUBTARGET_X86 \ - SUBTARGET_ARM \ -@@ -179,6 +185,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { - SUBTARGET_SPARC \ - SUBTARGET_HEXAGON \ - SUBTARGET_RISCV \ -+ SUBTARGET_LOONGARCH \ - - #define SUBTARGET(x) \ - namespace llvm { \ -diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs -index 8542dcf5b..06351731b 100644 ---- a/compiler/rustc_llvm/src/lib.rs -+++ b/compiler/rustc_llvm/src/lib.rs -@@ -102,6 +102,14 @@ pub fn initialize_available_targets() { - LLVMInitializeM68kAsmPrinter, - LLVMInitializeM68kAsmParser - ); -+ init_target!( -+ llvm_component = "loongarch", -+ LLVMInitializeLoongArchTargetInfo, -+ LLVMInitializeLoongArchTarget, -+ LLVMInitializeLoongArchTargetMC, -+ LLVMInitializeLoongArchAsmPrinter, -+ LLVMInitializeLoongArchAsmParser -+ ); - init_target!( - llvm_component = "mips", - LLVMInitializeMipsTargetInfo, -diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs -index 7f16da52b..b0c040f72 100644 ---- a/compiler/rustc_span/src/symbol.rs -+++ b/compiler/rustc_span/src/symbol.rs -@@ -900,6 +900,7 @@ symbols! { - log_syntax, - logf32, - logf64, -+ loongarch64_target_feature, - loop_break_value, - lt, - macro_at_most_once_rep, -diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs -new file mode 100644 -index 000000000..018fe7d15 ---- /dev/null -+++ b/compiler/rustc_target/src/abi/call/loongarch.rs -@@ -0,0 +1,342 @@ -+use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; -+use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; -+use crate::spec::HasTargetSpec; -+ -+#[derive(Copy, Clone)] -+enum RegPassKind { -+ Float(Reg), -+ Integer(Reg), -+ Unknown, -+} -+ -+#[derive(Copy, Clone)] -+enum FloatConv { -+ FloatPair(Reg, Reg), -+ Float(Reg), -+ MixedPair(Reg, Reg), -+} -+ -+#[derive(Copy, Clone)] -+struct CannotUseFpConv; -+ -+fn is_loongarch_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool { -+ match arg.layout.abi { -+ Abi::Vector { .. } => true, -+ _ => arg.layout.is_aggregate(), -+ } -+} -+ -+fn should_use_fp_conv_helper<'a, Ty, C>( -+ cx: &C, -+ arg_layout: &TyAndLayout<'a, Ty>, -+ xlen: u64, -+ flen: u64, -+ field1_kind: &mut RegPassKind, -+ field2_kind: &mut RegPassKind, -+) -> Result<(), CannotUseFpConv> -+where -+ Ty: TyAbiInterface<'a, C> + Copy, -+{ -+ match arg_layout.abi { -+ Abi::Scalar(scalar) => match scalar.primitive() { -+ abi::Int(..) | abi::Pointer => { -+ if arg_layout.size.bits() > xlen { -+ return Err(CannotUseFpConv); -+ } -+ match (*field1_kind, *field2_kind) { -+ (RegPassKind::Unknown, _) => { -+ *field1_kind = RegPassKind::Integer(Reg { -+ kind: RegKind::Integer, -+ size: arg_layout.size, -+ }); -+ } -+ (RegPassKind::Float(_), RegPassKind::Unknown) => { -+ *field2_kind = RegPassKind::Integer(Reg { -+ kind: RegKind::Integer, -+ size: arg_layout.size, -+ }); -+ } -+ _ => return Err(CannotUseFpConv), -+ } -+ } -+ abi::F32 | abi::F64 => { -+ if arg_layout.size.bits() > flen { -+ return Err(CannotUseFpConv); -+ } -+ match (*field1_kind, *field2_kind) { -+ (RegPassKind::Unknown, _) => { -+ *field1_kind = -+ RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); -+ } -+ (_, RegPassKind::Unknown) => { -+ *field2_kind = -+ RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); -+ } -+ _ => return Err(CannotUseFpConv), -+ } -+ } -+ }, -+ Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv), -+ Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields { -+ FieldsShape::Primitive => { -+ unreachable!("aggregates can't have `FieldsShape::Primitive`") -+ } -+ FieldsShape::Union(_) => { -+ if !arg_layout.is_zst() { -+ return Err(CannotUseFpConv); -+ } -+ } -+ FieldsShape::Array { count, .. } => { -+ for _ in 0..count { -+ let elem_layout = arg_layout.field(cx, 0); -+ should_use_fp_conv_helper( -+ cx, -+ &elem_layout, -+ xlen, -+ flen, -+ field1_kind, -+ field2_kind, -+ )?; -+ } -+ } -+ FieldsShape::Arbitrary { .. } => { -+ match arg_layout.variants { -+ abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), -+ abi::Variants::Single { .. } => (), -+ } -+ for i in arg_layout.fields.index_by_increasing_offset() { -+ let field = arg_layout.field(cx, i); -+ should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; -+ } -+ } -+ }, -+ } -+ Ok(()) -+} -+ -+fn should_use_fp_conv<'a, Ty, C>( -+ cx: &C, -+ arg: &TyAndLayout<'a, Ty>, -+ xlen: u64, -+ flen: u64, -+) -> Option -+where -+ Ty: TyAbiInterface<'a, C> + Copy, -+{ -+ let mut field1_kind = RegPassKind::Unknown; -+ let mut field2_kind = RegPassKind::Unknown; -+ if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { -+ return None; -+ } -+ match (field1_kind, field2_kind) { -+ (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), -+ (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), -+ (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), -+ (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), -+ _ => None, -+ } -+} -+ -+fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool -+where -+ Ty: TyAbiInterface<'a, C> + Copy, -+{ -+ if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) { -+ match conv { -+ FloatConv::Float(f) => { -+ arg.cast_to(f); -+ } -+ FloatConv::FloatPair(l, r) => { -+ arg.cast_to(CastTarget::pair(l, r)); -+ } -+ FloatConv::MixedPair(l, r) => { -+ arg.cast_to(CastTarget::pair(l, r)); -+ } -+ } -+ return false; -+ } -+ -+ let total = arg.layout.size; -+ -+ // "Scalars wider than 2✕XLEN are passed by reference and are replaced in -+ // the argument list with the address." -+ // "Aggregates larger than 2✕XLEN bits are passed by reference and are -+ // replaced in the argument list with the address, as are C++ aggregates -+ // with nontrivial copy constructors, destructors, or vtables." -+ if total.bits() > 2 * xlen { -+ // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. -+ if is_loongarch_aggregate(arg) { -+ arg.make_indirect(); -+ } -+ return true; -+ } -+ -+ let xlen_reg = match xlen { -+ 32 => Reg::i32(), -+ 64 => Reg::i64(), -+ _ => unreachable!("Unsupported XLEN: {}", xlen), -+ }; -+ if is_loongarch_aggregate(arg) { -+ if total.bits() <= xlen { -+ arg.cast_to(xlen_reg); -+ } else { -+ arg.cast_to(Uniform { unit: xlen_reg, total: Size::from_bits(xlen * 2) }); -+ } -+ return false; -+ } -+ -+ // "When passed in registers, scalars narrower than XLEN bits are widened -+ // according to the sign of their type up to 32 bits, then sign-extended to -+ // XLEN bits." -+ extend_integer_width(arg, xlen); -+ false -+} -+ -+fn classify_arg<'a, Ty, C>( -+ cx: &C, -+ arg: &mut ArgAbi<'a, Ty>, -+ xlen: u64, -+ flen: u64, -+ is_vararg: bool, -+ avail_gprs: &mut u64, -+ avail_fprs: &mut u64, -+) where -+ Ty: TyAbiInterface<'a, C> + Copy, -+{ -+ if !is_vararg { -+ match should_use_fp_conv(cx, &arg.layout, xlen, flen) { -+ Some(FloatConv::Float(f)) if *avail_fprs >= 1 => { -+ *avail_fprs -= 1; -+ arg.cast_to(f); -+ return; -+ } -+ Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { -+ *avail_fprs -= 2; -+ arg.cast_to(CastTarget::pair(l, r)); -+ return; -+ } -+ Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { -+ *avail_gprs -= 1; -+ *avail_fprs -= 1; -+ arg.cast_to(CastTarget::pair(l, r)); -+ return; -+ } -+ _ => (), -+ } -+ } -+ -+ let total = arg.layout.size; -+ let align = arg.layout.align.abi.bits(); -+ -+ // "Scalars wider than 2✕XLEN are passed by reference and are replaced in -+ // the argument list with the address." -+ // "Aggregates larger than 2✕XLEN bits are passed by reference and are -+ // replaced in the argument list with the address, as are C++ aggregates -+ // with nontrivial copy constructors, destructors, or vtables." -+ if total.bits() > 2 * xlen { -+ // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. -+ if is_loongarch_aggregate(arg) { -+ arg.make_indirect(); -+ } -+ if *avail_gprs >= 1 { -+ *avail_gprs -= 1; -+ } -+ return; -+ } -+ -+ let double_xlen_reg = match xlen { -+ 32 => Reg::i64(), -+ 64 => Reg::i128(), -+ _ => unreachable!("Unsupported XLEN: {}", xlen), -+ }; -+ -+ let xlen_reg = match xlen { -+ 32 => Reg::i32(), -+ 64 => Reg::i64(), -+ _ => unreachable!("Unsupported XLEN: {}", xlen), -+ }; -+ -+ if total.bits() > xlen { -+ let align_regs = align > xlen; -+ if is_loongarch_aggregate(arg) { -+ arg.cast_to(Uniform { -+ unit: if align_regs { double_xlen_reg } else { xlen_reg }, -+ total: Size::from_bits(xlen * 2), -+ }); -+ } -+ if align_regs && is_vararg { -+ *avail_gprs -= *avail_gprs % 2; -+ } -+ if *avail_gprs >= 2 { -+ *avail_gprs -= 2; -+ } else { -+ *avail_gprs = 0; -+ } -+ return; -+ } else if is_loongarch_aggregate(arg) { -+ arg.cast_to(xlen_reg); -+ if *avail_gprs >= 1 { -+ *avail_gprs -= 1; -+ } -+ return; -+ } -+ -+ // "When passed in registers, scalars narrower than XLEN bits are widened -+ // according to the sign of their type up to 32 bits, then sign-extended to -+ // XLEN bits." -+ if *avail_gprs >= 1 { -+ extend_integer_width(arg, xlen); -+ *avail_gprs -= 1; -+ } -+} -+ -+fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { -+ if let Abi::Scalar(scalar) = arg.layout.abi { -+ if let abi::Int(i, _) = scalar.primitive() { -+ // 32-bit integers are always sign-extended -+ if i.size().bits() == 32 && xlen > 32 { -+ if let PassMode::Direct(ref mut attrs) = arg.mode { -+ attrs.ext(ArgExtension::Sext); -+ return; -+ } -+ } -+ } -+ } -+ -+ arg.extend_integer_width_to(xlen); -+} -+ -+pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) -+where -+ Ty: TyAbiInterface<'a, C> + Copy, -+ C: HasDataLayout + HasTargetSpec, -+{ -+ let xlen = cx.data_layout().pointer_size.bits(); -+ let flen = match &cx.target_spec().llvm_abiname[..] { -+ "lp64" => 64, -+ "lp32" | "lpx32" => 32, -+ _ => 0, -+ }; -+ -+ let mut avail_gprs = 8; -+ let mut avail_fprs = 8; -+ -+ if !fn_abi.ret.is_ignore() && classify_ret(cx, &mut fn_abi.ret, xlen, flen) { -+ avail_gprs -= 1; -+ } -+ -+ for (i, arg) in fn_abi.args.iter_mut().enumerate() { -+ if arg.is_ignore() { -+ continue; -+ } -+ classify_arg( -+ cx, -+ arg, -+ xlen, -+ flen, -+ i >= fn_abi.fixed_count as usize, -+ &mut avail_gprs, -+ &mut avail_fprs, -+ ); -+ } -+} -diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs -index 9e5f0e4d1..c5a6f9893 100644 ---- a/compiler/rustc_target/src/abi/call/mod.rs -+++ b/compiler/rustc_target/src/abi/call/mod.rs -@@ -10,6 +10,7 @@ mod arm; - mod avr; - mod bpf; - mod hexagon; -+mod loongarch; - mod m68k; - mod mips; - mod mips64; -@@ -696,6 +697,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { - "amdgpu" => amdgpu::compute_abi_info(cx, self), - "arm" => arm::compute_abi_info(cx, self), - "avr" => avr::compute_abi_info(self), -+ "loongarch64" => loongarch::compute_abi_info(cx, self), - "m68k" => m68k::compute_abi_info(self), - "mips" => mips::compute_abi_info(cx, self), - "mips64" => mips64::compute_abi_info(cx, self), -diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs -new file mode 100644 -index 000000000..f1b879662 ---- /dev/null -+++ b/compiler/rustc_target/src/asm/loongarch.rs -@@ -0,0 +1,131 @@ -+use super::{InlineAsmArch, InlineAsmType}; -+use rustc_macros::HashStable_Generic; -+use rustc_span::Symbol; -+use std::fmt; -+ -+def_reg_class! { -+ LoongArch LoongArchInlineAsmRegClass { -+ reg, -+ freg, -+ } -+} -+ -+impl LoongArchInlineAsmRegClass { -+ pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { -+ &[] -+ } -+ -+ pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { -+ None -+ } -+ -+ pub fn suggest_modifier( -+ self, -+ _arch: InlineAsmArch, -+ _ty: InlineAsmType, -+ ) -> Option<(char, &'static str)> { -+ None -+ } -+ -+ pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { -+ None -+ } -+ -+ pub fn supported_types( -+ self, -+ arch: InlineAsmArch, -+ ) -> &'static [(InlineAsmType, Option)] { -+ match (self, arch) { -+ (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; }, -+ (Self::reg, _) => types! { _: I8, I16, I32, F32; }, -+ (Self::freg, _) => types! { _: F32, F64; }, -+ } -+ } -+} -+ -+// The reserved registers are taken from -+def_regs! { -+ LoongArch LoongArchInlineAsmReg LoongArchInlineAsmRegClass { -+ r1: reg = ["$r1","$ra"], -+ r4: reg = ["$r4","$a0"], -+ r5: reg = ["$r5","$a1"], -+ r6: reg = ["$r6","$a2"], -+ r7: reg = ["$r7","$a3"], -+ r8: reg = ["$r8","$a4"], -+ r9: reg = ["$r9","$a5"], -+ r10: reg = ["$r10","$a6"], -+ r11: reg = ["$r11","$a7"], -+ r12: reg = ["$r12","$t0"], -+ r13: reg = ["$r13","$t1"], -+ r14: reg = ["$r14","$t2"], -+ r15: reg = ["$r15","$t3"], -+ r16: reg = ["$r16","$t4"], -+ r17: reg = ["$r17","$t5"], -+ r18: reg = ["$r18","$t6"], -+ r19: reg = ["$r19","$t7"], -+ r20: reg = ["$r20","$t8"], -+ r23: reg = ["$r23","$s0"], -+ r24: reg = ["$r24","$s1"], -+ r25: reg = ["$r25","$s2"], -+ r26: reg = ["$r26","$s3"], -+ r27: reg = ["$r27","$s4"], -+ r28: reg = ["$r28","$s5"], -+ r29: reg = ["$r29","$s6"], -+ r30: reg = ["$r30","$s7"], -+ f0: freg = ["$f0","$fa0"], -+ f1: freg = ["$f1","$fa1"], -+ f2: freg = ["$f2","$fa2"], -+ f3: freg = ["$f3","$fa3"], -+ f4: freg = ["$f4","$fa4"], -+ f5: freg = ["$f5","$fa5"], -+ f6: freg = ["$f6","$fa6"], -+ f7: freg = ["$f7","$fa7"], -+ f8: freg = ["$f8","$ft0"], -+ f9: freg = ["$f9","$ft1"], -+ f10: freg = ["$f10","$ft2"], -+ f11: freg = ["$f11","$ft3"], -+ f12: freg = ["$f12","$ft4"], -+ f13: freg = ["$f13","$ft5"], -+ f14: freg = ["$f14","$ft6"], -+ f15: freg = ["$f15","$ft7"], -+ f16: freg = ["$f16","$ft8"], -+ f17: freg = ["$f17","$ft9"], -+ f18: freg = ["$f18","$ft10"], -+ f19: freg = ["$f19","$ft11"], -+ f20: freg = ["$f20","$ft12"], -+ f21: freg = ["$f21","$ft13"], -+ f22: freg = ["$f22","$ft14"], -+ f23: freg = ["$f23","$ft15"], -+ f24: freg = ["$f24","$fs0"], -+ f25: freg = ["$f25","$fs1"], -+ f26: freg = ["$f26","$fs2"], -+ f27: freg = ["$f27","$fs3"], -+ f28: freg = ["$f28","$fs4"], -+ f29: freg = ["$f29","$fs5"], -+ f30: freg = ["$f30","$fs6"], -+ f31: freg = ["$f31","$fs7"], -+ #error = ["$r0", "$zero"] => -+ "constant zero cannot be used as an operand for inline asm", -+ #error = ["$r2", "$tp"] => -+ "reserved for TLS", -+ #error = ["$r3", "$sp"] => -+ "the stack pointer cannot be used as an operand for inline asm", -+ #error = ["$r21", "$x"] => -+ "reserved for ABI extension", -+ #error = ["$r22", "$fp"] => -+ "the frame pointer cannot be used as an operand for inline asm", -+ #error = ["$r31", "$s8"] => -+ "r31 is used internally by LLVM and cannot be used as an operand for inline asm", -+ } -+} -+ -+impl LoongArchInlineAsmReg { -+ pub fn emit( -+ self, -+ out: &mut dyn fmt::Write, -+ _arch: InlineAsmArch, -+ _modifier: Option, -+ ) -> fmt::Result { -+ out.write_str(self.name()) -+ } -+} -diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs -index 65d2cd64b..2438ac3e8 100644 ---- a/compiler/rustc_target/src/asm/mod.rs -+++ b/compiler/rustc_target/src/asm/mod.rs -@@ -167,6 +167,7 @@ mod arm; - mod avr; - mod bpf; - mod hexagon; -+mod loongarch; - mod mips; - mod msp430; - mod nvptx; -@@ -182,6 +183,7 @@ pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; - pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; - pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; - pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; -+pub use loongarch::{LoongArchInlineAsmReg, LoongArchInlineAsmRegClass}; - pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; - pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}; - pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; -@@ -213,6 +215,7 @@ pub enum InlineAsmArch { - Bpf, - Avr, - Msp430, -+ LoongArch64, - } - - impl FromStr for InlineAsmArch { -@@ -230,6 +233,7 @@ impl FromStr for InlineAsmArch { - "powerpc" => Ok(Self::PowerPC), - "powerpc64" => Ok(Self::PowerPC64), - "hexagon" => Ok(Self::Hexagon), -+ "loongarch64" => Ok(Self::LoongArch64), - "mips" => Ok(Self::Mips), - "mips64" => Ok(Self::Mips64), - "s390x" => Ok(Self::S390x), -@@ -254,6 +258,7 @@ pub enum InlineAsmReg { - Nvptx(NvptxInlineAsmReg), - PowerPC(PowerPCInlineAsmReg), - Hexagon(HexagonInlineAsmReg), -+ LoongArch(LoongArchInlineAsmReg), - Mips(MipsInlineAsmReg), - S390x(S390xInlineAsmReg), - SpirV(SpirVInlineAsmReg), -@@ -274,6 +279,7 @@ impl InlineAsmReg { - Self::RiscV(r) => r.name(), - Self::PowerPC(r) => r.name(), - Self::Hexagon(r) => r.name(), -+ Self::LoongArch(r) => r.name(), - Self::Mips(r) => r.name(), - Self::S390x(r) => r.name(), - Self::Bpf(r) => r.name(), -@@ -291,6 +297,7 @@ impl InlineAsmReg { - Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), - Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), - Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), -+ Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()), - Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), - Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), - Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), -@@ -316,6 +323,7 @@ impl InlineAsmReg { - Self::PowerPC(PowerPCInlineAsmReg::parse(name)?) - } - InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?), -+ InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmReg::parse(name)?), - InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - Self::Mips(MipsInlineAsmReg::parse(name)?) - } -@@ -345,6 +353,7 @@ impl InlineAsmReg { - Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), - Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), - Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), -+ Self::LoongArch(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), - Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), - Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), - Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), -@@ -369,6 +378,7 @@ impl InlineAsmReg { - Self::RiscV(r) => r.emit(out, arch, modifier), - Self::PowerPC(r) => r.emit(out, arch, modifier), - Self::Hexagon(r) => r.emit(out, arch, modifier), -+ Self::LoongArch(r) => r.emit(out, arch, modifier), - Self::Mips(r) => r.emit(out, arch, modifier), - Self::S390x(r) => r.emit(out, arch, modifier), - Self::Bpf(r) => r.emit(out, arch, modifier), -@@ -386,6 +396,7 @@ impl InlineAsmReg { - Self::RiscV(_) => cb(self), - Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), - Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), -+ Self::LoongArch(_) => cb(self), - Self::Mips(_) => cb(self), - Self::S390x(_) => cb(self), - Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), -@@ -406,6 +417,7 @@ pub enum InlineAsmRegClass { - Nvptx(NvptxInlineAsmRegClass), - PowerPC(PowerPCInlineAsmRegClass), - Hexagon(HexagonInlineAsmRegClass), -+ LoongArch(LoongArchInlineAsmRegClass), - Mips(MipsInlineAsmRegClass), - S390x(S390xInlineAsmRegClass), - SpirV(SpirVInlineAsmRegClass), -@@ -427,6 +439,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.name(), - Self::PowerPC(r) => r.name(), - Self::Hexagon(r) => r.name(), -+ Self::LoongArch(r) => r.name(), - Self::Mips(r) => r.name(), - Self::S390x(r) => r.name(), - Self::SpirV(r) => r.name(), -@@ -450,6 +463,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), - Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), - Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), -+ Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch), - Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), - Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), - Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), -@@ -480,6 +494,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.suggest_modifier(arch, ty), - Self::PowerPC(r) => r.suggest_modifier(arch, ty), - Self::Hexagon(r) => r.suggest_modifier(arch, ty), -+ Self::LoongArch(r) => r.suggest_modifier(arch, ty), - Self::Mips(r) => r.suggest_modifier(arch, ty), - Self::S390x(r) => r.suggest_modifier(arch, ty), - Self::SpirV(r) => r.suggest_modifier(arch, ty), -@@ -506,6 +521,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.default_modifier(arch), - Self::PowerPC(r) => r.default_modifier(arch), - Self::Hexagon(r) => r.default_modifier(arch), -+ Self::LoongArch(r) => r.default_modifier(arch), - Self::Mips(r) => r.default_modifier(arch), - Self::S390x(r) => r.default_modifier(arch), - Self::SpirV(r) => r.default_modifier(arch), -@@ -531,6 +547,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.supported_types(arch), - Self::PowerPC(r) => r.supported_types(arch), - Self::Hexagon(r) => r.supported_types(arch), -+ Self::LoongArch(r) => r.supported_types(arch), - Self::Mips(r) => r.supported_types(arch), - Self::S390x(r) => r.supported_types(arch), - Self::SpirV(r) => r.supported_types(arch), -@@ -557,6 +574,7 @@ impl InlineAsmRegClass { - Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?) - } - InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?), -+ InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmRegClass::parse(name)?), - InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - Self::Mips(MipsInlineAsmRegClass::parse(name)?) - } -@@ -582,6 +600,7 @@ impl InlineAsmRegClass { - Self::Nvptx(r) => r.valid_modifiers(arch), - Self::PowerPC(r) => r.valid_modifiers(arch), - Self::Hexagon(r) => r.valid_modifiers(arch), -+ Self::LoongArch(r) => r.valid_modifiers(arch), - Self::Mips(r) => r.valid_modifiers(arch), - Self::S390x(r) => r.valid_modifiers(arch), - Self::SpirV(r) => r.valid_modifiers(arch), -@@ -740,6 +759,11 @@ pub fn allocatable_registers( - hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map); - map - } -+ InlineAsmArch::LoongArch64 => { -+ let mut map = loongarch::regclass_map(); -+ loongarch::fill_reg_map(arch, reloc_model, target_features, target, &mut map); -+ map -+ } - InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - let mut map = mips::regclass_map(); - mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map); -@@ -788,6 +812,7 @@ pub enum InlineAsmClobberAbi { - AArch64, - AArch64NoX18, - RiscV, -+ LoongArch, - } - - impl InlineAsmClobberAbi { -@@ -829,6 +854,10 @@ impl InlineAsmClobberAbi { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), - _ => Err(&["C", "system", "efiapi"]), - }, -+ InlineAsmArch::LoongArch64 => match name { -+ "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::LoongArch), -+ _ => Err(&["C", "system", "efiapi"]), -+ }, - _ => Err(&[]), - } - } -@@ -971,6 +1000,21 @@ impl InlineAsmClobberAbi { - v24, v25, v26, v27, v28, v29, v30, v31, - } - }, -+ InlineAsmClobberAbi::LoongArch => clobbered_regs! { -+ LoongArch LoongArchInlineAsmReg { -+ // ra -+ r1, -+ // a0-a7 -+ r4, r5, r6, r7, r8, r9, r10, r11, -+ // t0-t8 -+ r12, r13, r14, r15, r16, r17, r18, r19, r20, -+ // fa0-fa7 -+ f0, f1, f2, f3, f4, f5, f6, f7, -+ // ft0-ft15 -+ f8, f9, f10, f11, f12, f13, f14, f15, -+ f16, f17, f18, f19, f20, f21, f22, f23, -+ } -+ }, - } - } - } -diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs -new file mode 100644 -index 000000000..4dc785dac ---- /dev/null -+++ b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs -@@ -0,0 +1,18 @@ -+use crate::spec::{Target, TargetOptions}; -+ -+pub fn target() -> Target { -+ Target { -+ llvm_target: "loongarch64-unknown-linux-gnu".into(), -+ pointer_width: 64, -+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), -+ arch: "loongarch64".into(), -+ options: TargetOptions { -+ abi: "abilp64".into(), -+ cpu: "la464".into(), -+ max_atomic_width: Some(64), -+ llvm_abiname: "lp64".into(), -+ -+ ..super::linux_gnu_base::opts() -+ }, -+ } -+} -diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs -index 8909cf33a..5f43e4faa 100644 ---- a/compiler/rustc_target/src/spec/mod.rs -+++ b/compiler/rustc_target/src/spec/mod.rs -@@ -1245,6 +1245,8 @@ supported_targets! { - ("x86_64-unknown-none", x86_64_unknown_none), - - ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), -+ -+ ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu), - } - - /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> -diff --git a/library/std/src/env.rs b/library/std/src/env.rs -index 6eb7cbea6..d149d7cda 100644 ---- a/library/std/src/env.rs -+++ b/library/std/src/env.rs -@@ -888,6 +888,7 @@ pub mod consts { - /// - x86_64 - /// - arm - /// - aarch64 -+ /// - loongarch64 - /// - m68k - /// - mips - /// - mips64 -diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs -index c73791d14..4d0607d19 100644 ---- a/library/std/src/os/linux/raw.rs -+++ b/library/std/src/os/linux/raw.rs -@@ -232,6 +232,7 @@ mod arch { - } - - #[cfg(any( -+ target_arch = "loongarch64", - target_arch = "mips64", - target_arch = "s390x", - target_arch = "sparc64", -diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs -index 7f0b0439c..047aa07df 100644 ---- a/library/std/src/personality/gcc.rs -+++ b/library/std/src/personality/gcc.rs -@@ -76,6 +76,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 - #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] - const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 - -+#[cfg(target_arch = "loongarch64")] -+const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 -+ - // The following code is based on GCC's C and C++ personality routines. For reference, see: - // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc - // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c -diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs -index e8e7c51cb..3b0c6d4a2 100644 ---- a/library/std/src/sys/common/alloc.rs -+++ b/library/std/src/sys/common/alloc.rs -@@ -24,6 +24,7 @@ pub const MIN_ALIGN: usize = 8; - target_arch = "mips64", - target_arch = "s390x", - target_arch = "sparc64", -+ target_arch = "loongarch64", - target_arch = "riscv64", - target_arch = "wasm64", - )))] -diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs -index a5b6193b0..2da4dc286 100644 ---- a/library/unwind/src/libunwind.rs -+++ b/library/unwind/src/libunwind.rs -@@ -69,6 +69,9 @@ pub const unwinder_private_data_size: usize = 20; - #[cfg(all(target_arch = "hexagon", target_os = "linux"))] - pub const unwinder_private_data_size: usize = 35; - -+#[cfg(target_arch = "loongarch64")] -+pub const unwinder_private_data_size: usize = 2; -+ - #[repr(C)] - pub struct _Unwind_Exception { - pub exception_class: _Unwind_Exception_Class, -diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py -index 57128685d..93d53b2a3 100644 ---- a/src/bootstrap/bootstrap.py -+++ b/src/bootstrap/bootstrap.py -@@ -303,6 +303,7 @@ def default_build_triple(verbose): - 'i486': 'i686', - 'i686': 'i686', - 'i786': 'i686', -+ 'loongarch64': 'loongarch64', - 'm68k': 'm68k', - 'powerpc': 'powerpc', - 'powerpc64': 'powerpc64', -diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs -index 7e70e99bb..52cb9dc77 100644 ---- a/src/bootstrap/lib.rs -+++ b/src/bootstrap/lib.rs -@@ -213,7 +213,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] - ( - Some(Mode::Std), - "target_arch", -- Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa"]), -+ Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa", "loongarch64"]), - ), - /* Extra names used by dependencies */ - // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set -diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs -index 2f856c276..7c4da4d23 100644 ---- a/src/bootstrap/native.rs -+++ b/src/bootstrap/native.rs -@@ -357,7 +357,7 @@ impl Step for Llvm { - let llvm_targets = match &builder.config.llvm_targets { - Some(s) => s, - None => { -- "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\ -+ "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\ - Sparc;SystemZ;WebAssembly;X86" - } - }; -diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml -index 10de2e8d5..b34437f01 100644 ---- a/src/ci/github-actions/ci.yml -+++ b/src/ci/github-actions/ci.yml -@@ -346,6 +346,9 @@ jobs: - - name: dist-i686-linux - <<: *job-linux-xl - -+ - name: dist-loongarch64-linux -+ <<: *job-linux-xl -+ - - name: dist-mips-linux - <<: *job-linux-xl - -diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md -index a36518cc8..3724253a8 100644 ---- a/src/doc/rustc/src/platform-support.md -+++ b/src/doc/rustc/src/platform-support.md -@@ -86,6 +86,7 @@ target | notes - `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17) - `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17) - `armv7-unknown-linux-gnueabihf` | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17) -+`loongarch64-unknown-linux-gnu` | LOONGARCH64 Linux (kernel 4.19, glibc 2.28) - `mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23) - `mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23) - `mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23) -diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs -index f33f5d27d..11f713419 100644 ---- a/src/librustdoc/clean/cfg.rs -+++ b/src/librustdoc/clean/cfg.rs -@@ -515,6 +515,7 @@ impl<'a> fmt::Display for Display<'a> { - "aarch64" => "AArch64", - "arm" => "ARM", - "asmjs" => "JavaScript", -+ "loongarch64" => "LoongArch64", - "m68k" => "M68k", - "mips" => "MIPS", - "mips64" => "MIPS-64", -diff --git a/src/test/assembly/asm/loongarch-types.rs b/src/test/assembly/asm/loongarch-types.rs -new file mode 100644 -index 000000000..9c116f730 ---- /dev/null -+++ b/src/test/assembly/asm/loongarch-types.rs -@@ -0,0 +1,194 @@ -+// min-llvm-version: 10.0.1 -+// assembly-output: emit-asm -+// compile-flags: --target loongarch64-unknown-linux-gnu -+// needs-llvm-components: loongarch -+ -+#![feature(no_core, lang_items, rustc_attrs, asm_sym)] -+#![crate_type = "rlib"] -+#![no_core] -+#![allow(asm_sub_register)] -+ -+#[rustc_builtin_macro] -+macro_rules! asm { -+ () => {}; -+} -+#[rustc_builtin_macro] -+macro_rules! concat { -+ () => {}; -+} -+#[rustc_builtin_macro] -+macro_rules! stringify { -+ () => {}; -+} -+ -+#[lang = "sized"] -+trait Sized {} -+#[lang = "copy"] -+trait Copy {} -+ -+type ptr = *const i32; -+ -+impl Copy for i8 {} -+impl Copy for i16 {} -+impl Copy for i32 {} -+impl Copy for i64 {} -+impl Copy for f32 {} -+impl Copy for f64 {} -+impl Copy for ptr {} -+extern "C" { -+ fn extern_func(); -+ static extern_static: u8; -+} -+ -+// Hack to avoid function merging -+extern "Rust" { -+ fn dont_merge(s: &str); -+} -+ -+// CHECK-LABEL: sym_fn: -+// CHECK: #APP -+// CHECK: la.got $r12, extern_func -+// CHECK: #NO_APP -+#[no_mangle] -+pub unsafe fn sym_fn() { -+ asm!("la.got $r12, {}", sym extern_func); -+} -+ -+// CHECK-LABEL: sym_static: -+// CHECK: #APP -+// CHECK: la.got $r12, extern_static -+// CHECK: #NO_APP -+#[no_mangle] -+pub unsafe fn sym_static() { -+ asm!("la.got $r12, {}", sym extern_static); -+} -+ -+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { -+ #[no_mangle] -+ pub unsafe fn $func(x: $ty) -> $ty { -+ dont_merge(stringify!($func)); -+ -+ let y; -+ asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); -+ y -+ } -+};} -+ -+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { -+ #[no_mangle] -+ pub unsafe fn $func(x: $ty) -> $ty { -+ dont_merge(stringify!($func)); -+ -+ let y; -+ asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); -+ y -+ } -+};} -+ -+// CHECK-LABEL: reg_i8: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_i8, i8, reg, "move"); -+ -+// CHECK-LABEL: reg_i16: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_i16, i16, reg, "move"); -+ -+// CHECK-LABEL: reg_i32: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_i32, i32, reg, "move"); -+ -+// CHECK-LABEL: reg_f32: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_f32, f32, reg, "move"); -+ -+// CHECK-LABEL: reg_i64: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_i64, i64, reg, "move"); -+ -+// CHECK-LABEL: reg_f64: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_f64, f64, reg, "move"); -+ -+// CHECK-LABEL: reg_ptr: -+// CHECK: #APP -+// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} -+// CHECK: #NO_APP -+check!(reg_ptr, ptr, reg, "move"); -+ -+// CHECK-LABEL: freg_f32: -+// CHECK: #APP -+// CHECK: fmov.s $f{{[0-9]+}}, $f{{[0-9]+}} -+// CHECK: #NO_APP -+check!(freg_f32, f32, freg, "fmov.s"); -+ -+// CHECK-LABEL: freg_f64: -+// CHECK: #APP -+// CHECK: fmov.d $f{{[0-9]+}}, $f{{[0-9]+}} -+// CHECK: #NO_APP -+check!(freg_f64, f64, freg, "fmov.d"); -+ -+// CHECK-LABEL: r4_i8: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_i8, i8, "$r4", "move"); -+ -+// CHECK-LABEL: r4_i16: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_i16, i16, "$r4", "move"); -+ -+// CHECK-LABEL: r4_i32: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_i32, i32, "$r4", "move"); -+ -+// CHECK-LABEL: r4_f32: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_f32, f32, "$r4", "move"); -+ -+// CHECK-LABEL: r4_i64: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_i64, i64, "$r4", "move"); -+ -+// CHECK-LABEL: r4_f64: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_f64, f64, "$r4", "move"); -+ -+// CHECK-LABEL: r4_ptr: -+// CHECK: #APP -+// CHECK: move $r4, $r4 -+// CHECK: #NO_APP -+check_reg!(r4_ptr, ptr, "$r4", "move"); -+ -+// CHECK-LABEL: f0_f32: -+// CHECK: #APP -+// CHECK: fmov.s $f{{[0-9]+}}, $f{{[0-9]+}} -+// CHECK: #NO_APP -+check_reg!(f0_f32, f32, "$f0", "fmov.s"); -+ -+// CHECK-LABEL: f0_f64: -+// CHECK: #APP -+// CHECK: fmov.d $f{{[0-9]+}}, $f{{[0-9]+}} -+// CHECK: #NO_APP -+check_reg!(f0_f64, f64, "$f0", "fmov.d"); -diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs -index 4ed491dfb..1b79aa221 100644 ---- a/src/test/codegen/abi-main-signature-16bit-c-int.rs -+++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs -@@ -6,6 +6,7 @@ - // ignore-arm - // ignore-asmjs - // ignore-hexagon -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-powerpc -diff --git a/src/test/codegen/call-llvm-intrinsics.rs b/src/test/codegen/call-llvm-intrinsics.rs -index 998099c23..77a11ad9f 100644 ---- a/src/test/codegen/call-llvm-intrinsics.rs -+++ b/src/test/codegen/call-llvm-intrinsics.rs -@@ -1,6 +1,7 @@ - // compile-flags: -C no-prepopulate-passes - - // ignore-riscv64 -+// ignore-loongarch64 - - #![feature(link_llvm_intrinsics)] - #![crate_type = "lib"] -diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs -index fab84868f..ab47178b0 100644 ---- a/src/test/codegen/global_asm.rs -+++ b/src/test/codegen/global_asm.rs -@@ -6,6 +6,7 @@ - // ignore-bpfel - // ignore-bpfeb - // ignore-hexagon -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-msp430 -diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs -index 02ee91645..0eaecfde5 100644 ---- a/src/test/codegen/global_asm_include.rs -+++ b/src/test/codegen/global_asm_include.rs -@@ -6,6 +6,7 @@ - // ignore-bpfel - // ignore-bpfeb - // ignore-hexagon -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-msp430 -diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs -index bdcf0ea84..de2b03336 100644 ---- a/src/test/codegen/global_asm_x2.rs -+++ b/src/test/codegen/global_asm_x2.rs -@@ -6,6 +6,7 @@ - // ignore-bpfel - // ignore-bpfeb - // ignore-hexagon -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-msp430 -diff --git a/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs b/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs -new file mode 100644 -index 000000000..bfc4620d8 ---- /dev/null -+++ b/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs -@@ -0,0 +1,30 @@ -+// compile-flags: -C no-prepopulate-passes -+ -+// only-loongarch64 -+ -+#![feature(link_llvm_intrinsics)] -+#![crate_type = "lib"] -+ -+struct A; -+ -+impl Drop for A { -+ fn drop(&mut self) { -+ println!("A"); -+ } -+} -+ -+extern "C" { -+ #[link_name = "llvm.sqrt.f32"] -+ fn sqrt(x: f32) -> f32; -+} -+ -+pub fn do_call() { -+ let _a = A; -+ -+ unsafe { -+ // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them -+ // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4 -+ // CHECK: call float @llvm.sqrt.f32(float %{{.}} -+ sqrt(4.0); -+ } -+} -diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs -index 9d18c5f03..97ce1ccbd 100644 ---- a/src/test/codegen/repr-transparent-aggregates-1.rs -+++ b/src/test/codegen/repr-transparent-aggregates-1.rs -@@ -3,6 +3,7 @@ - - // ignore-arm - // ignore-aarch64 -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-powerpc -diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs -index df7e88f08..09ee567cd 100644 ---- a/src/test/codegen/repr-transparent-aggregates-2.rs -+++ b/src/test/codegen/repr-transparent-aggregates-2.rs -@@ -4,6 +4,7 @@ - // ignore-aarch64 - // ignore-emscripten - // ignore-mips64 -+// ignore-loongarch64 - // ignore-powerpc - // ignore-powerpc64 - // ignore-powerpc64le -diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs -index c68ba8460..5d5ebfc4b 100644 ---- a/src/test/codegen/repr-transparent.rs -+++ b/src/test/codegen/repr-transparent.rs -@@ -2,6 +2,7 @@ - - // ignore-riscv64 riscv64 has an i128 type used with test_Vector - // see codegen/riscv-abi for riscv functiona call tests -+// ignore-loongarch64 - - #![crate_type="lib"] - #![feature(repr_simd, transparent_unions)] -diff --git a/src/test/run-make-fulldeps/atomic-lock-free/Makefile b/src/test/run-make-fulldeps/atomic-lock-free/Makefile -index 37e59624a..dcca7f8f7 100644 ---- a/src/test/run-make-fulldeps/atomic-lock-free/Makefile -+++ b/src/test/run-make-fulldeps/atomic-lock-free/Makefile -@@ -25,6 +25,10 @@ ifeq ($(filter aarch64,$(LLVM_COMPONENTS)),aarch64) - $(RUSTC) --target=aarch64-unknown-linux-gnu atomic_lock_free.rs - nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add - endif -+ifeq ($(filter loongarch64,$(LLVM_COMPONENTS)),loongarch64) -+ $(RUSTC) --target=loongarch64-unknown-linux-gnu atomic_lock_free.rs -+ nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add -+endif - ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips) - $(RUSTC) --target=mips-unknown-linux-gnu atomic_lock_free.rs - nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add -diff --git a/src/test/ui/abi/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs -index 6d934538f..e1b89d950 100644 ---- a/src/test/ui/abi/stack-probes-lto.rs -+++ b/src/test/ui/abi/stack-probes-lto.rs -@@ -1,6 +1,7 @@ - // run-pass - // ignore-arm - // ignore-aarch64 -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-sparc -diff --git a/src/test/ui/cfg/conditional-compile-arch.rs b/src/test/ui/cfg/conditional-compile-arch.rs -index 7de561df1..34172b8c9 100644 ---- a/src/test/ui/cfg/conditional-compile-arch.rs -+++ b/src/test/ui/cfg/conditional-compile-arch.rs -@@ -13,6 +13,9 @@ pub fn main() { } - #[cfg(target_arch = "aarch64")] - pub fn main() { } - -+#[cfg(target_arch = "loongarch64")] -+pub fn main() { } -+ - #[cfg(target_arch = "mips")] - pub fn main() { } - -diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr -index 9864aa385..5ca4d3b3d 100644 ---- a/src/test/ui/check-cfg/compact-values.stderr -+++ b/src/test/ui/check-cfg/compact-values.stderr -@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value - LL | #[cfg(target(os = "linux", arch = "X"))] - | ^^^^^^^^^^ - | -- = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 -+ = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, loongarch64, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 - = note: `#[warn(unexpected_cfgs)]` on by default - - warning: 1 warning emitted -diff --git a/src/test/ui/process/nofile-limit.rs b/src/test/ui/process/nofile-limit.rs -index 3ddf8d6ef..79a6be731 100644 ---- a/src/test/ui/process/nofile-limit.rs -+++ b/src/test/ui/process/nofile-limit.rs -@@ -1,7 +1,8 @@ - // Check that statically linked binary executes successfully - // with RLIMIT_NOFILE resource lowered to zero. Regression - // test for issue #96621. --// -+// loongarch64 has no setrlimit -+// ignore-loongarch64 - // run-pass - // dont-check-compiler-stderr - // only-linux -diff --git a/src/test/ui/target-feature/gate.rs b/src/test/ui/target-feature/gate.rs -index 2382c98f8..15d1af6f7 100644 ---- a/src/test/ui/target-feature/gate.rs -+++ b/src/test/ui/target-feature/gate.rs -@@ -2,6 +2,7 @@ - // ignore-aarch64 - // ignore-wasm - // ignore-emscripten -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-powerpc -@@ -28,6 +29,7 @@ - // gate-test-ermsb_target_feature - // gate-test-bpf_target_feature - // gate-test-aarch64_ver_target_feature -+// gate-test-loongarch64_target_feature - - #[target_feature(enable = "avx512bw")] - //~^ ERROR: currently unstable -diff --git a/src/test/ui/target-feature/invalid-attribute.rs b/src/test/ui/target-feature/invalid-attribute.rs -index ad1b6e96b..040f3a365 100644 ---- a/src/test/ui/target-feature/invalid-attribute.rs -+++ b/src/test/ui/target-feature/invalid-attribute.rs -@@ -2,6 +2,7 @@ - // ignore-aarch64 - // ignore-wasm - // ignore-emscripten -+// ignore-loongarch64 - // ignore-mips - // ignore-mips64 - // ignore-powerpc -diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs -index b0006cb90..0c2b4b1ed 100644 ---- a/src/tools/build-manifest/src/main.rs -+++ b/src/tools/build-manifest/src/main.rs -@@ -28,6 +28,7 @@ static HOSTS: &[&str] = &[ - "i686-pc-windows-gnu", - "i686-pc-windows-msvc", - "i686-unknown-linux-gnu", -+ "loongarch64-unknown-linux-gnu", - "mips-unknown-linux-gnu", - "mips64-unknown-linux-gnuabi64", - "mips64el-unknown-linux-gnuabi64", -@@ -99,6 +100,7 @@ static TARGETS: &[&str] = &[ - "i686-unknown-freebsd", - "i686-unknown-linux-gnu", - "i686-unknown-linux-musl", -+ "loongarch64-unknown-linux-gnu", - "m68k-unknown-linux-gnu", - "mips-unknown-linux-gnu", - "mips-unknown-linux-musl", -diff --git a/src/tools/clippy/tests/ui/asm_syntax.rs b/src/tools/clippy/tests/ui/asm_syntax.rs -index 0220bf333..03748de7b 100644 ---- a/src/tools/clippy/tests/ui/asm_syntax.rs -+++ b/src/tools/clippy/tests/ui/asm_syntax.rs -@@ -1,5 +1,6 @@ - // only-x86_64 - // ignore-aarch64 -+// ignore-loongarch64 - - #[warn(clippy::inline_asm_x86_intel_syntax)] - mod warn_intel { -diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs -index 0260f6848..f4fb9fcdf 100644 ---- a/src/tools/compiletest/src/common.rs -+++ b/src/tools/compiletest/src/common.rs -@@ -430,7 +430,7 @@ impl Config { - pub fn has_asm_support(&self) -> bool { - static ASM_SUPPORTED_ARCHS: &[&str] = &[ - "x86", "x86_64", "arm", "aarch64", "riscv32", -- "riscv64", -+ "riscv64", "loongarch64", - // These targets require an additional asm_experimental_arch feature. - // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32", - ]; --- -2.41.0 - diff --git a/download b/download index 97f70e9..0f1c6ac 100644 --- a/download +++ b/download @@ -1,2 +1,2 @@ -96b082a8b44707eafa9d696923f40c28 rustc-1.66.1-src.tar.xz -a38646f7beb7f905a6ef7a8cc2315a77 wasi-libc-wasi-sdk-17.tar.gz +b6f9973de878e37a589f0989e4138480 rustc-1.71.1-src.tar.xz +4c63bd9552e0a694d70201bdad011ca5 wasi-libc-wasi-sdk-20.tar.gz diff --git a/rust.spec b/rust.spec index fb1829c..a6c5c42 100644 --- a/rust.spec +++ b/rust.spec @@ -1,6 +1,6 @@ -# Only x86_64 and i686 are Tier 1 platforms at this time. +# Only x86_64, i686, and aarch64 are Tier 1 platforms at this time. # https://doc.rust-lang.org/nightly/rustc/platform-support.html -%global rust_arches x86_64 i686 aarch64 ppc64le s390x loongarch64 +%global rust_arches x86_64 i686 aarch64 ppc64le s390x # The channel can be stable, beta, or nightly %{!?channel: %global channel stable} @@ -8,9 +8,9 @@ # To bootstrap from scratch, set the channel and date from src/stage0.json # e.g. 1.59.0 wants rustc: 1.58.0-2022-01-13 # or nightly wants some beta-YYYY-MM-DD -%global bootstrap_version 1.65.0 -%global bootstrap_channel 1.65.0 -%global bootstrap_date 2022-11-03 +%global bootstrap_version 1.70.0 +%global bootstrap_channel 1.70.0 +%global bootstrap_date 2023-06-01 # Only the specified arches will use bootstrap binaries. # NOTE: Those binaries used to be uploaded with every new release, but that was @@ -39,7 +39,7 @@ # src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh # (updated per https://github.com/rust-lang/rust/pull/96907) %global wasi_libc_url https://github.com/WebAssembly/wasi-libc -%global wasi_libc_ref wasi-sdk-17 +%global wasi_libc_ref wasi-sdk-20 %global wasi_libc_name wasi-libc-%{wasi_libc_ref} %global wasi_libc_source %{wasi_libc_url}/archive/%{wasi_libc_ref}/%{wasi_libc_name}.tar.gz %global wasi_libc_dir %{_builddir}/%{wasi_libc_name} @@ -48,17 +48,17 @@ %bcond_with llvm_static # We can also choose to just use Rust's bundled LLVM, in case the system LLVM -# is insufficient. Rust currently requires LLVM 12.0+. -%global min_llvm_version 13.0.0 -%global bundled_llvm_version 15.0.2 +# is insufficient. Rust currently requires LLVM 14.0+. +%global min_llvm_version 14.0.0 +%global bundled_llvm_version 16.0.5 %bcond_with bundled_llvm -# Requires stable libgit2 1.5, and not the next minor soname change. +# Requires stable libgit2 1.6, and not the next minor soname change. # This needs to be consistent with the bindings in vendor/libgit2-sys. -%global min_libgit2_version 1.5.0 -%global next_libgit2_version 1.6.0~ -%global bundled_libgit2_version 1.5.0 -%if 0%{?fedora} >= 99 +%global min_libgit2_version 1.6.4 +%global next_libgit2_version 1.7.0~ +%global bundled_libgit2_version 1.6.4 +%if 0%{?fedora} >= 38 %bcond_with bundled_libgit2 %else %bcond_without bundled_libgit2 @@ -87,8 +87,8 @@ %endif Name: rust -Version: 1.66.1 -Release: 3%{?dist} +Version: 1.71.1 +Release: 1%{?dist} Summary: The Rust Programming Language License: (ASL 2.0 or MIT) and (BSD and MIT) # ^ written as: (rust itself) and (bundled libraries) @@ -108,16 +108,18 @@ Source1: %{wasi_libc_source} Patch1: 0001-Use-lld-provided-by-system-for-wasm.patch # Set a substitute-path in rust-gdb for standard library sources. -Patch2: rustc-1.61.0-rust-gdb-substitute-path.patch +Patch2: rustc-1.70.0-rust-gdb-substitute-path.patch -# https://github.com/rust-lang/rust/pull/103072 -Patch3: 0001-compiletest-set-the-dylib-path-when-gathering-target.patch +# Override default target CPUs to match distro settings +# TODO: upstream this ability into the actual build configuration +Patch3: 0001-Let-environment-variables-override-some-default-CPUs.patch -# https://github.com/rust-lang/rust/pull/104001 -Patch4: 0001-Improve-generating-Custom-entry-function.patch +# Enable the profiler runtime for native hosts +# https://github.com/rust-lang/rust/pull/114069 +Patch4: 0001-Allow-using-external-builds-of-the-compiler-rt-profi.patch -# https://github.com/rust-lang/rust/pull/105468 -Patch5: 0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch +# https://github.com/rust-lang/rust/pull/114440 +Patch5: 0001-bootstrap-config-fix-version-comparison-bug.patch ### RHEL-specific patches below ### @@ -125,26 +127,11 @@ Patch5: 0001-Mangle-main-as-__main_void-on-wasm32-wasi.patch Source100: macros.rust-toolset # Disable cargo->libgit2->libssh2 on RHEL, as it's not approved for FIPS (rhbz1732949) -Patch100: rustc-1.65.0-disable-libssh2.patch +Patch100: rustc-1.71.0-disable-libssh2.patch # libcurl on RHEL7 doesn't have http2, but since cargo requests it, curl-sys # will try to build it statically -- instead we turn off the feature. -Patch101: rustc-1.65.0-disable-http2.patch - -# kernel rh1410097 causes too-small stacks for PIE. -# (affects RHEL6 kernels when building for RHEL7) -Patch102: rustc-1.65.0-no-default-pie.patch - -Patch1000: 0001-cargo-CVE-2023-38497.patch -Patch1001: 0001-update-vendor-tar-to-0.4.39.patch - -#patch for loongarch64 -Patch103: 0001-vendor-cc-add-loongarch64-support.patch -Patch104: 0002-vendor-libc-update-loongarch64-support.patch -Patch105: 0003-vendor-psm-add-loongarch64-support.patch -Patch106: 0004-vendor-object-add-loongarch64-support.patch -Patch107: 0005-llvm-update-loongarch64-support.patch -Patch108: 0006-rust-add-loongarch64-support.patch +Patch101: rustc-1.71.0-disable-http2.patch # Get the Rust triple for any arch. %{lua: function rust_triple(arch) @@ -162,7 +149,14 @@ Patch108: 0006-rust-add-loongarch64-support.patch return arch.."-unknown-linux-"..abi end} +# Get the environment form of a Rust triple +%{lua: function rust_triple_env(triple) + local sub = string.gsub(triple, "-", "_") + return string.upper(sub) +end} + %global rust_triple %{lua: print(rust_triple(rpm.expand("%{_target_cpu}")))} +%global rust_triple_env %{lua: print(rust_triple_env(rpm.expand("%{rust_triple}")))} %if %defined bootstrap_arches # For each bootstrap arch, add an additional binary Source. @@ -238,7 +232,7 @@ Provides: bundled(llvm) = %{bundled_llvm_version} %else BuildRequires: cmake >= 2.8.11 %if 0%{?epel} == 7 -%global llvm llvm13 +%global llvm llvm14 %endif %if %defined llvm %global llvm_root %{_libdir}/%{llvm} @@ -275,7 +269,7 @@ Requires: %{name}-std-static%{?_isa} = %{version}-%{release} Requires: /usr/bin/cc %if 0%{?epel} == 7 -%global devtoolset_name devtoolset-9 +%global devtoolset_name devtoolset-11 BuildRequires: %{devtoolset_name}-binutils BuildRequires: %{devtoolset_name}-gcc BuildRequires: %{devtoolset_name}-gcc-c++ @@ -340,6 +334,15 @@ find '%{buildroot}%{rustlibdir}'/wasm*/lib -type f -regex '.*\\.\\(a\\|rlib\\)' %{nil} %endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +# For profiler_builtins +BuildRequires: compiler-rt +%endif + +# This component was removed as of Rust 1.69.0. +# https://github.com/rust-lang/rust/pull/101841 +Obsoletes: %{name}-analysis < 1.69.0~ + %description Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety. @@ -349,8 +352,9 @@ This package includes the Rust compiler and documentation generator. %package std-static Summary: Standard library for Rust +Provides: %{name}-std-static-%{rust_triple} = %{version}-%{release} Requires: %{name} = %{version}-%{release} -Requires: glibc-devel%{?_isa} >= 2.11 +Requires: glibc-devel%{?_isa} >= 2.17 %description std-static This package includes the standard libraries for building applications @@ -554,26 +558,13 @@ This package includes source files for the Rust standard library. It may be useful as a reference for code completion tools in various editors. -%package analysis -Summary: Compiler analysis data for the Rust standard library -%if 0%{?rhel} && 0%{?rhel} < 8 -Requires: %{name}-std-static%{?_isa} = %{version}-%{release} -%else -Recommends: %{name}-std-static%{?_isa} = %{version}-%{release} -%endif - -%description analysis -This package contains analysis data files produced with rustc's -Zsave-analysis -feature for the Rust standard library. The RLS (Rust Language Server) uses this -data to provide information about the Rust standard library. - - -%if 0%{?rhel} && 0%{?rhel} >= 8 +%if 0%{?rhel} %package toolset Summary: Rust Toolset -Requires: rust%{?_isa} = %{version}-%{release} -Requires: cargo%{?_isa} = %{version}-%{release} +BuildArch: noarch +Requires: rust = %{version}-%{release} +Requires: cargo = %{version}-%{release} %description toolset This is the metapackage for Rust Toolset, bringing in the Rust compiler, @@ -602,35 +593,21 @@ test -f '%{local_rust_root}/bin/rustc' %setup -q -n %{rustc_package} -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 +%patch -P1 -p1 +%patch -P2 -p1 +%patch -P3 -p1 +%patch -P4 -p1 +%patch -P5 -p1 %if %with disabled_libssh2 -%patch100 -p1 +%patch -P100 -p1 %endif %if %without curl_http2 -%patch101 -p1 -rm -rf vendor/libnghttp2-sys/ +%patch -P101 -p1 +rm -rf vendor/libnghttp2-sys*/ %endif -%if 0%{?rhel} && 0%{?rhel} < 8 -%patch102 -p1 -%endif - -%patch1000 -p1 -%patch1001 -p1 - -%patch103 -p1 -%patch104 -p1 -%patch105 -p1 -%patch106 -p1 -%patch107 -p1 -%patch108 -p1 - # Use our explicit python3 first sed -i.try-python -e '/^try python3 /i try "%{__python3}" "$@"' ./configure @@ -643,21 +620,21 @@ mkdir -p src/llvm-project/libunwind/ %endif # Remove other unused vendored libraries -rm -rf vendor/curl-sys/curl/ +rm -rf vendor/curl-sys*/curl/ rm -rf vendor/*jemalloc-sys*/jemalloc/ -rm -rf vendor/libmimalloc-sys/c_src/mimalloc/ -rm -rf vendor/libssh2-sys/libssh2/ -rm -rf vendor/libz-sys/src/zlib/ -rm -rf vendor/libz-sys/src/zlib-ng/ -rm -rf vendor/lzma-sys/xz-*/ -rm -rf vendor/openssl-src/openssl/ +rm -rf vendor/libffi-sys*/libffi/ +rm -rf vendor/libmimalloc-sys*/c_src/mimalloc/ +rm -rf vendor/libssh2-sys*/libssh2/ +rm -rf vendor/libz-sys*/src/zlib{,-ng}/ +rm -rf vendor/lzma-sys*/xz-*/ +rm -rf vendor/openssl-src*/openssl/ %if %without bundled_libgit2 -rm -rf vendor/libgit2-sys/libgit2/ +rm -rf vendor/libgit2-sys*/libgit2/ %endif %if %with disabled_libssh2 -rm -rf vendor/libssh2-sys/ +rm -rf vendor/libssh2-sys*/ %endif # This only affects the transient rust-installer, but let it use our dynamic xz-libs @@ -686,9 +663,28 @@ find vendor -name .cargo-checksum.json \ # it's a shebang and make them executable. Then brp-mangle-shebangs gets upset... find -name '*.rs' -type f -perm /111 -exec chmod -v -x '{}' '+' +# The distro flags are only appropriate for the host, not our cross-targets, +# and they're not as fine-grained as the settings we choose for std vs rustc. +%if %defined build_rustflags +%global build_rustflags %{nil} +%endif + +# These are similar to __cflags_arch_* in /usr/lib/rpm/redhat/macros +%{lua: function rustc_target_cpus() + local fedora = tonumber(rpm.expand("0%{?fedora}")) + local rhel = tonumber(rpm.expand("0%{?rhel}")) + local env = + " RUSTC_TARGET_CPU_X86_64=x86-64" .. ((rhel >= 10) and "-v3" or (rhel == 9) and "-v2" or "") + .. " RUSTC_TARGET_CPU_PPC64LE=" .. ((rhel >= 9) and "pwr9" or "pwr8") + .. " RUSTC_TARGET_CPU_S390X=" .. + ((rhel >= 9) and "z14" or (rhel == 8 or fedora >= 38) and "z13" or + (fedora >= 26) and "zEC12" or (rhel == 7) and "z196" or "z10") + return env +end} + # Set up shared environment variables for build/install/check -%global rust_env %{?rustflags:RUSTFLAGS="%{rustflags}"} -%if 0%{?cmake_path:1} +%global rust_env %{?rustflags:RUSTFLAGS="%{rustflags}"} %{lua: print(rustc_target_cpus())} +%if %defined cmake_path %global rust_env %{?rust_env} PATH="%{cmake_path}:$PATH" %endif %if %without disabled_libssh2 @@ -697,11 +693,10 @@ find -name '*.rs' -type f -perm /111 -exec chmod -v -x '{}' '+' %endif %global export_rust_env %{?rust_env:export %{rust_env}} - %build %{export_rust_env} -%ifarch %{arm} %{ix86} loongarch64 +%ifarch %{arm} %{ix86} # full debuginfo is exhausting memory; just do libstd for now # https://github.com/rust-lang/rust/issues/45854 %if 0%{?rhel} && 0%{?rhel} < 8 @@ -758,6 +753,12 @@ end} end} %endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +# The exact profiler path is version dependent, and uses LLVM-specific +# arch names in the filename, but this find is good enough for now... +PROFILER=$(find %{_libdir}/clang -type f -name 'libclang_rt.profile-*.a') +%endif + %configure --disable-option-checking \ --libdir=%{common_libdir} \ --build=%{rust_triple} --host=%{rust_triple} --target=%{rust_triple} \ @@ -766,6 +767,7 @@ end} --set target.%{rust_triple}.cxx=%{__cxx} \ --set target.%{rust_triple}.ar=%{__ar} \ --set target.%{rust_triple}.ranlib=%{__ranlib} \ + ${PROFILER:+--set target.%{rust_triple}.profiler="$PROFILER"} \ %{?mingw_target_config} \ %{?wasm_target_config} \ --python=%{__python3} \ @@ -783,7 +785,7 @@ end} --set build.install-stage=2 \ --set build.test-stage=2 \ --enable-extended \ - --tools=analysis,cargo,clippy,rls,rust-analyzer,rustfmt,src \ + --tools=cargo,clippy,rls,rust-analyzer,rustfmt,src \ --enable-vendor \ --enable-verbose-tests \ --dist-compression-formats=gz \ @@ -798,6 +800,9 @@ for triple in %{?mingw_targets} %{?wasm_targets}; do done %install +%if 0%{?rhel} && 0%{?rhel} <= 9 +%{?set_build_flags} +%endif %{export_rust_env} DESTDIR=%{buildroot} %{__python3} ./x.py install @@ -812,6 +817,9 @@ done # These are transient files used by x.py dist and install rm -rf ./build/dist/ ./build/tmp/ +# Some of the components duplicate-install binaries, leaving backups we don't want +rm -f %{buildroot}%{_bindir}/*.old + # Make sure the shared libraries are in the proper libdir %if "%{_libdir}" != "%{common_libdir}" mkdir -p %{buildroot}%{_libdir} @@ -878,13 +886,16 @@ rm -f %{buildroot}%{rustlibdir}/etc/lldb_* # We don't want Rust copies of LLVM tools (rust-lld, rust-llvm-dwp) rm -f %{buildroot}%{rustlibdir}/%{rust_triple}/bin/rust-ll* -%if 0%{?rhel} && 0%{?rhel} >= 8 +%if 0%{?rhel} # This allows users to build packages using Rust Toolset. %{__install} -D -m 644 %{S:100} %{buildroot}%{rpmmacrodir}/macros.rust-toolset %endif %check +%if 0%{?rhel} && 0%{?rhel} <= 9 +%{?set_build_flags} +%endif %{export_rust_env} # Sanity-check the installed binaries, debuginfo-stripped and all. @@ -902,7 +913,10 @@ done # The results are not stable on koji, so mask errors and just log it. # Some of the larger test artifacts are manually cleaned to save space. -timeout -v 90m %{__python3} ./x.py test --no-fail-fast || : + +# Bootstrap is excluded because it's not something we ship, and a lot of its +# tests are geared toward the upstream CI environment. +timeout -v 90m %{__python3} ./x.py test --no-fail-fast --exclude src/bootstrap || : rm -rf "./build/%{rust_triple}/test/" timeout -v 30m %{__python3} ./x.py test --no-fail-fast cargo || : @@ -1016,16 +1030,7 @@ end} %files doc %docdir %{_docdir}/%{name} %dir %{_docdir}/%{name} -%dir %{_docdir}/%{name}/html -%{_docdir}/%{name}/html/*/ -%{_docdir}/%{name}/html/*.html -%{_docdir}/%{name}/html/*.css -%{_docdir}/%{name}/html/*.js -%{_docdir}/%{name}/html/*.png -%{_docdir}/%{name}/html/*.svg -%{_docdir}/%{name}/html/*.woff2 -%license %{_docdir}/%{name}/html/*.txt -%license %{_docdir}/%{name}/html/*.md +%{_docdir}/%{name}/html # former cargo-doc %docdir %{_docdir}/cargo %dir %{_docdir}/cargo @@ -1070,22 +1075,36 @@ end} %{rustlibdir}/src -%files analysis -%{rustlibdir}/%{rust_triple}/analysis/ - - -%if 0%{?rhel} && 0%{?rhel} >= 8 +%if 0%{?rhel} %files toolset %{rpmmacrodir}/macros.rust-toolset %endif %changelog -* Tue Dec 19 2023 WANG Rui - 1.66.1-3 -- Add support for loongarch64. +* Tue Aug 08 2023 Josh Stone - 1.71.1-1 +- Update to 1.71.1. +- Security fix for CVE-2023-38497 + +* Wed Jul 26 2023 Josh Stone - 1.71.0-2 +- Relax the suspicious_double_ref_op lint (rhbz2225471) +- Enable the profiler runtime for native hosts (rhbz2213875) + +* Thu Jul 20 2023 Josh Stone - 1.71.0-1 +- Update to 1.71.0. + +* Tue Jul 18 2023 Josh Stone - 1.70.0-1 +- Update to 1.70.0. + +* Fri May 26 2023 Josh Stone - 1.69.0-1 +- Update to 1.69.0. +- Obsolete rust-analysis. + +* Fri May 19 2023 Josh Stone - 1.68.2-1 +- Update to 1.68.2. -* Wed Aug 16 2023 Liwei Ge - 1.66.1-2 -- Fix CVE-2023-38497 +* Thu May 18 2023 Josh Stone - 1.67.1-1 +- Update to 1.67.1. * Wed Jan 11 2023 Josh Stone - 1.66.1-1 - Update to 1.66.1. diff --git a/rustc-1.65.0-disable-libssh2.patch b/rustc-1.65.0-disable-libssh2.patch deleted file mode 100644 index 24be1f3..0000000 --- a/rustc-1.65.0-disable-libssh2.patch +++ /dev/null @@ -1,43 +0,0 @@ ---- rustc-beta-src/Cargo.lock.orig 2022-09-24 10:20:14.000000000 -0700 -+++ rustc-beta-src/Cargo.lock 2022-10-04 10:26:35.490270607 -0700 -@@ -1971,7 +1971,6 @@ - dependencies = [ - "cc", - "libc", -- "libssh2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", -@@ -2004,20 +2003,6 @@ - ] - - [[package]] --name = "libssh2-sys" --version = "0.2.23" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" --dependencies = [ -- "cc", -- "libc", -- "libz-sys", -- "openssl-sys", -- "pkg-config", -- "vcpkg", --] -- --[[package]] - name = "libz-sys" - version = "1.1.3" - source = "registry+https://github.com/rust-lang/crates.io-index" ---- rustc-beta-src/vendor/git2/Cargo.toml.orig 2022-10-04 10:26:35.490270607 -0700 -+++ rustc-beta-src/vendor/git2/Cargo.toml 2022-10-04 10:28:14.002187686 -0700 -@@ -58,9 +58,7 @@ - - [features] - default = [ -- "ssh", - "https", -- "ssh_key_from_memory", - ] - https = [ - "libgit2-sys/https", diff --git a/rustc-1.65.0-no-default-pie.patch b/rustc-1.65.0-no-default-pie.patch deleted file mode 100644 index 2a69611..0000000 --- a/rustc-1.65.0-no-default-pie.patch +++ /dev/null @@ -1,43 +0,0 @@ ---- rustc-beta-src/compiler/rustc_codegen_ssa/src/back/link.rs.orig 2022-09-24 10:20:14.000000000 -0700 -+++ rustc-beta-src/compiler/rustc_codegen_ssa/src/back/link.rs 2022-10-05 11:24:21.759564185 -0700 -@@ -755,7 +755,7 @@ - && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") - { - info!("linker output: {:?}", out); -- warn!("Linker does not support -no-pie command line option. Retrying without."); -+ info!("Linker does not support -no-pie command line option. Retrying without."); - for arg in cmd.take_args() { - if arg.to_string_lossy() != "-no-pie" { - cmd.arg(arg); -@@ -774,7 +774,7 @@ - && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie") - { - info!("linker output: {:?}", out); -- warn!( -+ info!( - "Linker does not support -static-pie command line option. Retrying with -static instead." - ); - // Mirror `add_(pre,post)_link_objects` to replace CRT objects. -@@ -1520,15 +1520,15 @@ - } - - fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { -- let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) { -+ // Only use PIE if explicitly specified. -+ #[allow(rustc::bad_opt_access)] -+ let explicit_pic = -+ matches!(sess.opts.cg.relocation_model, Some(RelocModel::Pic | RelocModel::Pie)); -+ let kind = match (crate_type, sess.crt_static(Some(crate_type)), explicit_pic) { - (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe, -- (CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => { -- LinkOutputKind::DynamicPicExe -- } -+ (CrateType::Executable, false, true) => LinkOutputKind::DynamicPicExe, - (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe, -- (CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => { -- LinkOutputKind::StaticPicExe -- } -+ (CrateType::Executable, true, true) => LinkOutputKind::StaticPicExe, - (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe, - (_, true, _) => LinkOutputKind::StaticDylib, - (_, false, _) => LinkOutputKind::DynamicDylib, diff --git a/rustc-1.61.0-rust-gdb-substitute-path.patch b/rustc-1.70.0-rust-gdb-substitute-path.patch similarity index 44% rename from rustc-1.61.0-rust-gdb-substitute-path.patch rename to rustc-1.70.0-rust-gdb-substitute-path.patch index b94e23e..e9e5e2e 100644 --- a/rustc-1.61.0-rust-gdb-substitute-path.patch +++ b/rustc-1.70.0-rust-gdb-substitute-path.patch @@ -1,18 +1,21 @@ ---- rustc-1.61.0-src/src/etc/rust-gdb.orig 2022-05-17 18:29:36.000000000 -0700 -+++ rustc-1.61.0-src/src/etc/rust-gdb 2022-05-18 11:18:13.732709661 -0700 -@@ -14,6 +14,9 @@ fi +diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb +index 9abed30ea6f7..e4bf55df3688 100755 +--- a/src/etc/rust-gdb ++++ b/src/etc/rust-gdb +@@ -13,8 +13,6 @@ fi + # Find out where the pretty printer Python module is RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)" GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" +-# Get the commit hash for path remapping +-RUSTC_COMMIT_HASH="$("$RUSTC" -vV | sed -n 's/commit-hash: \([a-zA-Z0-9_]*\)/\1/p')" -+RUST_STD_BUILD="@BUILDDIR@/library/" -+RUST_STD_SRC="$RUSTC_SYSROOT/lib/rustlib/src/rust/library/" -+ # Run GDB with the additional arguments that load the pretty printers # Set the environment variable `RUST_GDB` to overwrite the call to a - # different/specific command (defaults to `gdb`). -@@ -21,4 +24,5 @@ RUST_GDB="${RUST_GDB:-gdb}" +@@ -23,6 +21,6 @@ RUST_GDB="${RUST_GDB:-gdb}" PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" exec ${RUST_GDB} \ --directory="$GDB_PYTHON_MODULE_DIRECTORY" \ -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \ -+ -iex "set substitute-path $RUST_STD_BUILD $RUST_STD_SRC" \ +- -iex "set substitute-path /rustc/$RUSTC_COMMIT_HASH $RUSTC_SYSROOT/lib/rustlib/src/rust" \ ++ -iex "set substitute-path @BUILDDIR@ $RUSTC_SYSROOT/lib/rustlib/src/rust" \ "$@" + diff --git a/rustc-1.65.0-disable-http2.patch b/rustc-1.71.0-disable-http2.patch similarity index 63% rename from rustc-1.65.0-disable-http2.patch rename to rustc-1.71.0-disable-http2.patch index 99e33c7..34fdab3 100644 --- a/rustc-1.65.0-disable-http2.patch +++ b/rustc-1.71.0-disable-http2.patch @@ -1,6 +1,6 @@ ---- rustc-beta-src/Cargo.lock.orig 2022-10-04 10:55:48.797517289 -0700 -+++ rustc-beta-src/Cargo.lock 2022-10-04 10:55:48.799517248 -0700 -@@ -1026,7 +1026,6 @@ +--- rustc-beta-src/src/tools/cargo/Cargo.lock.orig 2023-07-07 17:30:04.817452621 -0700 ++++ rustc-beta-src/src/tools/cargo/Cargo.lock 2023-07-07 17:30:27.777988139 -0700 +@@ -734,7 +734,6 @@ dependencies = [ "cc", "libc", @@ -8,14 +8,14 @@ "libz-sys", "openssl-sys", "pkg-config", -@@ -1993,16 +1992,6 @@ - checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" +@@ -1954,16 +1953,6 @@ + checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] -name = "libnghttp2-sys" --version = "0.1.4+1.41.0" +-version = "0.1.7+1.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "03624ec6df166e79e139a2310ca213283d6b3c30810c54844f307086d4488df1" +-checksum = "57ed28aba195b38d5ff02b9170cbff627e336a20925e43b4945390401c5dc93f" -dependencies = [ - "cc", - "libc", @@ -23,43 +23,22 @@ - -[[package]] name = "libz-sys" - version = "1.1.3" + version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" ---- rustc-beta-src/src/tools/cargo/Cargo.toml.orig 2022-10-04 10:55:48.799517248 -0700 -+++ rustc-beta-src/src/tools/cargo/Cargo.toml 2022-10-04 11:00:55.057162743 -0700 -@@ -21,7 +21,7 @@ - cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } - cargo-util = { path = "crates/cargo-util", version = "0.2.1" } - crates-io = { path = "crates/crates-io", version = "0.34.0" } --curl = { version = "0.4.43", features = ["http2"] } -+curl = { version = "0.4.43", features = [] } - curl-sys = "0.4.55" - env_logger = "0.9.0" - pretty_env_logger = { version = "0.4", optional = true } ---- rustc-beta-src/src/tools/cargo/src/cargo/sources/registry/http_remote.rs.orig 2022-09-24 10:23:17.000000000 -0700 -+++ rustc-beta-src/src/tools/cargo/src/cargo/sources/registry/http_remote.rs 2022-10-04 10:55:48.799517248 -0700 -@@ -192,16 +192,8 @@ - } - self.fetch_started = true; - -- // We've enabled the `http2` feature of `curl` in Cargo, so treat -- // failures here as fatal as it would indicate a build-time problem. -- self.multiplexing = self.config.http_config()?.multiplexing.unwrap_or(true); -- -- self.multi -- .pipelining(false, self.multiplexing) -- .with_context(|| "failed to enable multiplexing/pipelining in curl")?; -- -- // let's not flood the server with connections -- self.multi.set_max_host_connections(2)?; -+ // Multiplexing is disabled because the system libcurl doesn't support it. -+ self.multiplexing = false; - - self.config - .shell() ---- rustc-beta-src/src/tools/cargo/src/cargo/core/package.rs.orig 2022-09-24 10:23:17.000000000 -0700 -+++ rustc-beta-src/src/tools/cargo/src/cargo/core/package.rs 2022-10-04 10:55:48.800517227 -0700 -@@ -403,16 +403,9 @@ +--- rustc-beta-src/src/tools/cargo/Cargo.toml.orig 2023-07-07 17:30:04.819452581 -0700 ++++ rustc-beta-src/src/tools/cargo/Cargo.toml 2023-07-07 17:30:24.133061874 -0700 +@@ -118,7 +118,7 @@ + cargo-util.workspace = true + clap = { workspace = true, features = ["wrap_help"] } + crates-io.workspace = true +-curl = { workspace = true, features = ["http2"] } ++curl = { workspace = true, features = [] } + curl-sys.workspace = true + env_logger.workspace = true + filetime.workspace = true +--- rustc-beta-src/src/tools/cargo/src/cargo/core/package.rs.orig 2023-06-24 10:27:37.000000000 -0700 ++++ rustc-beta-src/src/tools/cargo/src/cargo/core/package.rs 2023-07-07 17:30:04.819452581 -0700 +@@ -407,16 +407,9 @@ sources: SourceMap<'cfg>, config: &'cfg Config, ) -> CargoResult> { @@ -79,7 +58,30 @@ Ok(PackageSet { packages: package_ids -@@ -658,7 +651,7 @@ +--- rustc-beta-src/src/tools/cargo/src/cargo/sources/registry/http_remote.rs.orig 2023-06-24 10:27:37.000000000 -0700 ++++ rustc-beta-src/src/tools/cargo/src/cargo/sources/registry/http_remote.rs 2023-07-07 17:30:04.819452581 -0700 +@@ -229,16 +229,8 @@ + } + self.fetch_started = true; + +- // We've enabled the `http2` feature of `curl` in Cargo, so treat +- // failures here as fatal as it would indicate a build-time problem. +- self.multiplexing = self.config.http_config()?.multiplexing.unwrap_or(true); +- +- self.multi +- .pipelining(false, self.multiplexing) +- .with_context(|| "failed to enable multiplexing/pipelining in curl")?; +- +- // let's not flood the server with connections +- self.multi.set_max_host_connections(2)?; ++ // Multiplexing is disabled because the system libcurl doesn't support it. ++ self.multiplexing = false; + + if !self.quiet { + self.config +--- rustc-beta-src/src/tools/cargo/src/cargo/util/network/mod.rs.orig 2023-06-24 10:27:37.000000000 -0700 ++++ rustc-beta-src/src/tools/cargo/src/cargo/util/network/mod.rs 2023-07-07 17:30:04.819452581 -0700 +@@ -26,7 +26,7 @@ macro_rules! try_old_curl { ($e:expr, $msg:expr) => { let result = $e; diff --git a/rustc-1.71.0-disable-libssh2.patch b/rustc-1.71.0-disable-libssh2.patch new file mode 100644 index 0000000..ba61454 --- /dev/null +++ b/rustc-1.71.0-disable-libssh2.patch @@ -0,0 +1,42 @@ +--- rustc-beta-src/src/tools/cargo/Cargo.lock.orig 2023-06-24 10:27:37.000000000 -0700 ++++ rustc-beta-src/src/tools/cargo/Cargo.lock 2023-07-07 17:12:23.406932870 -0700 +@@ -1942,7 +1942,6 @@ + dependencies = [ + "cc", + "libc", +- "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +@@ -1965,20 +1964,6 @@ + ] + + [[package]] +-name = "libssh2-sys" +-version = "0.3.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +-dependencies = [ +- "cc", +- "libc", +- "libz-sys", +- "openssl-sys", +- "pkg-config", +- "vcpkg", +-] +- +-[[package]] + name = "libz-sys" + version = "1.1.8" + source = "registry+https://github.com/rust-lang/crates.io-index" +--- rustc-beta-src/src/tools/cargo/Cargo.toml.orig 2023-06-24 10:27:37.000000000 -0700 ++++ rustc-beta-src/src/tools/cargo/Cargo.toml 2023-07-07 17:12:00.688392750 -0700 +@@ -31,7 +31,7 @@ + filetime = "0.2.9" + flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } + fwdansi = "1.1.0" +-git2 = "0.17.1" ++git2 = { version = "0.17.1", default-features = false, features = ["https"] } + git2-curl = "0.18.0" + gix = { version = "0.44.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] } + gix-features-for-configuration-only = { version = "0.29.0", package = "gix-features", features = [ "parallel" ] } -- Gitee From 9a1e16d4b04a4822bd7d7acf2e79f54b3250576b Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Sun, 25 Jun 2023 17:50:07 +0800 Subject: [PATCH 2/2] Update loongarch64 --- 0001-vendor-cc-add-loongarch64-support.patch | 33 + ...ndor-libc-update-loongarch64-support.patch | 221 + 0003-vendor-psm-add-loongarch64-support.patch | 105 + ...endor-object-add-loongarch64-support.patch | 623 + 0005-llvm-update-loongarch64-support.patch | 70995 ++++++++++++++++ 0006-rust-add-loongarch64-support.patch | 1691 + rust.spec | 25 +- 7 files changed, 73690 insertions(+), 3 deletions(-) create mode 100644 0001-vendor-cc-add-loongarch64-support.patch create mode 100644 0002-vendor-libc-update-loongarch64-support.patch create mode 100644 0003-vendor-psm-add-loongarch64-support.patch create mode 100644 0004-vendor-object-add-loongarch64-support.patch create mode 100644 0005-llvm-update-loongarch64-support.patch create mode 100644 0006-rust-add-loongarch64-support.patch diff --git a/0001-vendor-cc-add-loongarch64-support.patch b/0001-vendor-cc-add-loongarch64-support.patch new file mode 100644 index 0000000..5c230cb --- /dev/null +++ b/0001-vendor-cc-add-loongarch64-support.patch @@ -0,0 +1,33 @@ +From 83e9097a192bf123df9b8313e9e8acd91e0c2e5d Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Thu, 7 Jul 2022 10:56:12 +0800 +Subject: [PATCH 1/6] vendor: cc: add loongarch64 support + +--- + vendor/cc/.cargo-checksum.json | 2 +- + vendor/cc/src/lib.rs | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/vendor/cc/.cargo-checksum.json b/vendor/cc/.cargo-checksum.json +index a7f8f2fe7..89b178159 100644 +--- a/vendor/cc/.cargo-checksum.json ++++ b/vendor/cc/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"Cargo.lock":"739aae86d1e7096fc84b9a6273cc49635503a4ee87b3a4b6601f569880866b29","Cargo.toml":"ccfa92dd53511178ef95aa87b2dcbdd45e23f9f8a8454e455d7da8e08feab4b5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"38970d678de0efb4b5e2978265daa8a613a1db35fc42e669621b03fc56d5b138","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"4645453198766c7486fc9b8782b06cfd0f94cbbcb3482413173e73234a447518","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"} +\ No newline at end of file ++{"files":{"Cargo.lock":"739aae86d1e7096fc84b9a6273cc49635503a4ee87b3a4b6601f569880866b29","Cargo.toml":"ccfa92dd53511178ef95aa87b2dcbdd45e23f9f8a8454e455d7da8e08feab4b5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"8313001f13ddc7b8959a81453cc8f1dcf0f95e47a283bb2c6048ba7b143acef8","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"4645453198766c7486fc9b8782b06cfd0f94cbbcb3482413173e73234a447518","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"} +diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs +index e3a2b98b0..30594a895 100644 +--- a/vendor/cc/src/lib.rs ++++ b/vendor/cc/src/lib.rs +@@ -2581,6 +2581,7 @@ impl Build { + ]), // explicit None if not found, so caller knows to fall back + "i686-unknown-linux-musl" => Some("musl"), + "i686-unknown-netbsd" => Some("i486--netbsdelf"), ++ "loongarch64-unknown-linux-gnu" => Some("loongarch64-linux-gnu"), + "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), + "mips-unknown-linux-musl" => Some("mips-linux-musl"), + "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), +-- +2.41.0 + diff --git a/0002-vendor-libc-update-loongarch64-support.patch b/0002-vendor-libc-update-loongarch64-support.patch new file mode 100644 index 0000000..90e5c15 --- /dev/null +++ b/0002-vendor-libc-update-loongarch64-support.patch @@ -0,0 +1,221 @@ +From fa9cbadfe8bca161db1c2866dbb22219b4f7e48c Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Sun, 25 Jun 2023 16:15:14 +0800 +Subject: [PATCH 2/6] vendor: libc: update loongarch64 support + +--- + vendor/libc-0.2.126/.cargo-checksum.json | 2 +- + .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ + .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ + vendor/libc-0.2.127/.cargo-checksum.json | 2 +- + .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ + .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ + vendor/libc/.cargo-checksum.json | 2 +- + .../linux/gnu/b64/loongarch64/align.rs | 17 +++++++++++++++++ + .../linux_like/linux/gnu/b64/loongarch64/mod.rs | 16 ++++++++++++++++ + 9 files changed, 102 insertions(+), 3 deletions(-) + +diff --git a/vendor/libc-0.2.126/.cargo-checksum.json b/vendor/libc-0.2.126/.cargo-checksum.json +index 26956a434..2db39a0c3 100644 +--- a/vendor/libc-0.2.126/.cargo-checksum.json ++++ b/vendor/libc-0.2.126/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"6a0abcfcbc1d9fb00a356343043a161f5b84b3f780cb0f02df4627d022b14b7f","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"41f9743021d9e5ed74ede55c94057cf6867a322a13b25a5d524b966656a08e38","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"bc8c46531bd1a2429f36aaf2bc137b50e42505b798de83f34eecfa94ad89179b","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"3f13d5f9b29d8969dde507661f1637524e21fe3bd34957fc778868f2f3713c46","src/macros.rs":"d7437c2573c4915768ff96b34710a61ee9f63622b23526cddeaeaf6bfb4751a2","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"d7155927fbd1af6dd984a4c6c1a735a5932af828c96818209487eb6ae72d7d7e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"379302e12d30807a1f973c4e2dd2205179d95343ee6fae05f33c9ed45a342799","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"467b66843ab8c1a54b01ae9e90aaf0295b32f54decbdfb64caca84523b488925","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a7345cc3fb7372572efe06848feb2cc246dfc2c2a0cc9ccf434f4c55041a59fa","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"594a0f9e23c4d7702ba38afdba5a0e866be25d692ec0afd66e04d939aa6b3f04","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"cb1560bf8ffcc7b2726a27b433efac90e726292960626f3064bd2c6b7f861a55","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"816a8ef47df60a752a91967627eeccb9ca776dc718ecc53ae902d8edaee0bce9","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"d5833ff9b94daa81d2470df544453212af17530d78c5a7fb912eac915d00f329","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"6454948ea98be86243229f99d67cdc7ca460e16b2a6445663ff4b5b6907c358d","src/unix/linux_like/android/mod.rs":"1247397a7e1b6269e0d2d6df88c6396bc18eb477e3ff293ff57d66a6b1380d94","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"b71d37106750f57bc2dae4e9bcb473ff098ef48235827e41a1687a39825f0aa4","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c4e20b1c63d7a03a6e22aef2046689ef95cc4651011ade7cb94176fcea1dc252","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"1b939aaf3cdf3efc7d3bd53e83e80235530d3ba0c24bb7611d4730d35d457ec1","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"84ad4a663b5fa2498179be8dca96fef5f0446ec1619215ac674424ee394e307d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"cff23db1e0bac8c30052dfed5e89e65bc207471e4bfb3a6fa0a4df62ed9e413e","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"9b05b1fae6bcb7cb6d909b9973977fde01684175f3e26c27dcb44223cc3933d9","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"2efe98b8166270be1624888953fa07da06f08313f15bf4c7dc2eba63f5a790a5","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"ddd223d4f574b2b92072bbdab091f12d8d89d5e05f41076ddfa6bc6af379698f","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"dd4f7a1d66d8501b4a2c4e75e6e9305ed69f1002ae99e410596a6c636878595a","src/unix/mod.rs":"d1b4ba41f9b9c106f6ba8c661b5808824b774a7a7caac7d8938bf50979ba5195","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"976b07a13e195840b67c166a62318abfa9ffc8d5ebbb0358f199dd213ec98d1b","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"} +\ No newline at end of file ++{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"6a0abcfcbc1d9fb00a356343043a161f5b84b3f780cb0f02df4627d022b14b7f","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"41f9743021d9e5ed74ede55c94057cf6867a322a13b25a5d524b966656a08e38","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"bc8c46531bd1a2429f36aaf2bc137b50e42505b798de83f34eecfa94ad89179b","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"3f13d5f9b29d8969dde507661f1637524e21fe3bd34957fc778868f2f3713c46","src/macros.rs":"d7437c2573c4915768ff96b34710a61ee9f63622b23526cddeaeaf6bfb4751a2","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"d7155927fbd1af6dd984a4c6c1a735a5932af828c96818209487eb6ae72d7d7e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"379302e12d30807a1f973c4e2dd2205179d95343ee6fae05f33c9ed45a342799","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"467b66843ab8c1a54b01ae9e90aaf0295b32f54decbdfb64caca84523b488925","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a7345cc3fb7372572efe06848feb2cc246dfc2c2a0cc9ccf434f4c55041a59fa","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"594a0f9e23c4d7702ba38afdba5a0e866be25d692ec0afd66e04d939aa6b3f04","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"cb1560bf8ffcc7b2726a27b433efac90e726292960626f3064bd2c6b7f861a55","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"816a8ef47df60a752a91967627eeccb9ca776dc718ecc53ae902d8edaee0bce9","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"d5833ff9b94daa81d2470df544453212af17530d78c5a7fb912eac915d00f329","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"6454948ea98be86243229f99d67cdc7ca460e16b2a6445663ff4b5b6907c358d","src/unix/linux_like/android/mod.rs":"1247397a7e1b6269e0d2d6df88c6396bc18eb477e3ff293ff57d66a6b1380d94","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"b71d37106750f57bc2dae4e9bcb473ff098ef48235827e41a1687a39825f0aa4","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c4e20b1c63d7a03a6e22aef2046689ef95cc4651011ade7cb94176fcea1dc252","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"1b939aaf3cdf3efc7d3bd53e83e80235530d3ba0c24bb7611d4730d35d457ec1","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"84ad4a663b5fa2498179be8dca96fef5f0446ec1619215ac674424ee394e307d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"cff23db1e0bac8c30052dfed5e89e65bc207471e4bfb3a6fa0a4df62ed9e413e","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"9b05b1fae6bcb7cb6d909b9973977fde01684175f3e26c27dcb44223cc3933d9","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"2efe98b8166270be1624888953fa07da06f08313f15bf4c7dc2eba63f5a790a5","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"ddd223d4f574b2b92072bbdab091f12d8d89d5e05f41076ddfa6bc6af379698f","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"dd4f7a1d66d8501b4a2c4e75e6e9305ed69f1002ae99e410596a6c636878595a","src/unix/mod.rs":"d1b4ba41f9b9c106f6ba8c661b5808824b774a7a7caac7d8938bf50979ba5195","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"976b07a13e195840b67c166a62318abfa9ffc8d5ebbb0358f199dd213ec98d1b","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"} +diff --git a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +index 7ca870fd0..ba3075edd 100644 +--- a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs ++++ b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +@@ -5,3 +5,20 @@ s_no_extra_traits! { + priv_: [f64; 4] + } + } ++ ++s! { ++ #[repr(align(8))] ++ pub struct clone_args { ++ pub flags: ::c_ulonglong, ++ pub pidfd: ::c_ulonglong, ++ pub child_tid: ::c_ulonglong, ++ pub parent_tid: ::c_ulonglong, ++ pub exit_signal: ::c_ulonglong, ++ pub stack: ::c_ulonglong, ++ pub stack_size: ::c_ulonglong, ++ pub tls: ::c_ulonglong, ++ pub set_tid: ::c_ulonglong, ++ pub set_tid_size: ::c_ulonglong, ++ pub cgroup: ::c_ulonglong, ++ } ++} +diff --git a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +index 2ed6a9156..ff520e0c6 100644 +--- a/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs ++++ b/vendor/libc-0.2.126/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +@@ -247,6 +247,20 @@ align_const! { + }; + } + ++pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; ++pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; ++pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; ++pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; ++pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; ++pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; ++pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; ++pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; ++pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; ++pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; ++pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; ++pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; ++pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; ++ + pub const SYS_io_setup: ::c_long = 0; + pub const SYS_io_destroy: ::c_long = 1; + pub const SYS_io_submit: ::c_long = 2; +@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; + pub const F_OFD_SETLK: ::c_int = 37; + pub const F_OFD_SETLKW: ::c_int = 38; + ++pub const MADV_SOFT_OFFLINE: ::c_int = 101; ++ + pub const EDEADLK: ::c_int = 35; + pub const EDEADLOCK: ::c_int = 35; + pub const ENAMETOOLONG: ::c_int = 36; +diff --git a/vendor/libc-0.2.127/.cargo-checksum.json b/vendor/libc-0.2.127/.cargo-checksum.json +index 3fdf6bc61..29d5859a3 100644 +--- a/vendor/libc-0.2.127/.cargo-checksum.json ++++ b/vendor/libc-0.2.127/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"e1c4b3839177aabdc73c017ee87ba3dcc8025b2730cb0a2c015473f9db99f3fa","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"94cbaad15021e287a1b9546a697b04c1e560f1204b52204ffaaea5975c5d03b9","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"0c5306ea9d12b5261380d733dc3f7624cf259c45638eac8d9222c7e32e134a65","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"e35db24ba69ee0262854916fa19a306bf6c40388f5593ab32d0907e24b5fc5c6","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"d0e8246063cae113806524a63a47c6c0628cc54a3ef03e938e89964f8b4f08b4","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ec229cc7af2511cb510c078e87e90ee2625090bfe94f40eb35f73d79143533aa","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"1e35b4773384ea143810cdce4b96f47108b37446430da30c96a0d1651656d73d","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8f9613e50c2771b33d7cf817a735d536b389ec57f861b9486d870373c768276e","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"228505fa48292e74b06acbed96196801595a4b822da2126a6d6c7fa773cff8bc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"69cc3638c6f7e2086ada7bacf5ea01ce1b7f5d045fd012c6f46b8635d30ce594","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"962741303dc24a5b9653f2e9b0b4ad9eb42fc54daa0a70ca70a7ce175e75094b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"c69c90606d4362f8de89b8816df0ded724ed64b53bf55d15681fde171b7bb361","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c72a08011c32f82919e930e0d89044d8feb65fd41bf80647436756c290344eb8","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f0db9914315d5a3d51bf5ec04a0ae6584f2e1688b9258ce132b617e67d9bd7a9","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"1ca6821fbb94476500d4352908e713b7c698cb7ff0a49997934126391657c573","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"758e222200a8cbb74b1eb01581da92fea895619da866bc383129d4b9a5366aef","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"c7ebabc4e1bdbbd97e5065faa3a57f41f473570920582d979f9e9d4f77448546","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"c3365480375bc258ffe267e7a299d7b3bb542a908bef8881f503ddc25ba8fc1f","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"aabf4582a7ddf17544ee4bfa6a954f0c6e2bd17e707b7ac5266d5697e0da762a","src/unix/mod.rs":"e13a3a67c25c28dffc53a317ab07b6416b014d10dabab9bc9002157a2362c75f","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"8914a68865af026c1f4fb1d5f02ba0053362ef34b813ad60cc4aa3a88aa4999e","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"} +\ No newline at end of file ++{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"e1c4b3839177aabdc73c017ee87ba3dcc8025b2730cb0a2c015473f9db99f3fa","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"94cbaad15021e287a1b9546a697b04c1e560f1204b52204ffaaea5975c5d03b9","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"0c5306ea9d12b5261380d733dc3f7624cf259c45638eac8d9222c7e32e134a65","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"e35db24ba69ee0262854916fa19a306bf6c40388f5593ab32d0907e24b5fc5c6","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"d0e8246063cae113806524a63a47c6c0628cc54a3ef03e938e89964f8b4f08b4","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ec229cc7af2511cb510c078e87e90ee2625090bfe94f40eb35f73d79143533aa","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"1e35b4773384ea143810cdce4b96f47108b37446430da30c96a0d1651656d73d","src/unix/bsd/mod.rs":"7720ec82c9334f988ec4b271784768a017c3dc2e6dfae4d02418eef753388aa7","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8f9613e50c2771b33d7cf817a735d536b389ec57f861b9486d870373c768276e","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"228505fa48292e74b06acbed96196801595a4b822da2126a6d6c7fa773cff8bc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"69cc3638c6f7e2086ada7bacf5ea01ce1b7f5d045fd012c6f46b8635d30ce594","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"962741303dc24a5b9653f2e9b0b4ad9eb42fc54daa0a70ca70a7ce175e75094b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"c69c90606d4362f8de89b8816df0ded724ed64b53bf55d15681fde171b7bb361","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c72a08011c32f82919e930e0d89044d8feb65fd41bf80647436756c290344eb8","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f0db9914315d5a3d51bf5ec04a0ae6584f2e1688b9258ce132b617e67d9bd7a9","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"1ca6821fbb94476500d4352908e713b7c698cb7ff0a49997934126391657c573","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"758e222200a8cbb74b1eb01581da92fea895619da866bc383129d4b9a5366aef","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"3686fc8cb2e311cda8e6b96f6dfe90b65a366714bd480312b692b1a6ca1241b6","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"c7ebabc4e1bdbbd97e5065faa3a57f41f473570920582d979f9e9d4f77448546","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"c3365480375bc258ffe267e7a299d7b3bb542a908bef8881f503ddc25ba8fc1f","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"aabf4582a7ddf17544ee4bfa6a954f0c6e2bd17e707b7ac5266d5697e0da762a","src/unix/mod.rs":"e13a3a67c25c28dffc53a317ab07b6416b014d10dabab9bc9002157a2362c75f","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"ff9c13e99d84912f5ebe75b7a7ea9c1e9d8f35a268716081e09899c7ea822bc6","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"8914a68865af026c1f4fb1d5f02ba0053362ef34b813ad60cc4aa3a88aa4999e","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"e3ad95ba54f76e74c301611fe868d3d94f6b8939b03be672f568b06b10ae71c7","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"} +diff --git a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +index 7ca870fd0..ba3075edd 100644 +--- a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs ++++ b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +@@ -5,3 +5,20 @@ s_no_extra_traits! { + priv_: [f64; 4] + } + } ++ ++s! { ++ #[repr(align(8))] ++ pub struct clone_args { ++ pub flags: ::c_ulonglong, ++ pub pidfd: ::c_ulonglong, ++ pub child_tid: ::c_ulonglong, ++ pub parent_tid: ::c_ulonglong, ++ pub exit_signal: ::c_ulonglong, ++ pub stack: ::c_ulonglong, ++ pub stack_size: ::c_ulonglong, ++ pub tls: ::c_ulonglong, ++ pub set_tid: ::c_ulonglong, ++ pub set_tid_size: ::c_ulonglong, ++ pub cgroup: ::c_ulonglong, ++ } ++} +diff --git a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +index 2ed6a9156..ff520e0c6 100644 +--- a/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs ++++ b/vendor/libc-0.2.127/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +@@ -247,6 +247,20 @@ align_const! { + }; + } + ++pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; ++pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; ++pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; ++pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; ++pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; ++pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; ++pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; ++pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; ++pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; ++pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; ++pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; ++pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; ++pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; ++ + pub const SYS_io_setup: ::c_long = 0; + pub const SYS_io_destroy: ::c_long = 1; + pub const SYS_io_submit: ::c_long = 2; +@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; + pub const F_OFD_SETLK: ::c_int = 37; + pub const F_OFD_SETLKW: ::c_int = 38; + ++pub const MADV_SOFT_OFFLINE: ::c_int = 101; ++ + pub const EDEADLK: ::c_int = 35; + pub const EDEADLOCK: ::c_int = 35; + pub const ENAMETOOLONG: ::c_int = 36; +diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json +index 631af7226..824a6e056 100644 +--- a/vendor/libc/.cargo-checksum.json ++++ b/vendor/libc/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"04fa9ce26b0efcfe3dd51e3f1bbb81bb36f5d61982a11947283c7616d390549e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"cf7e0df0e655337d1c0852880817b6b514ef9599e2125232fc79cdf8eddd01ba","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"bb61eec399428faee753b3df509410c51ed2ac51406d40559fcec290bb50e293","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"e4f33050d52d3e5c932da8d10e1f377e1ff609fb178ea986bfc458d31e37dc19","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"23f189f188651762b38f40b4e9aba785625f6f9a52558a4a490510c3b1d08b53","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"57fee9dd251ac615ec7d32d293e0f0b6fa3bf28efbddd6d569765765aafb8b9b","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7df84dd6dee8b73fd4d72dd1638584d788e2a1a85f95746f7c5b330b8dc23655","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"236ef119410d566ef94064bf13d734635eaeecb3635a5d21e8e9f91e7e3152ac","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6a8eb9a1e35eec893de9c76a5be3ce29e4c3ca26db45fbcfa925bdd757f6352d","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a61d41f6fe01c06c6de5db2ed970522601eada133e6bac4ed2d1dfaceb576db2","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"fa260decf53280d4fdf714af60f42d4774f8d6f2da71b0a55a6c2a85e422eb57","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"079b11c99c6ca3cc5942c0e6d854541f8765c5058c2f024b84656697840e198b","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"41b9d0f405cd474385acce06df0649f4eeaab3fe8fb4655f97806fa40bdf84d8","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef4652dfb94e3c58aed5133ece982ad30569d46b6b1054552cd61905fa61690","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e2b46404e44f7d63c26af9dbd79b4e166ef7bced2bc9c6746a26ca86e508e0d4","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c91813ee5e1bc817996c46be86d1f46802e73df2952cab576ea015490929afc5","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"06abaca7fc85e805650ec807c4d06c888ff99e146e1ba2685f20840a86e35a2f","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"1d84f37fdfa4dfab1b758345af75e02485e2a18746830413c2afe5069a1e39ce","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"0514b337aaa6e62be9e01e00702ef996c60319b7050ece155530147c20de9995","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"7d8dfbd26ce958d9da17468b3c9d0b119ce7dbd59b3384551cd4423ce25db44a","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"3d03bd583aaf04f285f95ff8b53c9b5a891d3b64bfcda37a42648ec51c4c51e5","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"494e56628d4408bf66ad30ff71fbd21bc33d9037935c411dff7bf73dd3f1070b","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"1369fb55325914654ba3ad02410b75a40c8c0008feed9704c28520be1ee49641","src/unix/solarish/mod.rs":"52a31038984e68582347f4b28fd64c01e6308ff4293628818bb279605e7b28c6","src/unix/solarish/solaris.rs":"36abcfb46fab6e7151a0c1f555b419e1267b82893f6e84d5d260308ba8eeb0c5","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"} +\ No newline at end of file ++{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"04fa9ce26b0efcfe3dd51e3f1bbb81bb36f5d61982a11947283c7616d390549e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"cf7e0df0e655337d1c0852880817b6b514ef9599e2125232fc79cdf8eddd01ba","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"bb61eec399428faee753b3df509410c51ed2ac51406d40559fcec290bb50e293","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"e4f33050d52d3e5c932da8d10e1f377e1ff609fb178ea986bfc458d31e37dc19","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"23f189f188651762b38f40b4e9aba785625f6f9a52558a4a490510c3b1d08b53","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"57fee9dd251ac615ec7d32d293e0f0b6fa3bf28efbddd6d569765765aafb8b9b","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7df84dd6dee8b73fd4d72dd1638584d788e2a1a85f95746f7c5b330b8dc23655","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"236ef119410d566ef94064bf13d734635eaeecb3635a5d21e8e9f91e7e3152ac","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6a8eb9a1e35eec893de9c76a5be3ce29e4c3ca26db45fbcfa925bdd757f6352d","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"a61d41f6fe01c06c6de5db2ed970522601eada133e6bac4ed2d1dfaceb576db2","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"fa260decf53280d4fdf714af60f42d4774f8d6f2da71b0a55a6c2a85e422eb57","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"079b11c99c6ca3cc5942c0e6d854541f8765c5058c2f024b84656697840e198b","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"41b9d0f405cd474385acce06df0649f4eeaab3fe8fb4655f97806fa40bdf84d8","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef4652dfb94e3c58aed5133ece982ad30569d46b6b1054552cd61905fa61690","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"e2b46404e44f7d63c26af9dbd79b4e166ef7bced2bc9c6746a26ca86e508e0d4","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c91813ee5e1bc817996c46be86d1f46802e73df2952cab576ea015490929afc5","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"d92686cfa34bbd3f1cf58d7373d7eb7135437f0f5f296d83ffc53354f966619f","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"06abaca7fc85e805650ec807c4d06c888ff99e146e1ba2685f20840a86e35a2f","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"1d84f37fdfa4dfab1b758345af75e02485e2a18746830413c2afe5069a1e39ce","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"0514b337aaa6e62be9e01e00702ef996c60319b7050ece155530147c20de9995","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"7d8dfbd26ce958d9da17468b3c9d0b119ce7dbd59b3384551cd4423ce25db44a","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"3d03bd583aaf04f285f95ff8b53c9b5a891d3b64bfcda37a42648ec51c4c51e5","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"494e56628d4408bf66ad30ff71fbd21bc33d9037935c411dff7bf73dd3f1070b","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"1369fb55325914654ba3ad02410b75a40c8c0008feed9704c28520be1ee49641","src/unix/solarish/mod.rs":"52a31038984e68582347f4b28fd64c01e6308ff4293628818bb279605e7b28c6","src/unix/solarish/solaris.rs":"36abcfb46fab6e7151a0c1f555b419e1267b82893f6e84d5d260308ba8eeb0c5","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"} +diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +index 7ca870fd0..ba3075edd 100644 +--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs ++++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs +@@ -5,3 +5,20 @@ s_no_extra_traits! { + priv_: [f64; 4] + } + } ++ ++s! { ++ #[repr(align(8))] ++ pub struct clone_args { ++ pub flags: ::c_ulonglong, ++ pub pidfd: ::c_ulonglong, ++ pub child_tid: ::c_ulonglong, ++ pub parent_tid: ::c_ulonglong, ++ pub exit_signal: ::c_ulonglong, ++ pub stack: ::c_ulonglong, ++ pub stack_size: ::c_ulonglong, ++ pub tls: ::c_ulonglong, ++ pub set_tid: ::c_ulonglong, ++ pub set_tid_size: ::c_ulonglong, ++ pub cgroup: ::c_ulonglong, ++ } ++} +diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +index 2ed6a9156..ff520e0c6 100644 +--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs ++++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs +@@ -247,6 +247,20 @@ align_const! { + }; + } + ++pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; ++pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; ++pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; ++pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; ++pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; ++pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; ++pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; ++pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; ++pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; ++pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; ++pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; ++pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; ++pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; ++ + pub const SYS_io_setup: ::c_long = 0; + pub const SYS_io_destroy: ::c_long = 1; + pub const SYS_io_submit: ::c_long = 2; +@@ -587,6 +601,8 @@ pub const F_OFD_GETLK: ::c_int = 36; + pub const F_OFD_SETLK: ::c_int = 37; + pub const F_OFD_SETLKW: ::c_int = 38; + ++pub const MADV_SOFT_OFFLINE: ::c_int = 101; ++ + pub const EDEADLK: ::c_int = 35; + pub const EDEADLOCK: ::c_int = 35; + pub const ENAMETOOLONG: ::c_int = 36; +-- +2.41.0 + diff --git a/0003-vendor-psm-add-loongarch64-support.patch b/0003-vendor-psm-add-loongarch64-support.patch new file mode 100644 index 0000000..461f59e --- /dev/null +++ b/0003-vendor-psm-add-loongarch64-support.patch @@ -0,0 +1,105 @@ +From d4a6c0659f5008337b85451da2e2ea0a74110f99 Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Thu, 7 Jul 2022 11:53:09 +0800 +Subject: [PATCH 3/6] vendor: psm: add loongarch64 support + +--- + vendor/psm/.cargo-checksum.json | 2 +- + vendor/psm/build.rs | 1 + + vendor/psm/src/arch/loongarch64.s | 64 +++++++++++++++++++++++++++++++ + 3 files changed, 66 insertions(+), 1 deletion(-) + create mode 100644 vendor/psm/src/arch/loongarch64.s + +diff --git a/vendor/psm/.cargo-checksum.json b/vendor/psm/.cargo-checksum.json +index a69778b20..ea3c4f99a 100644 +--- a/vendor/psm/.cargo-checksum.json ++++ b/vendor/psm/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"Cargo.lock":"2928b712f89aee2b62581df1e552b7cb8288d999ba180291b4900b86a05c6d8d","Cargo.toml":"c2c5a0154a80cffc82349cd98f819ea1259c92f195c5878ceefb66e06b14d28c","LICENSE-APACHE":"965a63a81d9a2fbeb5f9096954dabb49690f9dffcdac9825f675b25c807252a2","LICENSE-MIT":"3e3714aa69bd874601741fd7d7ad5298740cece37778e279fc1ab4451c5a11af","README.mkd":"6385ecaced99b0a29a5b40166d34ef9312f322c1b8ad002bef3b08cd6c3e29b2","build.rs":"1d7872546e6924bbb2947edc055ddd01f48683cc80d9d75a846adb65540345f0","examples/info.rs":"8ffb89912304ecbf3d714dcc094f42e86fdd0738625b2e76be2e7d59ab0736cf","examples/on_stack_fibo.rs":"287f0a08b177a97366a5da39e24e33e1f4bbe30a1f2473956721c8a9d93926a4","examples/on_stack_fibo_alloc_each_frame.rs":"e084041bbb81d51b195a4db539a765409272916df29c83a62213a93de4b6fca3","examples/panics.rs":"6791fe0dda9456b3becf989cbc89bc45ae27302e633572a57bbf10a57b830076","examples/replace_stack_1.rs":"374a28881f5e5dbf9db9b9e34929fb7a7e6f3910d782a6718f53ac269807b990","examples/thread.rs":"3cf92882aff96151608584d63535701cc8e5ae953d7ecf706d77371180bff025","src/arch/aarch64_armasm.asm":"1c737338287f3de981fbae97f104ac5e49425ba7fbcb4f7d80120afae47a86d5","src/arch/aarch_aapcs64.s":"459b8cd5a96104893e8f849ac83369101d7204c933841672df162104bebd2375","src/arch/arm_aapcs.s":"4ada635e8528279bd0326654f5203b6bdc94dd68c94fdef5de551384ba1b1747","src/arch/arm_armasm.asm":"e3b514169f19368b0b49374412de38bd9f50576e7b93b64d685a0f84fa8f4c91","src/arch/mips64_eabi.s":"4e6f95f89ba72fc4dd1a9a547920764f66d98251d236941cee4d227010484520","src/arch/mips_eabi.s":"8b7927fd63660eb276e2951f28df6b11920f04be4dc17a16b66ad386da12c4c3","src/arch/powerpc32.s":"0b508a65dec7254ba2e0dc65a2c9e86c21069fe62f5d7c41f5190415a4885912","src/arch/powerpc64.s":"c1602d09d12ba1df48fc96af0f827f8679fc93cee728813527fb1b817a788911","src/arch/powerpc64_openpower.s":"421b11cc7381427d1e2acb4e681c9836ccfea0b79930492f0a99ec4d27495e58","src/arch/psm.h":"2cebda3740aa73b167b8ec18e3d2202ca46e400a081a46329b86051abd1a872a","src/arch/riscv.s":"a81d2af4bcc9c29db304730697e52a89a7376b51d2735185c67be8910d0cdf39","src/arch/riscv64.s":"a51da67ce569e2442ff487b062bb8fdfe7c769f3f05a88de480bd5ab214d9a4f","src/arch/sparc64.s":"6250acbd938aea2e440061663a79fbb2dac0592b3a193f027b6b910e2a8e3af1","src/arch/sparc_sysv.s":"c2da7576e1fbe2234cc8a5cf937f7676e125435295f8c32089bfa0b0f27fde5e","src/arch/wasm32.o":"d7279f419cb7e169cae2af2463507652e0393b801c2f4580244de70d3def58b6","src/arch/wasm32.s":"1ebdc90de48f13e6474ee17c406578fc090ff61e57c1f560ecf6e6b75c7ef10a","src/arch/x86.s":"1919a4af1474895f904ed4281a4a8fcdd0428dab257bff4ea262db83ed63b445","src/arch/x86_64.s":"c80f1a3e22db61fd62b5ef2e1b6663185403bdcbcfbfe7ff0f8e0831ff0cafcf","src/arch/x86_64_msvc.asm":"85683bc65a03371ea7d8d79dcbe487f690cc2460c359817fc63c30d575ad8957","src/arch/x86_64_windows_gnu.s":"44637034e094ec0ad76dbe1232e97271c8155eb93bcb1dd86fe825acd05978a0","src/arch/x86_msvc.asm":"1735d4b19f8e46d0699fc9538baa7ab0885d27531ef7d9960e2027ad8137769b","src/arch/x86_windows_gnu.s":"b94d907a86f230c5c8ca1c708ede173f73c5269496f3959e08e4a92155e160d7","src/arch/zseries_linux.s":"5c3379a76e31bf13abf240efda12596fabce108cf63f60f9d0495e82ab8f1717","src/lib.rs":"18774ee37630bc6c7a36273014f80f6afa3f73bf34f4c49f5795d2eb5df1c195","tests/stack_direction.rs":"77d8f9dee196e99e70d569f59fef82bc2f88a8ec17bfe07ebe2f005fcb815c8b","tests/stack_direction_2.rs":"f9191394de5b6381af6ba8223e7717230059dc335f639238c0ddbc7eb87bfc0e"},"package":"cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"} +\ No newline at end of file ++{"files":{"Cargo.lock":"2928b712f89aee2b62581df1e552b7cb8288d999ba180291b4900b86a05c6d8d","Cargo.toml":"c2c5a0154a80cffc82349cd98f819ea1259c92f195c5878ceefb66e06b14d28c","LICENSE-APACHE":"965a63a81d9a2fbeb5f9096954dabb49690f9dffcdac9825f675b25c807252a2","LICENSE-MIT":"3e3714aa69bd874601741fd7d7ad5298740cece37778e279fc1ab4451c5a11af","README.mkd":"6385ecaced99b0a29a5b40166d34ef9312f322c1b8ad002bef3b08cd6c3e29b2","build.rs":"f742cdd0ea2c92b5f43008488b6dc3c89424f83ca9ef25ca89ab3894d6707764","examples/info.rs":"8ffb89912304ecbf3d714dcc094f42e86fdd0738625b2e76be2e7d59ab0736cf","examples/on_stack_fibo.rs":"287f0a08b177a97366a5da39e24e33e1f4bbe30a1f2473956721c8a9d93926a4","examples/on_stack_fibo_alloc_each_frame.rs":"e084041bbb81d51b195a4db539a765409272916df29c83a62213a93de4b6fca3","examples/panics.rs":"6791fe0dda9456b3becf989cbc89bc45ae27302e633572a57bbf10a57b830076","examples/replace_stack_1.rs":"374a28881f5e5dbf9db9b9e34929fb7a7e6f3910d782a6718f53ac269807b990","examples/thread.rs":"3cf92882aff96151608584d63535701cc8e5ae953d7ecf706d77371180bff025","src/arch/aarch64_armasm.asm":"1c737338287f3de981fbae97f104ac5e49425ba7fbcb4f7d80120afae47a86d5","src/arch/aarch_aapcs64.s":"459b8cd5a96104893e8f849ac83369101d7204c933841672df162104bebd2375","src/arch/arm_aapcs.s":"4ada635e8528279bd0326654f5203b6bdc94dd68c94fdef5de551384ba1b1747","src/arch/arm_armasm.asm":"e3b514169f19368b0b49374412de38bd9f50576e7b93b64d685a0f84fa8f4c91","src/arch/loongarch64.s":"47836a2b0a19d8b7a63fd21674509224ec8059eee1251205ad88c8e0ec7469a3","src/arch/mips64_eabi.s":"4e6f95f89ba72fc4dd1a9a547920764f66d98251d236941cee4d227010484520","src/arch/mips_eabi.s":"8b7927fd63660eb276e2951f28df6b11920f04be4dc17a16b66ad386da12c4c3","src/arch/powerpc32.s":"0b508a65dec7254ba2e0dc65a2c9e86c21069fe62f5d7c41f5190415a4885912","src/arch/powerpc64.s":"c1602d09d12ba1df48fc96af0f827f8679fc93cee728813527fb1b817a788911","src/arch/powerpc64_openpower.s":"421b11cc7381427d1e2acb4e681c9836ccfea0b79930492f0a99ec4d27495e58","src/arch/psm.h":"2cebda3740aa73b167b8ec18e3d2202ca46e400a081a46329b86051abd1a872a","src/arch/riscv.s":"a81d2af4bcc9c29db304730697e52a89a7376b51d2735185c67be8910d0cdf39","src/arch/riscv64.s":"a51da67ce569e2442ff487b062bb8fdfe7c769f3f05a88de480bd5ab214d9a4f","src/arch/sparc64.s":"6250acbd938aea2e440061663a79fbb2dac0592b3a193f027b6b910e2a8e3af1","src/arch/sparc_sysv.s":"c2da7576e1fbe2234cc8a5cf937f7676e125435295f8c32089bfa0b0f27fde5e","src/arch/wasm32.o":"d7279f419cb7e169cae2af2463507652e0393b801c2f4580244de70d3def58b6","src/arch/wasm32.s":"1ebdc90de48f13e6474ee17c406578fc090ff61e57c1f560ecf6e6b75c7ef10a","src/arch/x86.s":"1919a4af1474895f904ed4281a4a8fcdd0428dab257bff4ea262db83ed63b445","src/arch/x86_64.s":"c80f1a3e22db61fd62b5ef2e1b6663185403bdcbcfbfe7ff0f8e0831ff0cafcf","src/arch/x86_64_msvc.asm":"85683bc65a03371ea7d8d79dcbe487f690cc2460c359817fc63c30d575ad8957","src/arch/x86_64_windows_gnu.s":"44637034e094ec0ad76dbe1232e97271c8155eb93bcb1dd86fe825acd05978a0","src/arch/x86_msvc.asm":"1735d4b19f8e46d0699fc9538baa7ab0885d27531ef7d9960e2027ad8137769b","src/arch/x86_windows_gnu.s":"b94d907a86f230c5c8ca1c708ede173f73c5269496f3959e08e4a92155e160d7","src/arch/zseries_linux.s":"5c3379a76e31bf13abf240efda12596fabce108cf63f60f9d0495e82ab8f1717","src/lib.rs":"18774ee37630bc6c7a36273014f80f6afa3f73bf34f4c49f5795d2eb5df1c195","tests/stack_direction.rs":"77d8f9dee196e99e70d569f59fef82bc2f88a8ec17bfe07ebe2f005fcb815c8b","tests/stack_direction_2.rs":"f9191394de5b6381af6ba8223e7717230059dc335f639238c0ddbc7eb87bfc0e"},"package":"cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"} +diff --git a/vendor/psm/build.rs b/vendor/psm/build.rs +index 01a13bf71..9fab27a83 100644 +--- a/vendor/psm/build.rs ++++ b/vendor/psm/build.rs +@@ -51,6 +51,7 @@ fn find_assembly( + ("riscv32", _, _, _) => Some(("src/arch/riscv.s", true)), + ("riscv64", _, _, _) => Some(("src/arch/riscv64.s", true)), + ("wasm32", _, _, _) => Some(("src/arch/wasm32.o", true)), ++ ("loongarch64", _, _, _) => Some(("src/arch/loongarch64.s", true)), + _ => None, + } + } +diff --git a/vendor/psm/src/arch/loongarch64.s b/vendor/psm/src/arch/loongarch64.s +new file mode 100644 +index 000000000..04bcee3a0 +--- /dev/null ++++ b/vendor/psm/src/arch/loongarch64.s +@@ -0,0 +1,64 @@ ++#include "psm.h" ++ ++.text ++.globl rust_psm_stack_direction ++.p2align 2 ++.type rust_psm_stack_direction,@function ++/* extern "C" fn() -> u8 */ ++rust_psm_stack_direction: ++.cfi_startproc ++ addi.w $r4, $r0, STACK_DIRECTION_DESCENDING ++ jr $r1 ++.rust_psm_stack_direction_end: ++.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction ++.cfi_endproc ++ ++ ++.globl rust_psm_stack_pointer ++.p2align 2 ++.type rust_psm_stack_pointer,@function ++/* extern "C" fn() -> *mut u8 */ ++rust_psm_stack_pointer: ++.cfi_startproc ++ move $r4, $r3 ++ jr $r1 ++.rust_psm_stack_pointer_end: ++.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer ++.cfi_endproc ++ ++ ++.globl rust_psm_replace_stack ++.p2align 2 ++.type rust_psm_replace_stack,@function ++/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */ ++rust_psm_replace_stack: ++.cfi_startproc ++ move $r3, $r6 ++ jr $r5 ++.rust_psm_replace_stack_end: ++.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack ++.cfi_endproc ++ ++ ++.globl rust_psm_on_stack ++.p2align 2 ++.type rust_psm_on_stack,@function ++/* extern "C" fn(r4: iusize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */ ++rust_psm_on_stack: ++.cfi_startproc ++ st.d $r3, $r7, -8 ++ st.d $r1, $r7, -16 ++ .cfi_def_cfa 7, 0 ++ .cfi_offset 3, -8 ++ .cfi_offset 1, -16 ++ addi.d $r3, $r7, -16 ++ .cfi_def_cfa 3, -16 ++ jirl $r1, $r6, 0 ++ ld.d $r1, $r3, 0 ++ .cfi_restore 12 ++ ld.d $r3, $r3, 8 ++ .cfi_restore 3 ++ jr $r1 ++.rust_psm_on_stack_end: ++.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack ++.cfi_endproc +-- +2.41.0 + diff --git a/0004-vendor-object-add-loongarch64-support.patch b/0004-vendor-object-add-loongarch64-support.patch new file mode 100644 index 0000000..620cb66 --- /dev/null +++ b/0004-vendor-object-add-loongarch64-support.patch @@ -0,0 +1,623 @@ +From 5258a72e586e973867e392178f0e3dfd19610d23 Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Sun, 25 Jun 2023 16:22:39 +0800 +Subject: [PATCH 4/6] vendor: object: add loongarch64 support + +--- + vendor/object-0.26.2/.cargo-checksum.json | 2 +- + vendor/object-0.26.2/src/common.rs | 2 + + vendor/object-0.26.2/src/elf.rs | 119 +++++++++ + vendor/object-0.26.2/src/read/elf/file.rs | 1 + + .../object-0.26.2/src/read/elf/relocation.rs | 5 + + vendor/object-0.26.2/src/write/elf.rs | 10 + + vendor/object-0.26.2/tests/round_trip/mod.rs | 1 + + vendor/object/.cargo-checksum.json | 2 +- + vendor/object/src/common.rs | 4 +- + vendor/object/src/elf.rs | 244 +++++++++--------- + vendor/object/src/write/elf/object.rs | 7 +- + 11 files changed, 264 insertions(+), 133 deletions(-) + +diff --git a/vendor/object-0.26.2/.cargo-checksum.json b/vendor/object-0.26.2/.cargo-checksum.json +index 1f76cb1fc..32e0621c8 100644 +--- a/vendor/object-0.26.2/.cargo-checksum.json ++++ b/vendor/object-0.26.2/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"CHANGELOG.md":"52a47c66164f368e5a167f1732525583ec574cd7de8be91fac29d52997b1c632","Cargo.lock":"a1190887088da0ebf768d172d97a9c21519fe4adb72860e4c9d3826307a57ce6","Cargo.toml":"2481b73a96029b6409d582b026d901d04f5ef12c12ccb27f3c997fa567ce18a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"283c8881f81e647191130eea41b94fe877214e492fd35dd02a10c0698aaedcdf","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"49feba2fd34a6fb76e18763348e6ccf5a0c4ccf3779e5bc622df4d8ed14e82bf","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"9a16e67c321a6b35d35ce9d0611281f8f30b2c475cde68479d6a0fdd2b997a5e","src/elf.rs":"78df96810cb379e1dd8b4872ab90d2337855fa4d4d98fb09697d0750154dc40b","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"fccca74e1e79d5d4dbb090a0103d91b5a0b4f71983d5e3ee3b139b13a9c7990d","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"7a1b57131f43ed01472f4924f37657896880b82b127a153795388eb4577a640a","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"696a956935e7f1babb621ff71dec23154ca4bf906a8adfa5c02aac7a50117c69","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"3b15e43d5db9e3af025cda166dd731a5a10293c8d6a6a6f82e7ff4541a4b04a8","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"721e4f96c2de16f85192db0ad53ee34745bcbe8d551ad297d4f44ab13205ec06","src/read/coff/symbol.rs":"01a11c8f77c1b80d354d9437439cf4685b99bf254cc9eeadd19da2a394fc3c57","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"9d5958552ac3f590249c45795d40d8ffce0d41a6e4d9ae2f38f356ad4e46c05e","src/read/elf/hash.rs":"3a08046c78a6fd79bccfd1a0d4cc113da8d0664164576f290885b51d8110acca","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"62b27c79964f7b037f4fb0b952afacd14790751828e82b67ed5890f143e2b2dc","src/read/elf/section.rs":"d692093ad195ccd0e4857c2f9c638543aa38a8179180e68d27a1f0784aa5e09a","src/read/elf/segment.rs":"d3cbb86cc9ca6eca93f9c17f36823dae0bd72ab2761f2b784dadd8f5b5c9dd9f","src/read/elf/symbol.rs":"9582039f44e82a3bbf225db12ddab9a3b3d5f4b0536d4125c18bb693da3c6db7","src/read/elf/version.rs":"c665034c90cb17e7bd1a6ba836966534fb2527698979908a704cf3b716c0dbdc","src/read/macho/dyld_cache.rs":"37330ba249226231b2e6ae7de80d60845c2eb7db854fd588c52fc706e13e49b8","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c524be5be3447afb5aa9c68673f495de05e652687790397f6bf5617b9beea21a","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"c0a615079779bf83bc3a6ae6d816f8d853099591f0b72e8646a624955bc5069e","src/read/mod.rs":"18ccc63d7acfc1af561d413738cafb1882368179257d36d2dc2496e21095bf7c","src/read/pe/file.rs":"f17836ac757dfd198323a2df1289b02dbb3ba85f2ceff0fdb7e565d30d555da3","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"befd3c82fe6d9186b5802945853da9653649779989fd36cd2a835e3264156281","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"16f52497fd18ec893c8f72903e9ea0bde6901e75acdfbc8be6a7305e13bccb8c","src/write/elf.rs":"2d6d3c4b014e9df7dd09e3ecf926a7d8fbac6e3cf3ab768e672b7c8ac1d38485","src/write/macho.rs":"fa058f9e7aa1e9895a3c4575fa527c3d5dbac186d994c9ba48801348a8428f35","src/write/mod.rs":"970620fba6e7b851981cda09929d93667a51d0c0be2c1491fdd8002d530515df","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"3bf18004fd5cd25229e480856f36b3410f23b12c096de4c52ab13e11da75b2e3","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b741ba432fdee2156699743962c64aaf2d1e9629c432e40953ac4d410688ea5a","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"} +\ No newline at end of file ++{"files":{"CHANGELOG.md":"52a47c66164f368e5a167f1732525583ec574cd7de8be91fac29d52997b1c632","Cargo.lock":"a1190887088da0ebf768d172d97a9c21519fe4adb72860e4c9d3826307a57ce6","Cargo.toml":"2481b73a96029b6409d582b026d901d04f5ef12c12ccb27f3c997fa567ce18a7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"283c8881f81e647191130eea41b94fe877214e492fd35dd02a10c0698aaedcdf","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/ar.rs":"9846b618c70acfcb869895f1e1829a3b3824c04afd685ee7af289c91fcf0e420","examples/dyldcachedump.rs":"d30974ade7acbb13843ab5ffe74e825316f533b4bf7a6431799277d2340aad01","examples/nm.rs":"07b8dd510ad51640ffedba74ef3d05b290922d1a5ccf78237693e527124deb2d","examples/objcopy.rs":"e4e3a080733e877bd8024b3bd98dbf607e3ad9611db4f417a156c0f144f6b663","examples/objdump.rs":"1e0a27b2c3ac4dd85df9fc9a4463644de5f4762b3428e9b0d4f542c7084ff793","examples/objectmap.rs":"d36457d5334551a8d82880847a563ca619e022746e8ef3fd79f3a16193a5dd95","examples/readobj.rs":"49feba2fd34a6fb76e18763348e6ccf5a0c4ccf3779e5bc622df4d8ed14e82bf","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"fefada6d122499cfbdb3c2d6deb3727f0c516b771a9393f716310564c4139da3","src/elf.rs":"47244eee991c738a1e72777e835c196ce2fbd10d5e20a741271356c402d41540","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"fccca74e1e79d5d4dbb090a0103d91b5a0b4f71983d5e3ee3b139b13a9c7990d","src/macho.rs":"ef938fbfd5913711493ef4347a1b426b7ee661a2eb2038681552d7d8b7282e7a","src/pe.rs":"7a1b57131f43ed01472f4924f37657896880b82b127a153795388eb4577a640a","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"696a956935e7f1babb621ff71dec23154ca4bf906a8adfa5c02aac7a50117c69","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"f4198dcdd2c270c9f1ba9efa30c6fb291913984079a45c02e6b6f57dce2700da","src/read/coff/file.rs":"3b15e43d5db9e3af025cda166dd731a5a10293c8d6a6a6f82e7ff4541a4b04a8","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"a9406980b89a33a16b4fa4f41f01d6db63096c46ff61bb8bd590f86f1d5ed5cf","src/read/coff/section.rs":"721e4f96c2de16f85192db0ad53ee34745bcbe8d551ad297d4f44ab13205ec06","src/read/coff/symbol.rs":"01a11c8f77c1b80d354d9437439cf4685b99bf254cc9eeadd19da2a394fc3c57","src/read/elf/comdat.rs":"340cccdea68c7ed77406ee45c4baa5f179588d77d90bb88b0cd9749d0d725cb1","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"2454551eb67757622b3d6660bc13ed39341be91f382eb8b1910095f58cf2bae2","src/read/elf/file.rs":"46e1aa01bed485c53288df14cc1688fe5e4ed81f259a30f54acbb3498042db72","src/read/elf/hash.rs":"3a08046c78a6fd79bccfd1a0d4cc113da8d0664164576f290885b51d8110acca","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"68c85f2ab03ea14feccdffbb383c6c44a55281b7ca17aa82a487ea8ccc710b70","src/read/elf/section.rs":"d692093ad195ccd0e4857c2f9c638543aa38a8179180e68d27a1f0784aa5e09a","src/read/elf/segment.rs":"d3cbb86cc9ca6eca93f9c17f36823dae0bd72ab2761f2b784dadd8f5b5c9dd9f","src/read/elf/symbol.rs":"9582039f44e82a3bbf225db12ddab9a3b3d5f4b0536d4125c18bb693da3c6db7","src/read/elf/version.rs":"c665034c90cb17e7bd1a6ba836966534fb2527698979908a704cf3b716c0dbdc","src/read/macho/dyld_cache.rs":"37330ba249226231b2e6ae7de80d60845c2eb7db854fd588c52fc706e13e49b8","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"c524be5be3447afb5aa9c68673f495de05e652687790397f6bf5617b9beea21a","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"59e70336d50f757d8d8daf44f23acca77de87cffcf2d62326e3b17c2ff9f672f","src/read/macho/segment.rs":"659b61a8cb563504f533c390fb901883b72c298f7bea037100a677cc9e4face4","src/read/macho/symbol.rs":"c0a615079779bf83bc3a6ae6d816f8d853099591f0b72e8646a624955bc5069e","src/read/mod.rs":"18ccc63d7acfc1af561d413738cafb1882368179257d36d2dc2496e21095bf7c","src/read/pe/file.rs":"f17836ac757dfd198323a2df1289b02dbb3ba85f2ceff0fdb7e565d30d555da3","src/read/pe/mod.rs":"05d9f3320596f9e567cbd791b68982d50a31e8d18f60c2c401c4a40eb50f1d94","src/read/pe/section.rs":"befd3c82fe6d9186b5802945853da9653649779989fd36cd2a835e3264156281","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"5f29ae16bcf078c7089b22d7bd3ca9c6bc2eb637900a3b1cc70f9a45e5f8be09","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"936ac6b218d23d7bb9ca6869f17cd8dafbed80ee0b267254c7a3ffe05bd46948","src/write/coff.rs":"16f52497fd18ec893c8f72903e9ea0bde6901e75acdfbc8be6a7305e13bccb8c","src/write/elf.rs":"34cbd7f14853309f94ac29d3371fac25165dbd72b0d84b6c6cd2cae6eb3fd2c7","src/write/macho.rs":"fa058f9e7aa1e9895a3c4575fa527c3d5dbac186d994c9ba48801348a8428f35","src/write/mod.rs":"970620fba6e7b851981cda09929d93667a51d0c0be2c1491fdd8002d530515df","src/write/string.rs":"920d71223a5a146ef516b6d5fb6d22bc86a7e456da369ae8a4d1ca6b63d59892","src/write/util.rs":"3bf18004fd5cd25229e480856f36b3410f23b12c096de4c52ab13e11da75b2e3","tests/integration.rs":"d491a0ae0d50c3194cd7b81720262f55ccb234251346f188284ce29729823dc2","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/comdat.rs":"2e3ef1aef466911646e5cbfe0b1a8c1543530baf8ca6102394519e701a1e2747","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"a1ff40266998321c75023cf76384f8ad03828c6d487421ea8b7774fce8173039","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"8086e07fb15c3306944606b3cdd26cd0db42d1606885fc43dada4aa6e456aa2c","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"} +diff --git a/vendor/object-0.26.2/src/common.rs b/vendor/object-0.26.2/src/common.rs +index c86665c21..0759a9d4e 100644 +--- a/vendor/object-0.26.2/src/common.rs ++++ b/vendor/object-0.26.2/src/common.rs +@@ -23,6 +23,7 @@ pub enum Architecture { + S390x, + Sparc64, + Wasm32, ++ LoongArch64, + } + + impl Architecture { +@@ -50,6 +51,7 @@ impl Architecture { + Architecture::S390x => Some(AddressSize::U64), + Architecture::Sparc64 => Some(AddressSize::U64), + Architecture::Wasm32 => Some(AddressSize::U32), ++ Architecture::LoongArch64 => Some(AddressSize::U64), + } + } + } +diff --git a/vendor/object-0.26.2/src/elf.rs b/vendor/object-0.26.2/src/elf.rs +index 28ac16bbe..5591834f1 100644 +--- a/vendor/object-0.26.2/src/elf.rs ++++ b/vendor/object-0.26.2/src/elf.rs +@@ -564,6 +564,8 @@ pub const EM_BPF: u16 = 247; + pub const EM_CSKY: u16 = 252; + /// Digital Alpha + pub const EM_ALPHA: u16 = 0x9026; ++/// LOONGARCH ++pub const EM_LOONGARCH: u16 = 258; + + // Values for `FileHeader*::e_version` and `Ident::version`. + /// Invalid ELF version. +@@ -6081,6 +6083,123 @@ pub const R_RISCV_SET32: u32 = 56; + #[allow(missing_docs)] + pub const R_RISCV_32_PCREL: u32 = 57; + ++//LOONGARCH values `FileHeader*::e_flags`. ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI: u32 = 0x0003; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LP64: u32 = 0x0003; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LPX32: u32 = 0x0002; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LP32: u32 = 0x0001; ++ ++// LOONGARCH values `Rel*::r_type`. ++/* Loongarch specific dynamic relocations. */ ++#[allow(missing_docs)] ++pub const R_LARCH_NONE: u32 = 0; ++#[allow(missing_docs)] ++pub const R_LARCH_32: u32 = 1; ++#[allow(missing_docs)] ++pub const R_LARCH_64: u32 = 2; ++#[allow(missing_docs)] ++pub const R_LARCH_RELATIVE: u32 = 3; ++#[allow(missing_docs)] ++pub const R_LARCH_COPY: u32 = 4; ++#[allow(missing_docs)] ++pub const R_LARCH_JUMP_SLOT: u32 = 5; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPMOD32: u32 = 6; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPMOD64: u32 = 7; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPREL32: u32 = 8; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPREL64: u32 = 9; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_TPREL32: u32 = 10; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_TPREL64: u32 = 11; ++#[allow(missing_docs)] ++pub const R_LARCH_IRELATIVE: u32 = 12; ++#[allow(missing_docs)] ++pub const R_LARCH_MARK_LA: u32 = 20; ++#[allow(missing_docs)] ++pub const R_LARCH_MARK_PCREL: u32 = 21; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_ASSERT: u32 = 30; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_NOT: u32 = 31; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SUB: u32 = 32; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SL: u32 = 33; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SR: u32 = 34; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_ADD: u32 = 35; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_AND: u32 = 36; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_IF_ELSE: u32 = 37; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_U: u32 = 46; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD8: u32 = 47; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD16: u32 = 48; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD24: u32 = 49; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD32: u32 = 50; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD64: u32 = 51; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB8: u32 = 52; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB16: u32 = 53; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB24: u32 = 54; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB32: u32 = 55; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB64: u32 = 56; ++#[allow(missing_docs)] ++pub const R_LARCH_GNU_VTINHERIT: u32 = 57; ++#[allow(missing_docs)] ++pub const R_LARCH_GNU_VTENTRY: u32 = 58; ++ + // BPF values `Rel*::r_type`. + /// No reloc + pub const R_BPF_NONE: u32 = 0; +diff --git a/vendor/object-0.26.2/src/read/elf/file.rs b/vendor/object-0.26.2/src/read/elf/file.rs +index 91273ca41..00262dafc 100644 +--- a/vendor/object-0.26.2/src/read/elf/file.rs ++++ b/vendor/object-0.26.2/src/read/elf/file.rs +@@ -161,6 +161,7 @@ where + (elf::EM_X86_64, false) => Architecture::X86_64_X32, + (elf::EM_X86_64, true) => Architecture::X86_64, + (elf::EM_HEXAGON, _) => Architecture::Hexagon, ++ (elf::EM_LOONGARCH, true) => Architecture::LoongArch64, + (elf::EM_MIPS, false) => Architecture::Mips, + (elf::EM_MIPS, true) => Architecture::Mips64, + (elf::EM_MSP430, _) => Architecture::Msp430, +diff --git a/vendor/object-0.26.2/src/read/elf/relocation.rs b/vendor/object-0.26.2/src/read/elf/relocation.rs +index d3e24b2e8..790cebc91 100644 +--- a/vendor/object-0.26.2/src/read/elf/relocation.rs ++++ b/vendor/object-0.26.2/src/read/elf/relocation.rs +@@ -301,6 +301,11 @@ fn parse_relocation( + elf::R_HEX_32 => (RelocationKind::Absolute, 32), + r_type => (RelocationKind::Elf(r_type), 0), + }, ++ elf::EM_LOONGARCH => match reloc.r_type(endian, false) { ++ elf::R_LARCH_32 => (RelocationKind::Absolute, 32), ++ elf::R_LARCH_64 => (RelocationKind::Absolute, 64), ++ r_type => (RelocationKind::Elf(r_type), 0), ++ }, + elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) { + elf::R_MIPS_16 => (RelocationKind::Absolute, 16), + elf::R_MIPS_32 => (RelocationKind::Absolute, 32), +diff --git a/vendor/object-0.26.2/src/write/elf.rs b/vendor/object-0.26.2/src/write/elf.rs +index 34e0abc85..c90146edb 100644 +--- a/vendor/object-0.26.2/src/write/elf.rs ++++ b/vendor/object-0.26.2/src/write/elf.rs +@@ -88,6 +88,7 @@ impl Object { + Architecture::Riscv32 => true, + Architecture::S390x => true, + Architecture::Sparc64 => true, ++ Architecture::LoongArch64 => true, + _ => { + return Err(Error(format!( + "unimplemented architecture {:?}", +@@ -371,6 +372,7 @@ impl Object { + Architecture::Riscv64 => elf::EM_RISCV, + Architecture::S390x => elf::EM_S390, + Architecture::Sparc64 => elf::EM_SPARCV9, ++ Architecture::LoongArch64 => elf::EM_LOONGARCH, + _ => { + return Err(Error(format!( + "unimplemented architecture {:?}", +@@ -682,6 +684,14 @@ impl Object { + return Err(Error(format!("unimplemented relocation {:?}", reloc))); + } + }, ++ Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) { ++ (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, ++ (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, ++ (RelocationKind::Elf(x), _, _) => x, ++ _ => { ++ return Err(Error(format!("unimplemented relocation {:?}", reloc))); ++ } ++ }, + Architecture::Mips | Architecture::Mips64 => { + match (reloc.kind, reloc.encoding, reloc.size) { + (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16, +diff --git a/vendor/object-0.26.2/tests/round_trip/mod.rs b/vendor/object-0.26.2/tests/round_trip/mod.rs +index 37050689f..5d97f7ab9 100644 +--- a/vendor/object-0.26.2/tests/round_trip/mod.rs ++++ b/vendor/object-0.26.2/tests/round_trip/mod.rs +@@ -236,6 +236,7 @@ fn elf_any() { + (Architecture::X86_64, Endianness::Little), + (Architecture::X86_64_X32, Endianness::Little), + (Architecture::Hexagon, Endianness::Little), ++ (Architecture::LoongArch64, Endianness::Little), + (Architecture::Mips, Endianness::Little), + (Architecture::Mips64, Endianness::Little), + (Architecture::Msp430, Endianness::Little), +diff --git a/vendor/object/.cargo-checksum.json b/vendor/object/.cargo-checksum.json +index e4a57348b..a85fa9ebb 100644 +--- a/vendor/object/.cargo-checksum.json ++++ b/vendor/object/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"CHANGELOG.md":"78aa23a55bd06448276854e3c19f984ff45098071dda36b27a0fb2e236630348","Cargo.toml":"4cdcbff917685fee9e3b4212583c2f1ea7a278b6fdb402ff18e314d57095a8b6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"3c5f153cecb269a4dbd5f0907951b1fe40e53054a9625bb75604e3b142ed45e3","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"ec5c87c07743202d1faabcaac7e4f65d7d1186ad47d503c7b9cd30ecce39383e","src/elf.rs":"018c6da138e3ff7f7d78c9346ffab37773e23fb6224ac8c7627defc802cbaacb","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"22f3f5a5834821d144daf3b1993da1a2072ee57692321366da9c281de6d0a0fe","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"f14fe040751bdde66d8a39b53d145817ac131722c6d790f853bbcd764b1466b8","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"3c525fbe89144caf72ae0d55f5625b3be8476dcfa8a9203425f68fb087631c12","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"a2b0e3131c17e3b14def694342b119a215b017ac81c8538097bebe0ea3a6ecdd","src/read/elf/comdat.rs":"9c31a274e7b43bc27f9b82a67207b94eef2d07ef107c8e2ef7a1535fe7329f55","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"192adf7e082e9a702233f5012981b422408e55f0d8460cf39f8faa8fda0d6a5e","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"4ce50bfeaa6ae69c36458139a7699eac6542f448c786b5a102efd187b0fd5ddb","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"f0534940d8697d7bb66bc784dee0a3e2e173c2ff5266d03d7ad92b0b3efa15e1","src/read/elf/symbol.rs":"6d7361ed09d3829f6fed87f26d10746b4b8b1862579f94445683651f047b8b43","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"ee5e429abdaf6de167de2247679e13ce37724a6a0c50b8842302eb98d583bb71","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"e8c308113c48439a00777404fca21d9115203c1135e65b8703d533af761658a2","src/read/pe/data_directory.rs":"9c20dec2b52b26d0a80d2cdf9565c5298ea90e5b5b1001808abf56cdb25a7f8b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"59d2b02d1c1cbac649796b245f4e8c85fdfedf5ca0feab4524cc2004aae82927","src/read/pe/import.rs":"ad1a094a3608be6c17dcc7d8c9eae99f2628055f0550818657cb0b185b4fb35e","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"71f9b8c0aaf0c54a7ee3bd0a2135f72d48da8bda2b4e3550c17aa4cc22e0ac5f","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/write/coff.rs":"43413acdb221a985b7d4c4c326ee4a48c09bc3d7dc99162a16724b99c8abf3c9","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"6101aef4e2c65f0e41fa63c04f229950b173525110b86165aede792159004ec2","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"392e3a81ebb1694cd9e66eeb98f046731348030b0c1f45e4a22df52aad928b94","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"ed1bef4d599ba31ca7083f53cf8605a91e1dd0a3e755df9271d1417649230452","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"} +\ No newline at end of file ++{"files":{"CHANGELOG.md":"78aa23a55bd06448276854e3c19f984ff45098071dda36b27a0fb2e236630348","Cargo.toml":"4cdcbff917685fee9e3b4212583c2f1ea7a278b6fdb402ff18e314d57095a8b6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"3c5f153cecb269a4dbd5f0907951b1fe40e53054a9625bb75604e3b142ed45e3","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"7ca11076759d4b87b42657f866b0d2b1dd07d2536b19645da0a5da5dd713b77d","src/common.rs":"85dfbce1d99eb21feff95062ef39c9082ae4f277cb7f5d8703cc024c9e7060f5","src/elf.rs":"2b81f91e92b13e32e246d357ac6168b0e3d355f82bd8b6d0becaa8b3f97dfd37","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"22f3f5a5834821d144daf3b1993da1a2072ee57692321366da9c281de6d0a0fe","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"f14fe040751bdde66d8a39b53d145817ac131722c6d790f853bbcd764b1466b8","src/pod.rs":"9643a698e1388ad98d1e9ea074ca5b0b35599a2491a82e67a62ebcdc8cb19218","src/read/any.rs":"3c525fbe89144caf72ae0d55f5625b3be8476dcfa8a9203425f68fb087631c12","src/read/archive.rs":"987eaf577ec47f5b4ac4e91c697abad31c00ead02f3241dde4f74ce24a884b20","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"a2b0e3131c17e3b14def694342b119a215b017ac81c8538097bebe0ea3a6ecdd","src/read/elf/comdat.rs":"9c31a274e7b43bc27f9b82a67207b94eef2d07ef107c8e2ef7a1535fe7329f55","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"192adf7e082e9a702233f5012981b422408e55f0d8460cf39f8faa8fda0d6a5e","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"4ce50bfeaa6ae69c36458139a7699eac6542f448c786b5a102efd187b0fd5ddb","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"f0534940d8697d7bb66bc784dee0a3e2e173c2ff5266d03d7ad92b0b3efa15e1","src/read/elf/symbol.rs":"6d7361ed09d3829f6fed87f26d10746b4b8b1862579f94445683651f047b8b43","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"05e84f0a10958ef4e3828f388cd5d2fea95481ea89aeb80b76a2784c4208e4a1","src/read/macho/file.rs":"ee5e429abdaf6de167de2247679e13ce37724a6a0c50b8842302eb98d583bb71","src/read/macho/load_command.rs":"df976715bbc7699f7fdb8e9d388ba3e96a6d40c6a03b96c2696bd7c19786695a","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"e8c308113c48439a00777404fca21d9115203c1135e65b8703d533af761658a2","src/read/pe/data_directory.rs":"9c20dec2b52b26d0a80d2cdf9565c5298ea90e5b5b1001808abf56cdb25a7f8b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"59d2b02d1c1cbac649796b245f4e8c85fdfedf5ca0feab4524cc2004aae82927","src/read/pe/import.rs":"ad1a094a3608be6c17dcc7d8c9eae99f2628055f0550818657cb0b185b4fb35e","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"71f9b8c0aaf0c54a7ee3bd0a2135f72d48da8bda2b4e3550c17aa4cc22e0ac5f","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/write/coff.rs":"43413acdb221a985b7d4c4c326ee4a48c09bc3d7dc99162a16724b99c8abf3c9","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"93f003cdbd2fa87a049b3bcc3840c18cef69f97ac92d29dd157513d05f1fefd8","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"392e3a81ebb1694cd9e66eeb98f046731348030b0c1f45e4a22df52aad928b94","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"ed1bef4d599ba31ca7083f53cf8605a91e1dd0a3e755df9271d1417649230452","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"} +diff --git a/vendor/object/src/common.rs b/vendor/object/src/common.rs +index 20dde991a..39a3fa6fe 100644 +--- a/vendor/object/src/common.rs ++++ b/vendor/object/src/common.rs +@@ -13,7 +13,6 @@ pub enum Architecture { + #[allow(non_camel_case_types)] + X86_64_X32, + Hexagon, +- LoongArch64, + Mips, + Mips64, + Msp430, +@@ -24,6 +23,7 @@ pub enum Architecture { + S390x, + Sparc64, + Wasm32, ++ LoongArch64, + } + + impl Architecture { +@@ -41,7 +41,6 @@ impl Architecture { + Architecture::X86_64 => Some(AddressSize::U64), + Architecture::X86_64_X32 => Some(AddressSize::U32), + Architecture::Hexagon => Some(AddressSize::U32), +- Architecture::LoongArch64 => Some(AddressSize::U64), + Architecture::Mips => Some(AddressSize::U32), + Architecture::Mips64 => Some(AddressSize::U64), + Architecture::Msp430 => Some(AddressSize::U16), +@@ -52,6 +51,7 @@ impl Architecture { + Architecture::S390x => Some(AddressSize::U64), + Architecture::Sparc64 => Some(AddressSize::U64), + Architecture::Wasm32 => Some(AddressSize::U32), ++ Architecture::LoongArch64 => Some(AddressSize::U64), + } + } + } +diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs +index 9f6577269..9c0b91621 100644 +--- a/vendor/object/src/elf.rs ++++ b/vendor/object/src/elf.rs +@@ -574,10 +574,10 @@ pub const EM_RISCV: u16 = 243; + pub const EM_BPF: u16 = 247; + /// C-SKY + pub const EM_CSKY: u16 = 252; +-/// Loongson LoongArch +-pub const EM_LOONGARCH: u16 = 258; + /// Digital Alpha + pub const EM_ALPHA: u16 = 0x9026; ++/// LOONGARCH ++pub const EM_LOONGARCH: u16 = 258; + + // Values for `FileHeader*::e_version` and `Ident::version`. + /// Invalid ELF version. +@@ -6114,6 +6114,123 @@ pub const R_RISCV_SET32: u32 = 56; + #[allow(missing_docs)] + pub const R_RISCV_32_PCREL: u32 = 57; + ++//LOONGARCH values `FileHeader*::e_flags`. ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI: u32 = 0x0003; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LP64: u32 = 0x0003; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LPX32: u32 = 0x0002; ++#[allow(missing_docs)] ++pub const EF_LARCH_ABI_LP32: u32 = 0x0001; ++ ++// LOONGARCH values `Rel*::r_type`. ++/* Loongarch specific dynamic relocations. */ ++#[allow(missing_docs)] ++pub const R_LARCH_NONE: u32 = 0; ++#[allow(missing_docs)] ++pub const R_LARCH_32: u32 = 1; ++#[allow(missing_docs)] ++pub const R_LARCH_64: u32 = 2; ++#[allow(missing_docs)] ++pub const R_LARCH_RELATIVE: u32 = 3; ++#[allow(missing_docs)] ++pub const R_LARCH_COPY: u32 = 4; ++#[allow(missing_docs)] ++pub const R_LARCH_JUMP_SLOT: u32 = 5; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPMOD32: u32 = 6; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPMOD64: u32 = 7; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPREL32: u32 = 8; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_DTPREL64: u32 = 9; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_TPREL32: u32 = 10; ++#[allow(missing_docs)] ++pub const R_LARCH_TLS_TPREL64: u32 = 11; ++#[allow(missing_docs)] ++pub const R_LARCH_IRELATIVE: u32 = 12; ++#[allow(missing_docs)] ++pub const R_LARCH_MARK_LA: u32 = 20; ++#[allow(missing_docs)] ++pub const R_LARCH_MARK_PCREL: u32 = 21; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_ASSERT: u32 = 30; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_NOT: u32 = 31; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SUB: u32 = 32; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SL: u32 = 33; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_SR: u32 = 34; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_ADD: u32 = 35; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_AND: u32 = 36; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_IF_ELSE: u32 = 37; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; ++#[allow(missing_docs)] ++pub const R_LARCH_SOP_POP_32_U: u32 = 46; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD8: u32 = 47; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD16: u32 = 48; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD24: u32 = 49; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD32: u32 = 50; ++#[allow(missing_docs)] ++pub const R_LARCH_ADD64: u32 = 51; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB8: u32 = 52; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB16: u32 = 53; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB24: u32 = 54; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB32: u32 = 55; ++#[allow(missing_docs)] ++pub const R_LARCH_SUB64: u32 = 56; ++#[allow(missing_docs)] ++pub const R_LARCH_GNU_VTINHERIT: u32 = 57; ++#[allow(missing_docs)] ++pub const R_LARCH_GNU_VTENTRY: u32 = 58; ++ + // BPF values `Rel*::r_type`. + /// No reloc + pub const R_BPF_NONE: u32 = 0; +@@ -6250,129 +6367,6 @@ pub const R_NDS32_TLS_TPOFF: u32 = 102; + #[allow(missing_docs)] + pub const R_NDS32_TLS_DESC: u32 = 119; + +-// LoongArch values `FileHeader*::e_flags`. +-/// Uses 64-bit GPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_LP64S: u32 = 0x1; +-/// Uses 64-bit GPRs, 32-bit FPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_LP64F: u32 = 0x2; +-/// Uses 64-bit GPRs, 64-bit FPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_LP64D: u32 = 0x3; +-/// Uses 32-bit GPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_ILP32S: u32 = 0x5; +-/// Uses 32-bit GPRs, 32-bit FPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_ILP32F: u32 = 0x6; +-/// Uses 32-bit GPRs, 64-bit FPRs and the stack for parameter passing +-pub const EF_LARCH_ABI_ILP32D: u32 = 0x7; +- +-// LoongArch values `Rel*::r_type`. +-/// No reloc +-pub const R_LARCH_NONE: u32 = 0; +-/// Runtime address resolving +-pub const R_LARCH_32: u32 = 1; +-/// Runtime address resolving +-pub const R_LARCH_64: u32 = 2; +-/// Runtime fixup for load-address +-pub const R_LARCH_RELATIVE: u32 = 3; +-/// Runtime memory copy in executable +-pub const R_LARCH_COPY: u32 = 4; +-/// Runtime PLT supporting +-pub const R_LARCH_JUMP_SLOT: u32 = 5; +-/// Runtime relocation for TLS-GD +-pub const R_LARCH_TLS_DTPMOD32: u32 = 6; +-/// Runtime relocation for TLS-GD +-pub const R_LARCH_TLS_DTPMOD64: u32 = 7; +-/// Runtime relocation for TLS-GD +-pub const R_LARCH_TLS_DTPREL32: u32 = 8; +-/// Runtime relocation for TLS-GD +-pub const R_LARCH_TLS_DTPREL64: u32 = 9; +-/// Runtime relocation for TLE-IE +-pub const R_LARCH_TLS_TPREL32: u32 = 10; +-/// Runtime relocation for TLE-IE +-pub const R_LARCH_TLS_TPREL64: u32 = 11; +-/// Runtime local indirect function resolving +-pub const R_LARCH_IRELATIVE: u32 = 12; +-/// Mark la.abs: load absolute address for static link. +-pub const R_LARCH_MARK_LA: u32 = 20; +-/// Mark external label branch: access PC relative address for static link. +-pub const R_LARCH_MARK_PCREL: u32 = 21; +-/// Push PC-relative offset +-pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; +-/// Push constant or absolute address +-pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; +-/// Duplicate stack top +-pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; +-/// Push for access GOT entry +-pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; +-/// Push for TLS-LE +-pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; +-/// Push for TLS-IE +-pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; +-/// Push for TLS-GD +-pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; +-/// Push for external function calling +-pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; +-/// Assert stack top +-pub const R_LARCH_SOP_ASSERT: u32 = 30; +-/// Stack top logical not (unary) +-pub const R_LARCH_SOP_NOT: u32 = 31; +-/// Stack top subtraction (binary) +-pub const R_LARCH_SOP_SUB: u32 = 32; +-/// Stack top left shift (binary) +-pub const R_LARCH_SOP_SL: u32 = 33; +-/// Stack top right shift (binary) +-pub const R_LARCH_SOP_SR: u32 = 34; +-/// Stack top addition (binary) +-pub const R_LARCH_SOP_ADD: u32 = 35; +-/// Stack top bitwise and (binary) +-pub const R_LARCH_SOP_AND: u32 = 36; +-/// Stack top selection (tertiary) +-pub const R_LARCH_SOP_IF_ELSE: u32 = 37; +-/// Pop stack top to fill 5-bit signed immediate operand +-pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; +-/// Pop stack top to fill 12-bit unsigned immediate operand +-pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; +-/// Pop stack top to fill 12-bit signed immediate operand +-pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; +-/// Pop stack top to fill 16-bit signed immediate operand +-pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; +-/// Pop stack top to fill 18-bit signed immediate operand with two trailing +-/// zeros implied +-pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; +-/// Pop stack top to fill 20-bit signed immediate operand +-pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; +-/// Pop stack top to fill 23-bit signed immediate operand with two trailing +-/// zeros implied +-pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; +-/// Pop stack top to fill 28-bit signed immediate operand with two trailing +-/// zeros implied +-pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; +-/// Pop stack top to fill an instruction +-pub const R_LARCH_SOP_POP_32_U: u32 = 46; +-/// 8-bit in-place addition +-pub const R_LARCH_ADD8: u32 = 47; +-/// 16-bit in-place addition +-pub const R_LARCH_ADD16: u32 = 48; +-/// 24-bit in-place addition +-pub const R_LARCH_ADD24: u32 = 49; +-/// 32-bit in-place addition +-pub const R_LARCH_ADD32: u32 = 50; +-/// 64-bit in-place addition +-pub const R_LARCH_ADD64: u32 = 51; +-/// 8-bit in-place subtraction +-pub const R_LARCH_SUB8: u32 = 52; +-/// 16-bit in-place subtraction +-pub const R_LARCH_SUB16: u32 = 53; +-/// 24-bit in-place subtraction +-pub const R_LARCH_SUB24: u32 = 54; +-/// 32-bit in-place subtraction +-pub const R_LARCH_SUB32: u32 = 55; +-/// 64-bit in-place subtraction +-pub const R_LARCH_SUB64: u32 = 56; +-/// GNU C++ vtable hierarchy +-pub const R_LARCH_GNU_VTINHERIT: u32 = 57; +-/// GNU C++ vtable member usage +-pub const R_LARCH_GNU_VTENTRY: u32 = 58; +- + unsafe_impl_endian_pod!( + FileHeader32, + FileHeader64, +diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs +index 8c1fa4717..7541e8ebf 100644 +--- a/vendor/object/src/write/elf/object.rs ++++ b/vendor/object/src/write/elf/object.rs +@@ -74,7 +74,6 @@ impl<'a> Object<'a> { + Architecture::X86_64 => true, + Architecture::X86_64_X32 => true, + Architecture::Hexagon => true, +- Architecture::LoongArch64 => true, + Architecture::Mips => false, + Architecture::Mips64 => true, + Architecture::Msp430 => true, +@@ -84,6 +83,7 @@ impl<'a> Object<'a> { + Architecture::Riscv32 => true, + Architecture::S390x => true, + Architecture::Sparc64 => true, ++ Architecture::LoongArch64 => true, + _ => { + return Err(Error(format!( + "unimplemented architecture {:?}", +@@ -271,7 +271,6 @@ impl<'a> Object<'a> { + Architecture::X86_64 => elf::EM_X86_64, + Architecture::X86_64_X32 => elf::EM_X86_64, + Architecture::Hexagon => elf::EM_HEXAGON, +- Architecture::LoongArch64 => elf::EM_LOONGARCH, + Architecture::Mips => elf::EM_MIPS, + Architecture::Mips64 => elf::EM_MIPS, + Architecture::Msp430 => elf::EM_MSP430, +@@ -281,6 +280,7 @@ impl<'a> Object<'a> { + Architecture::Riscv64 => elf::EM_RISCV, + Architecture::S390x => elf::EM_S390, + Architecture::Sparc64 => elf::EM_SPARCV9, ++ Architecture::LoongArch64 => elf::EM_LOONGARCH, + _ => { + return Err(Error(format!( + "unimplemented architecture {:?}", +@@ -524,8 +524,7 @@ impl<'a> Object<'a> { + return Err(Error(format!("unimplemented relocation {:?}", reloc))); + } + }, +- Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) +- { ++ Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) { + (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, + (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, + (RelocationKind::Elf(x), _, _) => x, +-- +2.41.0 + diff --git a/0005-llvm-update-loongarch64-support.patch b/0005-llvm-update-loongarch64-support.patch new file mode 100644 index 0000000..10258a2 --- /dev/null +++ b/0005-llvm-update-loongarch64-support.patch @@ -0,0 +1,70995 @@ +From fdea5c854378f7722ec6443de42999ba83f9c086 Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Sun, 25 Jun 2023 16:27:22 +0800 +Subject: [PATCH 5/6] llvm: update loongarch64 support + +--- + .../readability/SimplifyBooleanExprCheck.cpp | 4 +- + .../clang-tools-extra/clangd/CodeComplete.cpp | 5 +- + .../clang-tools-extra/clangd/Headers.cpp | 26 +- + .../clang-tools-extra/clangd/Headers.h | 6 + + .../clang-tools-extra/clangd/InlayHints.cpp | 59 +- + .../clang-tools-extra/clangd/TidyProvider.cpp | 10 +- + .../clangd/index/CanonicalIncludes.cpp | 16 +- + .../clangd/test/lit.site.cfg.py.in | 1 + + .../clangd/unittests/CodeCompleteTests.cpp | 17 + + .../clangd/unittests/HeadersTests.cpp | 14 + + .../clangd/unittests/InlayHintTests.cpp | 9 + + ...y-bool-expr-chained-conditional-return.cpp | 11 + + src/llvm-project/clang/CMakeLists.txt | 1 + + src/llvm-project/clang/docs/ReleaseNotes.rst | 6 + + .../clang/lib/Basic/CMakeLists.txt | 4 + + src/llvm-project/clang/lib/CodeGen/CGStmt.cpp | 15 + + .../clang/lib/CodeGen/TargetInfo.cpp | 8 +- + .../clang/lib/Driver/ToolChains/Gnu.cpp | 40 +- + src/llvm-project/clang/lib/Sema/SemaInit.cpp | 8 +- + .../clang/lib/Sema/SemaLookup.cpp | 8 +- + src/llvm-project/clang/lib/Sema/SemaType.cpp | 3 + + .../lib/StaticAnalyzer/Core/ExprEngine.cpp | 6 + + .../clang/lib/Tooling/Syntax/Tokens.cpp | 222 +- + .../test/Analysis/template-param-objects.cpp | 33 + + .../clang/test/CodeGen/arm-vaarg.c | 23 + + .../test/CodeGen/attr-btf_type_tag-func-ptr.c | 15 + + .../test/CodeGen/debug-info-enum-case-val.c | 30 + + .../clang/test/Sema/gnu-builtins.c | 13 + + .../SemaCXX/specialization-diagnose-crash.cpp | 24 + + .../clang/unittests/Driver/ToolChainTest.cpp | 92 - + .../unittests/Tooling/Syntax/TokensTest.cpp | 56 + + .../cmake/Modules/FindLibEdit.cmake | 1 + + .../cmake/Modules/CompilerRTDarwinUtils.cmake | 2 +- + .../compiler-rt/cmake/config-ix.cmake | 2 +- + .../compiler-rt/lib/builtins/CMakeLists.txt | 2 +- + .../lib/sanitizer_common/sanitizer_common.h | 2 +- + .../sanitizer_common_interceptors.inc | 2 +- + .../sanitizer_common/sanitizer_stack_store.h | 2 +- + .../TestCases/Linux/sem_init_glibc.cpp | 43 +- + .../function.objects/func.blocks.arc.pass.mm | 89 + + .../vector.bool/ctor_exceptions.pass.cpp | 141 + + .../vector/vector.cons/exceptions.pass.cpp | 229 + + src/llvm-project/libunwind/CMakeLists.txt | 2 +- + src/llvm-project/libunwind/README_RUST_SGX.md | 22 - + .../libunwind/cmake/config-ix.cmake | 2 +- + .../libunwind/docs/BuildingLibunwind.rst | 5 - + .../libunwind/src/AddressSpace.hpp | 27 - + src/llvm-project/libunwind/src/CMakeLists.txt | 47 +- + src/llvm-project/libunwind/src/RWMutex.hpp | 2 +- + .../libunwind/src/UnwindRustSgx.c | 125 - + .../libunwind/src/UnwindRustSgx.h | 94 - + src/llvm-project/libunwind/src/config.h | 4 - + src/llvm-project/lld/CMakeLists.txt | 13 - + src/llvm-project/lld/COFF/CMakeLists.txt | 1 + + src/llvm-project/lld/Common/CMakeLists.txt | 9 +- + src/llvm-project/lld/ELF/Arch/RISCV.cpp | 6 +- + src/llvm-project/lld/ELF/Driver.cpp | 9 +- + src/llvm-project/lld/ELF/InputFiles.cpp | 6 +- + src/llvm-project/lld/ELF/InputSection.cpp | 11 +- + .../lld/ELF/SyntheticSections.cpp | 10 +- + .../lld/MachO/UnwindInfoSection.cpp | 35 +- + .../lld/MachO/UnwindInfoSection.h | 2 +- + src/llvm-project/lld/MachO/Writer.cpp | 2 +- + .../lld/test/ELF/comdat-binding2.s | 42 + + .../lld/test/ELF/lto-plugin-ignore.s | 2 + + .../test/MachO/eh-frame-personality-dedup.s | 43 + + src/llvm-project/lld/test/wasm/export-all.s | 7 +- + .../lld/test/wasm/mutable-global-exports.s | 7 +- + src/llvm-project/lld/wasm/Driver.cpp | 1 + + src/llvm-project/lld/wasm/Symbols.cpp | 1 + + src/llvm-project/lld/wasm/Symbols.h | 11 +- + src/llvm-project/lld/wasm/Writer.cpp | 16 +- + src/llvm-project/lldb/bindings/CMakeLists.txt | 2 - + .../lldb/bindings/interfaces.swig | 3 - + .../lldb/bindings/python/python-typemaps.swig | 2 +- + .../lldb/include/lldb/API/SBType.h | 2 + + .../lldb/include/lldb/Symbol/CompilerType.h | 24 +- + .../lldb/include/lldb/Symbol/TypeSystem.h | 14 +- + src/llvm-project/lldb/source/API/SBType.cpp | 12 +- + .../source/Plugins/Process/Linux/Perf.cpp | 31 +- + .../TypeSystem/Clang/TypeSystemClang.cpp | 81 +- + .../TypeSystem/Clang/TypeSystemClang.h | 19 +- + .../lldb/source/Symbol/CompilerType.cpp | 18 +- + .../lldb/source/Symbol/TypeSystem.cpp | 12 +- + .../TestTemplatePackArgs.py | 38 + + .../class-template-parameter-pack/main.cpp | 8 +- + .../tools/debugserver/source/CMakeLists.txt | 2 +- + .../unittests/Symbol/TestTypeSystemClang.cpp | 30 +- + src/llvm-project/llvm/CMakeLists.txt | 5 +- + src/llvm-project/llvm/cmake/config-ix.cmake | 4 +- + src/llvm-project/llvm/cmake/config.guess | 3 + + .../llvm/cmake/modules/AddLLVM.cmake | 1 + + .../llvm/cmake/modules/CheckAtomic.cmake | 13 + + .../llvm/cmake/modules/FindFFI.cmake | 2 +- + .../llvm/cmake/modules/FindTerminfo.cmake | 2 +- + .../llvm/cmake/modules/FindZ3.cmake | 3 +- + .../llvm/cmake/modules/Findzstd.cmake | 49 + + .../cmake/modules/HandleLLVMOptions.cmake | 2 +- + .../llvm/cmake/modules/LLVMConfig.cmake.in | 1 - + src/llvm-project/llvm/docs/ReleaseNotes.rst | 14 + + .../llvm/include/llvm/ADT/Triple.h | 11 + + .../llvm/include/llvm/BinaryFormat/ELF.h | 23 +- + .../llvm/include/llvm/IR/CMakeLists.txt | 1 + + .../llvm/include/llvm/IR/InlineAsm.h | 1 + + .../llvm/include/llvm/IR/Intrinsics.td | 1 + + .../include/llvm/IR/IntrinsicsLoongArch.td | 3657 +++++++ + .../llvm/lib/Analysis/ScalarEvolution.cpp | 7 +- + .../llvm/lib/Analysis/VectorUtils.cpp | 7 +- + .../llvm/lib/CodeGen/PrologEpilogInserter.cpp | 8 +- + .../llvm/lib/CodeGen/RegAllocFast.cpp | 3 + + .../lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 3 + + .../SelectionDAG/SelectionDAGBuilder.cpp | 1 + + .../CodeGen/TargetLoweringObjectFileImpl.cpp | 10 + + .../llvm/lib/CodeGen/TypePromotion.cpp | 4 +- + .../lib/DebugInfo/DWARF/DWARFVerifier.cpp | 6 +- + src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp | 2 +- + src/llvm-project/llvm/lib/IR/Function.cpp | 1 + + .../llvm/lib/MC/MCObjectFileInfo.cpp | 6 + + .../llvm/lib/Object/RelocationResolver.cpp | 26 + + .../llvm/lib/ObjectYAML/ELFYAML.cpp | 8 - + .../llvm/lib/Support/CMakeLists.txt | 21 +- + src/llvm-project/llvm/lib/Support/Triple.cpp | 1 + + .../lib/Support/UnicodeNameToCodepoint.cpp | 8 +- + .../llvm/lib/Support/Unix/Path.inc | 2 +- + .../llvm/lib/Support/Unix/Signals.inc | 4 - + .../llvm/lib/Support/Windows/Threading.inc | 6 - + .../llvm/lib/Support/X86TargetParser.cpp | 10 +- + .../Target/AArch64/AArch64ISelLowering.cpp | 67 +- + .../lib/Target/AArch64/AArch64ISelLowering.h | 2 +- + .../llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 + + .../lib/Target/ARM/ARMTargetTransformInfo.cpp | 2 +- + .../Target/LoongArch/AsmParser/CMakeLists.txt | 4 +- + .../AsmParser/LoongArchAsmParser.cpp | 2529 ++++- + .../llvm/lib/Target/LoongArch/CMakeLists.txt | 13 +- + .../LoongArch/Disassembler/CMakeLists.txt | 4 +- + .../Disassembler/LoongArchDisassembler.cpp | 921 +- + .../llvm/lib/Target/LoongArch/LoongArch.h | 37 +- + .../llvm/lib/Target/LoongArch/LoongArch.td | 166 +- + .../Target/LoongArch/LoongArch32InstrInfo.td | 717 ++ + .../Target/LoongArch/LoongArchAsmPrinter.cpp | 614 +- + .../Target/LoongArch/LoongArchAsmPrinter.h | 115 +- + .../lib/Target/LoongArch/LoongArchCCState.cpp | 165 + + .../lib/Target/LoongArch/LoongArchCCState.h | 165 + + .../Target/LoongArch/LoongArchCallingConv.td | 309 +- + .../LoongArch/LoongArchExpandPseudo.cpp | 2471 +++++ + .../LoongArch/LoongArchFloat32InstrInfo.td | 229 - + .../LoongArch/LoongArchFloat64InstrInfo.td | 242 - + .../LoongArch/LoongArchFloatInstrFormats.td | 241 - + .../LoongArch/LoongArchFrameLowering.cpp | 610 +- + .../Target/LoongArch/LoongArchFrameLowering.h | 61 +- + .../LoongArch/LoongArchISelDAGToDAG.cpp | 946 +- + .../Target/LoongArch/LoongArchISelDAGToDAG.h | 143 +- + .../LoongArch/LoongArchISelLowering.cpp | 8809 +++++++++++++++-- + .../Target/LoongArch/LoongArchISelLowering.h | 632 +- + .../Target/LoongArch/LoongArchInstrFormats.td | 842 +- + .../Target/LoongArch/LoongArchInstrInfo.cpp | 1067 +- + .../lib/Target/LoongArch/LoongArchInstrInfo.h | 220 +- + .../Target/LoongArch/LoongArchInstrInfo.td | 2646 +++-- + .../Target/LoongArch/LoongArchInstrInfoF.td | 630 ++ + .../LoongArch/LoongArchLASXInstrFormats.td | 448 + + .../LoongArch/LoongArchLASXInstrInfo.td | 5673 +++++++++++ + .../LoongArch/LoongArchLSXInstrFormats.td | 449 + + .../Target/LoongArch/LoongArchLSXInstrInfo.td | 5906 +++++++++++ + .../Target/LoongArch/LoongArchMCInstLower.cpp | 357 +- + .../Target/LoongArch/LoongArchMCInstLower.h | 55 + + .../LoongArch/LoongArchMachineFunction.cpp | 58 + + .../LoongArch/LoongArchMachineFunction.h | 103 + + .../LoongArch/LoongArchMachineFunctionInfo.h | 57 - + .../LoongArch/LoongArchModuleISelDAGToDAG.cpp | 53 + + .../LoongArch/LoongArchRegisterInfo.cpp | 376 +- + .../Target/LoongArch/LoongArchRegisterInfo.h | 62 +- + .../Target/LoongArch/LoongArchRegisterInfo.td | 484 +- + .../Target/LoongArch/LoongArchSubtarget.cpp | 99 +- + .../lib/Target/LoongArch/LoongArchSubtarget.h | 146 +- + .../LoongArch/LoongArchTargetMachine.cpp | 170 +- + .../Target/LoongArch/LoongArchTargetMachine.h | 34 +- + .../LoongArch/LoongArchTargetObjectFile.cpp | 26 + + .../LoongArch/LoongArchTargetObjectFile.h | 24 + + .../LoongArch/LoongArchTargetStreamer.h | 130 + + .../LoongArchTargetTransformInfo.cpp | 325 + + .../LoongArch/LoongArchTargetTransformInfo.h | 91 + + .../LoongArch/MCTargetDesc/CMakeLists.txt | 11 +- + .../MCTargetDesc/LoongArchABIInfo.cpp | 106 + + .../LoongArch/MCTargetDesc/LoongArchABIInfo.h | 76 + + .../LoongArchAnalyzeImmediate.cpp | 64 + + ...chMatInt.h => LoongArchAnalyzeImmediate.h} | 15 +- + .../MCTargetDesc/LoongArchAsmBackend.cpp | 202 +- + .../MCTargetDesc/LoongArchAsmBackend.h | 78 +- + .../MCTargetDesc/LoongArchBaseInfo.cpp | 40 - + .../MCTargetDesc/LoongArchBaseInfo.h | 134 +- + .../MCTargetDesc/LoongArchELFObjectWriter.cpp | 176 +- + .../MCTargetDesc/LoongArchELFStreamer.cpp | 138 + + .../MCTargetDesc/LoongArchELFStreamer.h | 53 + + .../MCTargetDesc/LoongArchFixupKinds.h | 90 + + .../MCTargetDesc/LoongArchInstPrinter.cpp | 237 +- + .../MCTargetDesc/LoongArchInstPrinter.h | 110 +- + .../MCTargetDesc/LoongArchMCAsmInfo.cpp | 33 +- + .../MCTargetDesc/LoongArchMCAsmInfo.h | 9 +- + .../MCTargetDesc/LoongArchMCCodeEmitter.cpp | 1480 ++- + .../MCTargetDesc/LoongArchMCCodeEmitter.h | 146 + + .../MCTargetDesc/LoongArchMCExpr.cpp | 158 + + .../LoongArch/MCTargetDesc/LoongArchMCExpr.h | 97 + + .../MCTargetDesc/LoongArchMCTargetDesc.cpp | 144 +- + .../MCTargetDesc/LoongArchMCTargetDesc.h | 28 +- + .../MCTargetDesc/LoongArchMatInt.cpp | 51 - + .../MCTargetDesc/LoongArchTargetStreamer.cpp | 330 + + .../LoongArch/TargetInfo/CMakeLists.txt | 1 - + .../TargetInfo/LoongArchTargetInfo.cpp | 18 +- + .../TargetInfo/LoongArchTargetInfo.h | 4 +- + .../llvm/lib/Target/Sparc/SparcCallingConv.td | 10 +- + .../lib/Target/Sparc/SparcISelLowering.cpp | 61 +- + .../llvm/lib/Target/Sparc/SparcISelLowering.h | 5 + + src/llvm-project/llvm/lib/Target/X86/X86.td | 1 - + .../llvm/lib/Transforms/IPO/GlobalOpt.cpp | 2 +- + .../InstCombine/InstCombineCalls.cpp | 4 + + .../ControlHeightReduction.cpp | 1 + + .../llvm/lib/Transforms/Scalar/SROA.cpp | 19 +- + .../lib/Transforms/Utils/LoopVersioning.cpp | 4 +- + .../llvm/lib/Transforms/Utils/VNCoercion.cpp | 4 +- + .../Transforms/Vectorize/LoopVectorize.cpp | 4 +- + .../llvm/lib/Transforms/Vectorize/VPlan.cpp | 2 +- + .../llvm/lib/Transforms/Vectorize/VPlan.h | 2 +- + .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 5 +- + src/llvm-project/llvm/test/CMakeLists.txt | 1 + + .../llvm/test/CodeGen/LoongArch/1ri.mir | 96 - + .../llvm/test/CodeGen/LoongArch/2r.mir | 230 - + .../llvm/test/CodeGen/LoongArch/2ri.mir | 432 - + .../llvm/test/CodeGen/LoongArch/3r.mir | 995 -- + .../llvm/test/CodeGen/LoongArch/3ri.mir | 69 - + .../llvm/test/CodeGen/LoongArch/align.ll | 8 + + .../CodeGen/LoongArch/atomic-operand-imm0.ll | 17 + + .../test/CodeGen/LoongArch/atomic_16_8.ll | 809 ++ + .../test/CodeGen/LoongArch/atomic_64_32.ll | 327 + + .../llvm/test/CodeGen/LoongArch/bss.ll | 5 + + .../LoongArch/builtins-loongarch-base.ll | 752 ++ + .../llvm/test/CodeGen/LoongArch/const-mult.ll | 245 + + .../CodeGen/LoongArch/disable-tail-calls.ll | 94 + + .../llvm/test/CodeGen/LoongArch/divrem.ll | 68 + + .../llvm/test/CodeGen/LoongArch/dup-tail.ll | 45 + + .../test/CodeGen/LoongArch/eliminateFI.ll | 106 + + .../CodeGen/LoongArch/emergency-spill-slot.ll | 103 + + .../llvm/test/CodeGen/LoongArch/fcopysign.ll | 17 + + .../llvm/test/CodeGen/LoongArch/frame-info.ll | 132 + + .../llvm/test/CodeGen/LoongArch/fsel.ll | 47 + + .../llvm/test/CodeGen/LoongArch/immediate.ll | 2542 +++++ + .../CodeGen/LoongArch/inlineasm/extra-code.ll | 8 + + .../inlineasm/floating-point-in-gpr.ll | 31 + + .../non-native-value-type-registers-error.ll | 8 + + .../non-native-value-type-registers.ll | 42 + + .../test/CodeGen/LoongArch/inlineasm/preld.ll | 8 + + .../test/CodeGen/LoongArch/jirl-verify.ll | 34 + + .../test/CodeGen/LoongArch/lasx/VExtend.ll | 54 + + .../CodeGen/LoongArch/lasx/imm_vector_lasx.ll | 176 + + .../test/CodeGen/LoongArch/lasx/inline-asm.ll | 55 + + .../CodeGen/LoongArch/lasx/insert-lasx.ll | 38 + + .../CodeGen/LoongArch/lasx/intrinsic-lasx.ll | 70 + + .../test/CodeGen/LoongArch/lasx/lasxvclr.ll | 46 + + .../test/CodeGen/LoongArch/lasx/logic-lasx.ll | 130 + + .../test/CodeGen/LoongArch/lasx/set-lasx.ll | 38 + + .../LoongArch/lasx/shuffle_v4i64_1032.ll | 19 + + .../test/CodeGen/LoongArch/lasx/vext2xv.ll | 65 + + .../test/CodeGen/LoongArch/lasx/xvadda.ll | 62 + + .../test/CodeGen/LoongArch/lasx/xvaddsub.ll | 98 + + .../test/CodeGen/LoongArch/lasx/xvhadd.ll | 21 + + .../test/CodeGen/LoongArch/lasx/xvilvh.ll | 32 + + .../test/CodeGen/LoongArch/lasx/xvilvl.ll | 32 + + .../llvm/test/CodeGen/LoongArch/ldptr.ll | 70 + + .../llvm/test/CodeGen/LoongArch/lit.local.cfg | 12 +- + .../llvm/test/CodeGen/LoongArch/logic-op.ll | 171 + + .../llvm/test/CodeGen/LoongArch/lshr.ll | 12 + + .../CodeGen/LoongArch/lsx/imm_vector_lsx.ll | 176 + + .../test/CodeGen/LoongArch/lsx/inline-asm.ll | 34 + + .../CodeGen/LoongArch/lsx/intrinsic-lsx.ll | 92 + + .../test/CodeGen/LoongArch/lsx/logic-lsx.ll | 132 + + .../test/CodeGen/LoongArch/lsx/lsxvclr.ll | 50 + + .../test/CodeGen/LoongArch/lsx/set-lsx.ll | 38 + + .../llvm/test/CodeGen/LoongArch/lsx/vadda.ll | 62 + + .../llvm/test/CodeGen/LoongArch/lu12i.ll | 7 + + .../llvm/test/CodeGen/LoongArch/mcpu_load.ll | 72 + + .../llvm/test/CodeGen/LoongArch/misc.mir | 200 - + .../test/CodeGen/LoongArch/named-register.ll | 29 + + .../llvm/test/CodeGen/LoongArch/nomerge.ll | 35 + + .../llvm/test/CodeGen/LoongArch/noti32.ll | 143 + + .../LoongArch/peephole-load-store-addi.ll | 100 + + .../llvm/test/CodeGen/LoongArch/signext.ll | 37 + + .../llvm/test/CodeGen/LoongArch/stptr.ll | 52 + + .../llvm/test/CodeGen/LoongArch/tailcall-R.ll | 62 + + .../test/CodeGen/LoongArch/tailcall-check.ll | 155 + + .../test/CodeGen/LoongArch/tailcall-mem.ll | 35 + + .../llvm/test/CodeGen/LoongArch/tailcall.ll | 13 + + .../test/CodeGen/LoongArch/thread-pointer.ll | 9 + + .../llvm/test/CodeGen/LoongArch/trunc.ll | 108 + + .../test/CodeGen/LoongArch/unalignment.ll | 72 + + .../PowerPC/regalloc-fast-debug-spill.ll | 250 + + .../llvm/test/CodeGen/SPARC/bigreturn.ll | 254 + + .../CodeGen/X86/zero-call-used-regs-i386.ll | 112 + + .../llvm/test/MC/LoongArch/aligned-nops.s | 25 + + .../llvm/test/MC/LoongArch/atomic-error.s | 7 + + .../llvm/test/MC/LoongArch/atomic.s | 12 + + .../llvm/test/MC/LoongArch/fixups-expr.s | 40 + + .../llvm/test/MC/LoongArch/invalid.s | 50 + + .../llvm/test/MC/LoongArch/lit.local.cfg | 1 + + .../llvm/test/MC/LoongArch/macro-la.s | 168 + + .../llvm/test/MC/LoongArch/macro-li.s | 773 ++ + .../llvm/test/MC/LoongArch/valid_12imm.s | 33 + + .../llvm/test/MC/LoongArch/valid_4operands.s | 53 + + .../llvm/test/MC/LoongArch/valid_bigimm.s | 33 + + .../llvm/test/MC/LoongArch/valid_branch.s | 155 + + .../llvm/test/MC/LoongArch/valid_float.s | 297 + + .../llvm/test/MC/LoongArch/valid_integer.s | 369 + + .../llvm/test/MC/LoongArch/valid_memory.s | 405 + + .../llvm/test/MC/LoongArch/valid_priv.s | 125 + + .../test/Support/unix03-sigpipe-exit.test | 26 - + .../AtomicExpand/LoongArch/lit.local.cfg | 5 - + .../Transforms/GlobalOpt/inalloca-varargs.ll | 38 + + .../test/Transforms/InstCombine/cast-byval.ll | 31 + + .../versioning-scev-invalidation.ll | 125 + + ...interleave-allocsize-not-equal-typesize.ll | 141 + + .../phi-speculate-different-load-types.ll | 41 + + .../loongarch_function_name.ll.expected | 6 +- + ...arch_generated_funcs.ll.generated.expected | 148 - + ...ch_generated_funcs.ll.nogenerated.expected | 147 - + .../loongarch_generated_funcs.test | 17 - + .../llvm-readobj/ELF/loongarch-eflags.test | 64 - + .../tools/obj2yaml/ELF/loongarch-eflags.yaml | 29 - + .../llvm/tools/dsymutil/CMakeLists.txt | 4 +- + .../llvm/tools/llvm-config/CMakeLists.txt | 8 +- + .../llvm/tools/llvm-readobj/ELFDumper.cpp | 15 - + .../clang-tidy/misc/BUILD.gn | 2 +- + .../llvm/utils/gn/secondary/llvm/version.gni | 2 +- + .../llvm/utils/lit/lit/__init__.py | 2 +- + .../llvm/utils/lit/lit/llvm/config.py | 2 +- + 332 files changed, 57210 insertions(+), 7989 deletions(-) + create mode 100644 src/llvm-project/clang/test/Analysis/template-param-objects.cpp + create mode 100644 src/llvm-project/clang/test/CodeGen/arm-vaarg.c + create mode 100644 src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c + create mode 100644 src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c + create mode 100644 src/llvm-project/clang/test/Sema/gnu-builtins.c + create mode 100644 src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp + create mode 100644 src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm + create mode 100644 src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp + create mode 100644 src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp + delete mode 100644 src/llvm-project/libunwind/README_RUST_SGX.md + delete mode 100644 src/llvm-project/libunwind/src/UnwindRustSgx.c + delete mode 100644 src/llvm-project/libunwind/src/UnwindRustSgx.h + create mode 100644 src/llvm-project/lld/test/ELF/comdat-binding2.s + create mode 100644 src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s + create mode 100644 src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py + create mode 100644 src/llvm-project/llvm/cmake/modules/Findzstd.cmake + create mode 100644 src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp + rename src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/{LoongArchMatInt.h => LoongArchAnalyzeImmediate.h} (62%) + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h + delete mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp + create mode 100644 src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll + delete mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll + create mode 100644 src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/atomic.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/invalid.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/macro-la.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/macro-li.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_float.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s + create mode 100644 src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s + delete mode 100644 src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test + delete mode 100644 src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg + create mode 100644 src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll + create mode 100644 src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll + create mode 100644 src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll + create mode 100644 src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll + create mode 100644 src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll + delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected + delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected + delete mode 100644 src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test + delete mode 100644 src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test + delete mode 100644 src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml + +diff --git a/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +index 8ae990a92..afb4a1044 100644 +--- a/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp ++++ b/src/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +@@ -472,8 +472,8 @@ public: + checkSingleStatement(If->getThen(), parseReturnLiteralBool); + if (ThenReturnBool && + ThenReturnBool.Bool != TrailingReturnBool.Bool) { +- if (Check->ChainedConditionalReturn || +- (!PrevIf && If->getElse() == nullptr)) { ++ if ((Check->ChainedConditionalReturn || !PrevIf) && ++ If->getElse() == nullptr) { + Check->replaceCompoundReturnWithCondition( + Context, cast(*Second), TrailingReturnBool.Bool, + If, ThenReturnBool.Item); +diff --git a/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp b/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp +index edbb1722a..55982f412 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/CodeComplete.cpp +@@ -486,6 +486,9 @@ private: + // we need to complete 'forward<$1>($0)'. + return "($0)"; + ++ if (Snippet->empty()) ++ return ""; ++ + bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function || + Completion.Kind == CompletionItemKind::Method || + Completion.Kind == CompletionItemKind::Constructor || +@@ -524,8 +527,6 @@ private: + return *Snippet; + + // Replace argument snippets with a simplified pattern. +- if (Snippet->empty()) +- return ""; + if (MayHaveArgList) { + // Functions snippets can be of 2 types: + // - containing only function arguments, e.g. +diff --git a/src/llvm-project/clang-tools-extra/clangd/Headers.cpp b/src/llvm-project/clang-tools-extra/clangd/Headers.cpp +index cb7abac3e..af22a446b 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/Headers.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/Headers.cpp +@@ -22,9 +22,17 @@ + namespace clang { + namespace clangd { + +-const char IWYUPragmaKeep[] = "// IWYU pragma: keep"; +-const char IWYUPragmaExport[] = "// IWYU pragma: export"; +-const char IWYUPragmaBeginExports[] = "// IWYU pragma: begin_exports"; ++llvm::Optional parseIWYUPragma(const char *Text) { ++ // This gets called for every comment seen in the preamble, so it's quite hot. ++ constexpr llvm::StringLiteral IWYUPragma = "// IWYU pragma: "; ++ if (strncmp(Text, IWYUPragma.data(), IWYUPragma.size())) ++ return llvm::None; ++ Text += IWYUPragma.size(); ++ const char *End = Text; ++ while (*End != 0 && *End != '\n') ++ ++End; ++ return StringRef(Text, End - Text); ++} + + class IncludeStructure::RecordHeaders : public PPCallbacks, + public CommentHandler { +@@ -129,10 +137,10 @@ public: + } + + bool HandleComment(Preprocessor &PP, SourceRange Range) override { +- bool Err = false; +- llvm::StringRef Text = SM.getCharacterData(Range.getBegin(), &Err); +- if (Err) ++ auto Pragma = parseIWYUPragma(SM.getCharacterData(Range.getBegin())); ++ if (!Pragma) + return false; ++ + if (inMainFile()) { + // Given: + // +@@ -150,8 +158,7 @@ public: + // will know that the next inclusion is behind the IWYU pragma. + // FIXME: Support "IWYU pragma: begin_exports" and "IWYU pragma: + // end_exports". +- if (!Text.startswith(IWYUPragmaExport) && +- !Text.startswith(IWYUPragmaKeep)) ++ if (!Pragma->startswith("export") && !Pragma->startswith("keep")) + return false; + unsigned Offset = SM.getFileOffset(Range.getBegin()); + LastPragmaKeepInMainFileLine = +@@ -161,8 +168,7 @@ public: + // does not support them properly yet, so they will be not marked as + // unused. + // FIXME: Once IncludeCleaner supports export pragmas, remove this. +- if (!Text.startswith(IWYUPragmaExport) && +- !Text.startswith(IWYUPragmaBeginExports)) ++ if (!Pragma->startswith("export") && !Pragma->startswith("begin_exports")) + return false; + Out->HasIWYUExport.insert( + *Out->getID(SM.getFileEntryForID(SM.getFileID(Range.getBegin())))); +diff --git a/src/llvm-project/clang-tools-extra/clangd/Headers.h b/src/llvm-project/clang-tools-extra/clangd/Headers.h +index ff3f06316..ba72ad397 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/Headers.h ++++ b/src/llvm-project/clang-tools-extra/clangd/Headers.h +@@ -35,6 +35,12 @@ namespace clangd { + /// Returns true if \p Include is literal include like "path" or . + bool isLiteralInclude(llvm::StringRef Include); + ++/// If Text begins an Include-What-You-Use directive, returns it. ++/// Given "// IWYU pragma: keep", returns "keep". ++/// Input is a null-terminated char* as provided by SM.getCharacterData(). ++/// (This should not be StringRef as we do *not* want to scan for its length). ++llvm::Optional parseIWYUPragma(const char *Text); ++ + /// Represents a header file to be #include'd. + struct HeaderFile { + std::string File; +diff --git a/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp b/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp +index 7be05fbc3..16c6b1cec 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/InlayHints.cpp +@@ -10,6 +10,7 @@ + #include "Config.h" + #include "HeuristicResolver.h" + #include "ParsedAST.h" ++#include "SourceCode.h" + #include "clang/AST/Decl.h" + #include "clang/AST/DeclarationName.h" + #include "clang/AST/ExprCXX.h" +@@ -192,8 +193,8 @@ class InlayHintVisitor : public RecursiveASTVisitor { + public: + InlayHintVisitor(std::vector &Results, ParsedAST &AST, + const Config &Cfg, llvm::Optional RestrictRange) +- : Results(Results), AST(AST.getASTContext()), Cfg(Cfg), +- RestrictRange(std::move(RestrictRange)), ++ : Results(Results), AST(AST.getASTContext()), Tokens(AST.getTokens()), ++ Cfg(Cfg), RestrictRange(std::move(RestrictRange)), + MainFileID(AST.getSourceManager().getMainFileID()), + Resolver(AST.getHeuristicResolver()), + TypeHintPolicy(this->AST.getPrintingPolicy()), +@@ -227,8 +228,7 @@ public: + return true; + } + +- processCall(E->getParenOrBraceRange().getBegin(), E->getConstructor(), +- {E->getArgs(), E->getNumArgs()}); ++ processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()}); + return true; + } + +@@ -254,7 +254,7 @@ public: + if (!Callee) + return true; + +- processCall(E->getRParenLoc(), Callee, {E->getArgs(), E->getNumArgs()}); ++ processCall(Callee, {E->getArgs(), E->getNumArgs()}); + return true; + } + +@@ -278,11 +278,11 @@ public: + return true; + } + +- void addReturnTypeHint(FunctionDecl *D, SourceLocation Loc) { ++ void addReturnTypeHint(FunctionDecl *D, SourceRange Range) { + auto *AT = D->getReturnType()->getContainedAutoType(); + if (!AT || AT->getDeducedType().isNull()) + return; +- addTypeHint(Loc, D->getReturnType(), /*Prefix=*/"-> "); ++ addTypeHint(Range, D->getReturnType(), /*Prefix=*/"-> "); + } + + bool VisitVarDecl(VarDecl *D) { +@@ -375,21 +375,11 @@ public: + private: + using NameVec = SmallVector; + +- // The purpose of Anchor is to deal with macros. It should be the call's +- // opening or closing parenthesis or brace. (Always using the opening would +- // make more sense but CallExpr only exposes the closing.) We heuristically +- // assume that if this location does not come from a macro definition, then +- // the entire argument list likely appears in the main file and can be hinted. +- void processCall(SourceLocation Anchor, const FunctionDecl *Callee, ++ void processCall(const FunctionDecl *Callee, + llvm::ArrayRef Args) { + if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee) + return; + +- // If the anchor location comes from a macro defintion, there's nowhere to +- // put hints. +- if (!AST.getSourceManager().getTopMacroCallerLoc(Anchor).isFileID()) +- return; +- + // The parameter name of a move or copy constructor is not very interesting. + if (auto *Ctor = dyn_cast(Callee)) + if (Ctor->isCopyOrMoveConstructor()) +@@ -637,25 +627,33 @@ private: + #undef CHECK_KIND + } + +- auto FileRange = +- toHalfOpenFileRange(AST.getSourceManager(), AST.getLangOpts(), R); +- if (!FileRange) ++ auto LSPRange = getHintRange(R); ++ if (!LSPRange) + return; +- Range LSPRange{ +- sourceLocToPosition(AST.getSourceManager(), FileRange->getBegin()), +- sourceLocToPosition(AST.getSourceManager(), FileRange->getEnd())}; +- Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end; ++ Position LSPPos = Side == HintSide::Left ? LSPRange->start : LSPRange->end; + if (RestrictRange && + (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end))) + return; +- // The hint may be in a file other than the main file (for example, a header +- // file that was included after the preamble), do not show in that case. +- if (!AST.getSourceManager().isWrittenInMainFile(FileRange->getBegin())) +- return; + bool PadLeft = Prefix.consume_front(" "); + bool PadRight = Suffix.consume_back(" "); + Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, +- PadLeft, PadRight, LSPRange}); ++ PadLeft, PadRight, *LSPRange}); ++ } ++ ++ // Get the range of the main file that *exactly* corresponds to R. ++ llvm::Optional getHintRange(SourceRange R) { ++ const auto &SM = AST.getSourceManager(); ++ auto Spelled = Tokens.spelledForExpanded(Tokens.expandedTokens(R)); ++ // TokenBuffer will return null if e.g. R corresponds to only part of a ++ // macro expansion. ++ if (!Spelled || Spelled->empty()) ++ return llvm::None; ++ // Hint must be within the main file, not e.g. a non-preamble include. ++ if (SM.getFileID(Spelled->front().location()) != SM.getMainFileID() || ++ SM.getFileID(Spelled->back().location()) != SM.getMainFileID()) ++ return llvm::None; ++ return Range{sourceLocToPosition(SM, Spelled->front().location()), ++ sourceLocToPosition(SM, Spelled->back().endLocation())}; + } + + void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) { +@@ -680,6 +678,7 @@ private: + + std::vector &Results; + ASTContext &AST; ++ const syntax::TokenBuffer &Tokens; + const Config &Cfg; + llvm::Optional RestrictRange; + FileID MainFileID; +diff --git a/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp b/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp +index 32a4d6a30..a0a37e86b 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/TidyProvider.cpp +@@ -212,8 +212,14 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { + // code, which is often the case when clangd + // tries to build an AST. + "-bugprone-use-after-move", +- // Alias for bugprone-use-after-moe. +- "-hicpp-invalid-access-moved"); ++ // Alias for bugprone-use-after-move. ++ "-hicpp-invalid-access-moved", ++ ++ // ----- Performance problems ----- ++ ++ // This check runs expensive analysis for each variable. ++ // It has been observed to increase reparse time by 10x. ++ "-misc-const-correctness"); + + size_t Size = BadChecks.size(); + for (const std::string &Str : ExtraBadChecks) { +diff --git a/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp b/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp +index 145d98d57..bbc80e7e0 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/index/CanonicalIncludes.cpp +@@ -17,8 +17,6 @@ + namespace clang { + namespace clangd { + namespace { +-const char IWYUPragma[] = "// IWYU pragma: private, include "; +- + const std::pair IncludeMappings[] = { + {"include/__stddef_max_align_t.h", ""}, + {"include/__wmmintrin_aes.h", ""}, +@@ -712,17 +710,17 @@ collectIWYUHeaderMaps(CanonicalIncludes *Includes) { + PragmaCommentHandler(CanonicalIncludes *Includes) : Includes(Includes) {} + + bool HandleComment(Preprocessor &PP, SourceRange Range) override { +- llvm::StringRef Text = +- Lexer::getSourceText(CharSourceRange::getCharRange(Range), +- PP.getSourceManager(), PP.getLangOpts()); +- if (!Text.consume_front(IWYUPragma)) ++ auto Pragma = parseIWYUPragma( ++ PP.getSourceManager().getCharacterData(Range.getBegin())); ++ if (!Pragma || !Pragma->consume_front("private, include ")) + return false; + auto &SM = PP.getSourceManager(); + // We always insert using the spelling from the pragma. + if (auto *FE = SM.getFileEntryForID(SM.getFileID(Range.getBegin()))) +- Includes->addMapping( +- FE->getLastRef(), +- isLiteralInclude(Text) ? Text.str() : ("\"" + Text + "\"").str()); ++ Includes->addMapping(FE->getLastRef(), ++ isLiteralInclude(*Pragma) ++ ? Pragma->str() ++ : ("\"" + *Pragma + "\"").str()); + return false; + } + +diff --git a/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in b/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in +index 20caa72af..1fe7c8d0f 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in ++++ b/src/llvm-project/clang-tools-extra/clangd/test/lit.site.cfg.py.in +@@ -10,6 +10,7 @@ config.python_executable = "@Python3_EXECUTABLE@" + config.clang_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@") + config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") + config.llvm_libs_dir = lit_config.substitute("@LLVM_LIBS_DIR@") ++config.llvm_shlib_dir = "@SHLIBDIR@" + + config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.." + config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.." +diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +index 5050ab203..079a4ec70 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +@@ -1014,6 +1014,23 @@ TEST(CodeCompleteTest, NoColonColonAtTheEnd) { + EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::")))); + } + ++TEST(CompletionTests, EmptySnippetDoesNotCrash) { ++ // See https://github.com/clangd/clangd/issues/1216 ++ auto Results = completions(R"cpp( ++ int main() { ++ auto w = [&](auto &&f) { return f(f); }; ++ auto f = w([&](auto &&f) { ++ return [&](auto &&n) { ++ if (n == 0) { ++ return 1; ++ } ++ return n * ^(f)(n - 1); ++ }; ++ })(10); ++ } ++ )cpp"); ++} ++ + TEST(CompletionTest, BacktrackCrashes) { + // Sema calls code completion callbacks twice in these cases. + auto Results = completions(R"cpp( +diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp +index 32e4aea15..324d4b58a 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/unittests/HeadersTests.cpp +@@ -9,6 +9,7 @@ + #include "Headers.h" + + #include "Compiler.h" ++#include "Matchers.h" + #include "TestFS.h" + #include "TestTU.h" + #include "clang/Basic/TokenKinds.h" +@@ -30,6 +31,7 @@ namespace { + using ::testing::AllOf; + using ::testing::Contains; + using ::testing::ElementsAre; ++using ::testing::Eq; + using ::testing::IsEmpty; + using ::testing::Not; + using ::testing::UnorderedElementsAre; +@@ -445,6 +447,18 @@ TEST_F(HeadersTest, HasIWYUPragmas) { + EXPECT_FALSE(Includes.hasIWYUExport(getID("none.h", Includes))); + } + ++TEST(Headers, ParseIWYUPragma) { ++ EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), HasValue(Eq("keep"))); ++ EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep\netc"), ++ HasValue(Eq("keep"))); ++ EXPECT_EQ(parseIWYUPragma("/* IWYU pragma: keep"), llvm::None) ++ << "Only // comments supported!"; ++ EXPECT_EQ(parseIWYUPragma("// IWYU pragma: keep"), llvm::None) ++ << "Sensitive to whitespace"; ++ EXPECT_EQ(parseIWYUPragma("// IWYU pragma:keep"), llvm::None) ++ << "Sensitive to whitespace"; ++} ++ + } // namespace + } // namespace clangd + } // namespace clang +diff --git a/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +index a429c0899..7127f6cc5 100644 +--- a/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp ++++ b/src/llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +@@ -820,6 +820,15 @@ TEST(ParameterHints, Macros) { + } + )cpp", + ExpectedHint{"param: ", "param"}); ++ ++ // If the macro expands to multiple arguments, don't hint it. ++ assertParameterHints(R"cpp( ++ void foo(double x, double y); ++ #define CONSTANTS 3.14, 2.72 ++ void bar() { ++ foo(CONSTANTS); ++ } ++ )cpp"); + } + + TEST(ParameterHints, ConstructorParens) { +diff --git a/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp b/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp +index 7e97e9f71..ff50528c2 100644 +--- a/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp ++++ b/src/llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp +@@ -92,3 +92,14 @@ bool complex_chained_if_return_return_negated(int i) { + // CHECK-FIXES: {{^}} }{{$}} + // CHECK-FIXES: {{^ return i <= 10;$}} + // CHECK-FIXES: {{^}$}} ++ ++ ++bool PR57819(int x) { ++ // False positive introduced in clang-tidy-15 ++ // Expect no warning here. ++ if (x > 0) ++ return false; ++ else { ++ } ++ return true; ++} +diff --git a/src/llvm-project/clang/CMakeLists.txt b/src/llvm-project/clang/CMakeLists.txt +index 13d76e7fd..e3bc4b468 100644 +--- a/src/llvm-project/clang/CMakeLists.txt ++++ b/src/llvm-project/clang/CMakeLists.txt +@@ -117,6 +117,7 @@ if(CLANG_BUILT_STANDALONE) + include(TableGen) + include(HandleLLVMOptions) + include(VersionFromVCS) ++ include(CheckAtomic) + include(GetErrcMessages) + include(LLVMDistributionSupport) + +diff --git a/src/llvm-project/clang/docs/ReleaseNotes.rst b/src/llvm-project/clang/docs/ReleaseNotes.rst +index a17b033f5..13cca2ebb 100644 +--- a/src/llvm-project/clang/docs/ReleaseNotes.rst ++++ b/src/llvm-project/clang/docs/ReleaseNotes.rst +@@ -225,6 +225,12 @@ Bug Fixes + - Fix a crash when generating code coverage information for an + ``if consteval`` statement. This fixes + `Issue 57377 `_. ++- Fix a crash when a ``btf_type_tag`` attribute is applied to the pointee of ++ a function pointer. ++- Clang 14 predeclared some builtin POSIX library functions in ``gnu2x`` mode, ++ and Clang 15 accidentally stopped predeclaring those functions in that ++ language mode. Clang 16 now predeclares those functions again. This fixes ++ `Issue 56607 `_. + + Improvements to Clang's diagnostics + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +diff --git a/src/llvm-project/clang/lib/Basic/CMakeLists.txt b/src/llvm-project/clang/lib/Basic/CMakeLists.txt +index 3e052c0cf..c38c9fddb 100644 +--- a/src/llvm-project/clang/lib/Basic/CMakeLists.txt ++++ b/src/llvm-project/clang/lib/Basic/CMakeLists.txt +@@ -110,3 +110,7 @@ add_clang_library(clangBasic + omp_gen + ) + ++target_link_libraries(clangBasic ++ PRIVATE ++ ${LLVM_ATOMIC_LIB} ++) +diff --git a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp +index 481438de0..9935fcc0d 100644 +--- a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp ++++ b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp +@@ -1509,6 +1509,21 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S, + + llvm::ConstantInt *CaseVal = + Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); ++ ++ // Emit debuginfo for the case value if it is an enum value. ++ const ConstantExpr *CE; ++ if (auto ICE = dyn_cast(S.getLHS())) ++ CE = dyn_cast(ICE->getSubExpr()); ++ else ++ CE = dyn_cast(S.getLHS()); ++ if (CE) { ++ if (auto DE = dyn_cast(CE->getSubExpr())) ++ if (CGDebugInfo *Dbg = getDebugInfo()) ++ if (CGM.getCodeGenOpts().hasReducedDebugInfo()) ++ Dbg->EmitGlobalVariable(DE->getDecl(), ++ APValue(llvm::APSInt(CaseVal->getValue()))); ++ } ++ + if (SwitchLikelihood) + SwitchLikelihood->push_back(Stmt::getLikelihood(Attrs)); + +diff --git a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp +index 36e10e4df..44743fa02 100644 +--- a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp ++++ b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp +@@ -7047,10 +7047,10 @@ Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, + + // Empty records are ignored for parameter passing purposes. + if (isEmptyRecord(getContext(), Ty, true)) { +- Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr), +- getVAListElementType(CGF), SlotSize); +- Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); +- return Addr; ++ VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy); ++ auto *Load = CGF.Builder.CreateLoad(VAListAddr); ++ Address Addr = Address(Load, CGF.Int8Ty, SlotSize); ++ return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); + } + + CharUnits TySize = getContext().getTypeSizeInChars(Ty); +diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp +index f203cae1d..665cdc313 100644 +--- a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp ++++ b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp +@@ -2139,31 +2139,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( + // and gcc-toolsets. + if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux && + D.getVFS().exists("/opt/rh")) { +- // Find the directory in /opt/rh/ starting with gcc-toolset-* or +- // devtoolset-* with the highest version number and add that +- // one to our prefixes. +- std::string ChosenToolsetDir; +- unsigned ChosenToolsetVersion = 0; +- std::error_code EC; +- for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC), +- LE; +- !EC && LI != LE; LI = LI.increment(EC)) { +- StringRef ToolsetDir = llvm::sys::path::filename(LI->path()); +- unsigned ToolsetVersion; +- if ((!ToolsetDir.startswith("gcc-toolset-") && +- !ToolsetDir.startswith("devtoolset-")) || +- ToolsetDir.substr(ToolsetDir.rfind('-') + 1) +- .getAsInteger(10, ToolsetVersion)) +- continue; +- +- if (ToolsetVersion > ChosenToolsetVersion) { +- ChosenToolsetVersion = ToolsetVersion; +- ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str(); +- } +- } +- +- if (ChosenToolsetVersion > 0) +- Prefixes.push_back(ChosenToolsetDir + "/root/usr"); ++ // TODO: We may want to remove this, since the functionality ++ // can be achieved using config files. ++ Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr"); ++ Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr"); ++ Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-12/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-11/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-10/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-9/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-8/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-7/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); ++ Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); + } + + // Fall back to /usr which is used by most non-Solaris systems. +diff --git a/src/llvm-project/clang/lib/Sema/SemaInit.cpp b/src/llvm-project/clang/lib/Sema/SemaInit.cpp +index d3b454843..bf7ca718a 100644 +--- a/src/llvm-project/clang/lib/Sema/SemaInit.cpp ++++ b/src/llvm-project/clang/lib/Sema/SemaInit.cpp +@@ -695,10 +695,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, + // member of reference type uninitialized, the program is + // ill-formed. + SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) +- << Field->getType() +- << ILE->getSyntacticForm()->getSourceRange(); +- SemaRef.Diag(Field->getLocation(), +- diag::note_uninit_reference_member); ++ << Field->getType() ++ << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm()) ++ ->getSourceRange(); ++ SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); + } + hadError = true; + return; +diff --git a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp +index 68158ec97..5d0d87fd2 100644 +--- a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp ++++ b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp +@@ -939,11 +939,9 @@ bool Sema::LookupBuiltin(LookupResult &R) { + + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) { +- // In C++, C2x, and OpenCL (spec v1.2 s6.9.f), we don't have any +- // predefined library functions like 'malloc'. Instead, we'll just +- // error. +- if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL || +- getLangOpts().C2x) && ++ // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined ++ // library functions like 'malloc'. Instead, we'll just error. ++ if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL) && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return false; + +diff --git a/src/llvm-project/clang/lib/Sema/SemaType.cpp b/src/llvm-project/clang/lib/Sema/SemaType.cpp +index 3ab5d26a9..edcac4d2e 100644 +--- a/src/llvm-project/clang/lib/Sema/SemaType.cpp ++++ b/src/llvm-project/clang/lib/Sema/SemaType.cpp +@@ -6443,6 +6443,9 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + } + ++ while (BTFTagAttributedTypeLoc TL = CurrTL.getAs()) ++ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); ++ + while (DependentAddressSpaceTypeLoc TL = + CurrTL.getAs()) { + fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); +diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +index 19149d079..ab65612bc 100644 +--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp ++++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +@@ -2839,6 +2839,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, + return; + } + ++ if (const auto *TPO = dyn_cast(D)) { ++ // FIXME: We should meaningfully implement this. ++ (void)TPO; ++ return; ++ } ++ + llvm_unreachable("Support for this Decl not implemented."); + } + +diff --git a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp +index e2014f965..1fa73c667 100644 +--- a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp ++++ b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp +@@ -55,45 +55,140 @@ getTokensCovering(llvm::ArrayRef Toks, SourceRange R, + return {Begin, End}; + } + +-// Finds the smallest expansion range that contains expanded tokens First and +-// Last, e.g.: ++// Finds the range within FID corresponding to expanded tokens [First, Last]. ++// Prev precedes First and Next follows Last, these must *not* be included. ++// If no range satisfies the criteria, returns an invalid range. ++// + // #define ID(x) x + // ID(ID(ID(a1) a2)) + // ~~ -> a1 + // ~~ -> a2 + // ~~~~~~~~~ -> a1 a2 +-SourceRange findCommonRangeForMacroArgs(const syntax::Token &First, +- const syntax::Token &Last, +- const SourceManager &SM) { +- SourceRange Res; +- auto FirstLoc = First.location(), LastLoc = Last.location(); +- // Keep traversing up the spelling chain as longs as tokens are part of the +- // same expansion. +- while (!FirstLoc.isFileID() && !LastLoc.isFileID()) { +- auto ExpInfoFirst = SM.getSLocEntry(SM.getFileID(FirstLoc)).getExpansion(); +- auto ExpInfoLast = SM.getSLocEntry(SM.getFileID(LastLoc)).getExpansion(); +- // Stop if expansions have diverged. +- if (ExpInfoFirst.getExpansionLocStart() != +- ExpInfoLast.getExpansionLocStart()) ++SourceRange spelledForExpandedSlow(SourceLocation First, SourceLocation Last, ++ SourceLocation Prev, SourceLocation Next, ++ FileID TargetFile, ++ const SourceManager &SM) { ++ // There are two main parts to this algorithm: ++ // - identifying which spelled range covers the expanded tokens ++ // - validating that this range doesn't cover any extra tokens (First/Last) ++ // ++ // We do these in order. However as we transform the expanded range into the ++ // spelled one, we adjust First/Last so the validation remains simple. ++ ++ assert(SM.getSLocEntry(TargetFile).isFile()); ++ // In most cases, to select First and Last we must return their expansion ++ // range, i.e. the whole of any macros they are included in. ++ // ++ // When First and Last are part of the *same macro arg* of a macro written ++ // in TargetFile, we that slice of the arg, i.e. their spelling range. ++ // ++ // Unwrap such macro calls. If the target file has A(B(C)), the ++ // SourceLocation stack of a token inside C shows us the expansion of A first, ++ // then B, then any macros inside C's body, then C itself. ++ // (This is the reverse of the order the PP applies the expansions in). ++ while (First.isMacroID() && Last.isMacroID()) { ++ auto DecFirst = SM.getDecomposedLoc(First); ++ auto DecLast = SM.getDecomposedLoc(Last); ++ auto &ExpFirst = SM.getSLocEntry(DecFirst.first).getExpansion(); ++ auto &ExpLast = SM.getSLocEntry(DecLast.first).getExpansion(); ++ ++ if (!ExpFirst.isMacroArgExpansion() || !ExpLast.isMacroArgExpansion()) ++ break; ++ // Locations are in the same macro arg if they expand to the same place. ++ // (They may still have different FileIDs - an arg can have >1 chunks!) ++ if (ExpFirst.getExpansionLocStart() != ExpLast.getExpansionLocStart()) + break; +- // Do not continue into macro bodies. +- if (!ExpInfoFirst.isMacroArgExpansion() || +- !ExpInfoLast.isMacroArgExpansion()) ++ // Careful, given: ++ // #define HIDE ID(ID(a)) ++ // ID(ID(HIDE)) ++ // The token `a` is wrapped in 4 arg-expansions, we only want to unwrap 2. ++ // We distinguish them by whether the macro expands into the target file. ++ // Fortunately, the target file ones will always appear first. ++ auto &ExpMacro = ++ SM.getSLocEntry(SM.getFileID(ExpFirst.getExpansionLocStart())) ++ .getExpansion(); ++ if (ExpMacro.getExpansionLocStart().isMacroID()) + break; +- FirstLoc = SM.getImmediateSpellingLoc(FirstLoc); +- LastLoc = SM.getImmediateSpellingLoc(LastLoc); +- // Update the result afterwards, as we want the tokens that triggered the +- // expansion. +- Res = {FirstLoc, LastLoc}; ++ // Replace each endpoint with its spelling inside the macro arg. ++ // (This is getImmediateSpellingLoc without repeating lookups). ++ First = ExpFirst.getSpellingLoc().getLocWithOffset(DecFirst.second); ++ Last = ExpLast.getSpellingLoc().getLocWithOffset(DecLast.second); ++ ++ // Now: how do we adjust the previous/next bounds? Three cases: ++ // A) If they are also part of the same macro arg, we translate them too. ++ // This will ensure that we don't select any macros nested within the ++ // macro arg that cover extra tokens. Critical case: ++ // #define ID(X) X ++ // ID(prev target) // selecting 'target' succeeds ++ // #define LARGE ID(prev target) ++ // LARGE // selecting 'target' fails. ++ // B) They are not in the macro at all, then their expansion range is a ++ // sibling to it, and we can safely substitute that. ++ // #define PREV prev ++ // #define ID(X) X ++ // PREV ID(target) // selecting 'target' succeeds. ++ // #define LARGE PREV ID(target) ++ // LARGE // selecting 'target' fails. ++ // C) They are in a different arg of this macro, or the macro body. ++ // Now selecting the whole macro arg is fine, but the whole macro is not. ++ // Model this by setting using the edge of the macro call as the bound. ++ // #define ID2(X, Y) X Y ++ // ID2(prev, target) // selecting 'target' succeeds ++ // #define LARGE ID2(prev, target) ++ // LARGE // selecting 'target' fails ++ auto AdjustBound = [&](SourceLocation &Bound) { ++ if (Bound.isInvalid() || !Bound.isMacroID()) // Non-macro must be case B. ++ return; ++ auto DecBound = SM.getDecomposedLoc(Bound); ++ auto &ExpBound = SM.getSLocEntry(DecBound.first).getExpansion(); ++ if (ExpBound.isMacroArgExpansion() && ++ ExpBound.getExpansionLocStart() == ExpFirst.getExpansionLocStart()) { ++ // Case A: translate to (spelling) loc within the macro arg. ++ Bound = ExpBound.getSpellingLoc().getLocWithOffset(DecBound.second); ++ return; ++ } ++ while (Bound.isMacroID()) { ++ SourceRange Exp = SM.getImmediateExpansionRange(Bound).getAsRange(); ++ if (Exp.getBegin() == ExpMacro.getExpansionLocStart()) { ++ // Case B: bounds become the macro call itself. ++ Bound = (&Bound == &Prev) ? Exp.getBegin() : Exp.getEnd(); ++ return; ++ } ++ // Either case C, or expansion location will later find case B. ++ // We choose the upper bound for Prev and the lower one for Next: ++ // ID(prev) target ID(next) ++ // ^ ^ ++ // new-prev new-next ++ Bound = (&Bound == &Prev) ? Exp.getEnd() : Exp.getBegin(); ++ } ++ }; ++ AdjustBound(Prev); ++ AdjustBound(Next); + } +- // Normally mapping back to expansion location here only changes FileID, as +- // we've already found some tokens expanded from the same macro argument, and +- // they should map to a consecutive subset of spelled tokens. Unfortunately +- // SourceManager::isBeforeInTranslationUnit discriminates sourcelocations +- // based on their FileID in addition to offsets. So even though we are +- // referring to same tokens, SourceManager might tell us that one is before +- // the other if they've got different FileIDs. +- return SM.getExpansionRange(CharSourceRange(Res, true)).getAsRange(); ++ ++ // In all remaining cases we need the full containing macros. ++ // If this overlaps Prev or Next, then no range is possible. ++ SourceRange Candidate = ++ SM.getExpansionRange(SourceRange(First, Last)).getAsRange(); ++ auto DecFirst = SM.getDecomposedExpansionLoc(Candidate.getBegin()); ++ auto DecLast = SM.getDecomposedLoc(Candidate.getEnd()); ++ // Can end up in the wrong file due to bad input or token-pasting shenanigans. ++ if (Candidate.isInvalid() || DecFirst.first != TargetFile || DecLast.first != TargetFile) ++ return SourceRange(); ++ // Check bounds, which may still be inside macros. ++ if (Prev.isValid()) { ++ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Prev).getBegin()); ++ if (Dec.first != DecFirst.first || Dec.second >= DecFirst.second) ++ return SourceRange(); ++ } ++ if (Next.isValid()) { ++ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Next).getEnd()); ++ if (Dec.first != DecLast.first || Dec.second <= DecLast.second) ++ return SourceRange(); ++ } ++ // Now we know that Candidate is a file range that covers [First, Last] ++ // without encroaching on {Prev, Next}. Ship it! ++ return Candidate; + } + + } // namespace +@@ -363,51 +458,50 @@ TokenBuffer::spelledForExpanded(llvm::ArrayRef Expanded) const { + // of the range, bail out in that case. + if (Expanded.empty()) + return llvm::None; +- +- const syntax::Token *BeginSpelled; +- const Mapping *BeginMapping; +- std::tie(BeginSpelled, BeginMapping) = +- spelledForExpandedToken(&Expanded.front()); +- +- const syntax::Token *LastSpelled; +- const Mapping *LastMapping; +- std::tie(LastSpelled, LastMapping) = +- spelledForExpandedToken(&Expanded.back()); +- +- FileID FID = SourceMgr->getFileID(BeginSpelled->location()); ++ const syntax::Token *First = &Expanded.front(); ++ const syntax::Token *Last = &Expanded.back(); ++ const syntax::Token *FirstSpelled, *LastSpelled; ++ const TokenBuffer::Mapping *FirstMapping, *LastMapping; ++ std::tie(FirstSpelled, FirstMapping) = spelledForExpandedToken(First); ++ std::tie(LastSpelled, LastMapping) = spelledForExpandedToken(Last); ++ ++ FileID FID = SourceMgr->getFileID(FirstSpelled->location()); + // FIXME: Handle multi-file changes by trying to map onto a common root. + if (FID != SourceMgr->getFileID(LastSpelled->location())) + return llvm::None; + + const MarkedFile &File = Files.find(FID)->second; + +- // If both tokens are coming from a macro argument expansion, try and map to +- // smallest part of the macro argument. BeginMapping && LastMapping check is +- // only for performance, they are a prerequisite for Expanded.front() and +- // Expanded.back() being part of a macro arg expansion. +- if (BeginMapping && LastMapping && +- SourceMgr->isMacroArgExpansion(Expanded.front().location()) && +- SourceMgr->isMacroArgExpansion(Expanded.back().location())) { +- auto CommonRange = findCommonRangeForMacroArgs(Expanded.front(), +- Expanded.back(), *SourceMgr); +- // It might be the case that tokens are arguments of different macro calls, +- // in that case we should continue with the logic below instead of returning +- // an empty range. +- if (CommonRange.isValid()) +- return getTokensCovering(File.SpelledTokens, CommonRange, *SourceMgr); ++ // If the range is within one macro argument, the result may be only part of a ++ // Mapping. We must use the general (SourceManager-based) algorithm. ++ if (FirstMapping && FirstMapping == LastMapping && ++ SourceMgr->isMacroArgExpansion(First->location()) && ++ SourceMgr->isMacroArgExpansion(Last->location())) { ++ // We use excluded Prev/Next token for bounds checking. ++ SourceLocation Prev = (First == &ExpandedTokens.front()) ++ ? SourceLocation() ++ : (First - 1)->location(); ++ SourceLocation Next = (Last == &ExpandedTokens.back()) ++ ? SourceLocation() ++ : (Last + 1)->location(); ++ SourceRange Range = spelledForExpandedSlow( ++ First->location(), Last->location(), Prev, Next, FID, *SourceMgr); ++ if (Range.isInvalid()) ++ return llvm::None; ++ return getTokensCovering(File.SpelledTokens, Range, *SourceMgr); + } + ++ // Otherwise, use the fast version based on Mappings. + // Do not allow changes that doesn't cover full expansion. +- unsigned BeginExpanded = Expanded.begin() - ExpandedTokens.data(); +- unsigned EndExpanded = Expanded.end() - ExpandedTokens.data(); +- if (BeginMapping && BeginExpanded != BeginMapping->BeginExpanded) ++ unsigned FirstExpanded = Expanded.begin() - ExpandedTokens.data(); ++ unsigned LastExpanded = Expanded.end() - ExpandedTokens.data(); ++ if (FirstMapping && FirstExpanded != FirstMapping->BeginExpanded) + return llvm::None; +- if (LastMapping && LastMapping->EndExpanded != EndExpanded) ++ if (LastMapping && LastMapping->EndExpanded != LastExpanded) + return llvm::None; +- // All is good, return the result. + return llvm::makeArrayRef( +- BeginMapping ? File.SpelledTokens.data() + BeginMapping->BeginSpelled +- : BeginSpelled, ++ FirstMapping ? File.SpelledTokens.data() + FirstMapping->BeginSpelled ++ : FirstSpelled, + LastMapping ? File.SpelledTokens.data() + LastMapping->EndSpelled + : LastSpelled + 1); + } +diff --git a/src/llvm-project/clang/test/Analysis/template-param-objects.cpp b/src/llvm-project/clang/test/Analysis/template-param-objects.cpp +new file mode 100644 +index 000000000..dde95fa62 +--- /dev/null ++++ b/src/llvm-project/clang/test/Analysis/template-param-objects.cpp +@@ -0,0 +1,33 @@ ++// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection \ ++// RUN: -analyzer-config eagerly-assume=false -std=c++20 -verify %s ++ ++template void clang_analyzer_dump(T); ++void clang_analyzer_eval(bool); ++ ++struct Box { ++ int value; ++}; ++bool operator ==(Box lhs, Box rhs) { ++ return lhs.value == rhs.value; ++} ++template void dumps() { ++ clang_analyzer_dump(V); // expected-warning {{lazyCompoundVal}} ++ clang_analyzer_dump(&V); // expected-warning {{Unknown}} ++ clang_analyzer_dump(V.value); // expected-warning {{Unknown}} FIXME: It should be '6 S32b'. ++ clang_analyzer_dump(&V.value); // expected-warning {{Unknown}} ++} ++template void dumps(); ++ ++// [temp.param].7.3.2: ++// "All such template parameters in the program of the same type with the ++// same value denote the same template parameter object." ++template void stable_addresses() { ++ clang_analyzer_eval(&A1 == &A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. ++ clang_analyzer_eval(&B1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. ++ clang_analyzer_eval(&A1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. ++ ++ clang_analyzer_eval(A1 == A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. ++ clang_analyzer_eval(B1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. ++ clang_analyzer_eval(A1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. ++} ++template void stable_addresses(); +diff --git a/src/llvm-project/clang/test/CodeGen/arm-vaarg.c b/src/llvm-project/clang/test/CodeGen/arm-vaarg.c +new file mode 100644 +index 000000000..4dab397a2 +--- /dev/null ++++ b/src/llvm-project/clang/test/CodeGen/arm-vaarg.c +@@ -0,0 +1,23 @@ ++// RUN: %clang -Xclang -no-opaque-pointers -mfloat-abi=soft -target arm-linux-gnu -emit-llvm -S -o - %s | FileCheck %s ++ ++struct Empty {}; ++ ++struct Empty emptyvar; ++ ++void take_args(int a, ...) { ++// CHECK: [[ALLOCA_VA_LIST:%[a-zA-Z0-9._]+]] = alloca %struct.__va_list, align 4 ++// CHECK: call void @llvm.va_start ++// CHECK-NEXT: [[AP_ADDR:%[a-zA-Z0-9._]+]] = bitcast %struct.__va_list* [[ALLOCA_VA_LIST]] to i8** ++// CHECK-NEXT: [[LOAD_AP:%[a-zA-Z0-9._]+]] = load i8*, i8** [[AP_ADDR]], align 4 ++// CHECK-NEXT: [[EMPTY_PTR:%[a-zA-Z0-9._]+]] = bitcast i8* [[LOAD_AP]] to %struct.Empty* ++ ++ // It's conceivable that EMPTY_PTR may not actually be a valid pointer ++ // (e.g. it's at the very bottom of the stack and the next page is ++ // invalid). This doesn't matter provided it's never loaded (there's no ++ // well-defined way to tell), but it becomes a problem if we do try to use it. ++// CHECK-NOT: load %struct.Empty, %struct.Empty* [[EMPTY_PTR]] ++ __builtin_va_list l; ++ __builtin_va_start(l, a); ++ emptyvar = __builtin_va_arg(l, struct Empty); ++ __builtin_va_end(l); ++} +diff --git a/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c +new file mode 100644 +index 000000000..29ca5f58e +--- /dev/null ++++ b/src/llvm-project/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c +@@ -0,0 +1,15 @@ ++// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s ++ ++struct t { ++ int (__attribute__((btf_type_tag("rcu"))) *f)(); ++ int a; ++}; ++int foo(struct t *arg) { ++ return arg->a; ++} ++ ++// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f" ++// CHECK-SAME: baseType: ![[L18:[0-9]+]] ++// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]]) ++// CHECK: ![[L21]] = !{![[L22:[0-9]+]]} ++// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"} +diff --git a/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c b/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c +new file mode 100644 +index 000000000..f39de0d73 +--- /dev/null ++++ b/src/llvm-project/clang/test/CodeGen/debug-info-enum-case-val.c +@@ -0,0 +1,30 @@ ++// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s ++ ++enum { A = 1 }; ++int func1(int a) { ++ switch(a) { ++ case A: return 10; ++ default: break; ++ } ++ return 0; ++} ++// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type ++// CHECK-SAME: elements: [[TEST1_ENUMS:![0-9]*]] ++// CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]} ++// CHECK: [[TEST1_E]] = !DIEnumerator(name: "A", value: 1) ++ ++// Test ImplicitCast of switch case enum value ++enum { B = 2 }; ++typedef unsigned long long __t1; ++typedef __t1 __t2; ++int func2(__t2 a) { ++ switch(a) { ++ case B: return 10; ++ default: break; ++ } ++ return 0; ++} ++// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type ++// CHECK-SAME: elements: [[TEST2_ENUMS:![0-9]*]] ++// CHECK: [[TEST2_ENUMS]] = !{[[TEST2_E:![0-9]*]]} ++// CHECK: [[TEST2_E]] = !DIEnumerator(name: "B", value: 2) +diff --git a/src/llvm-project/clang/test/Sema/gnu-builtins.c b/src/llvm-project/clang/test/Sema/gnu-builtins.c +new file mode 100644 +index 000000000..c4da8b393 +--- /dev/null ++++ b/src/llvm-project/clang/test/Sema/gnu-builtins.c +@@ -0,0 +1,13 @@ ++// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu17 %s ++// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu2x %s ++// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c17 %s ++// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c2x %s ++ ++// std-no-diagnostics ++ ++// 'index' is a builtin library function, but only in GNU mode. So this should ++// give an error in GNU modes but be okay in non-GNU mode. ++// FIXME: the error is correct, but these notes are pretty awful. ++int index; // gnu-error {{redefinition of 'index' as different kind of symbol}} \ ++ gnu-note {{unguarded header; consider using #ifdef guards or #pragma once}} \ ++ gnu-note {{previous definition is here}} +diff --git a/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp b/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp +new file mode 100644 +index 000000000..5fd387cab +--- /dev/null ++++ b/src/llvm-project/clang/test/SemaCXX/specialization-diagnose-crash.cpp +@@ -0,0 +1,24 @@ ++// RUN: %clang_cc1 -fsyntax-only %s --std=c++17 -verify ++// This is a reduction of GH57370 and GH58028, originally appearing ++// in libstdc++'s variant code. ++ ++struct V1 {}; ++struct V2 : V1 { ++ int &a; ++}; ++ ++template using void_t = void; ++ ++template struct X { T x; }; ++ ++template struct Variant { ++ Variant() = delete; // expected-note {{deleted here}} ++}; ++ ++template ++struct Variant{T1()})>> {}; ++ ++void f() { ++ Variant(); ++ Variant(); // expected-error {{call to deleted constructor}} ++} +diff --git a/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp b/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp +index 64bc61652..c434dfcb3 100644 +--- a/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp ++++ b/src/llvm-project/clang/unittests/Driver/ToolChainTest.cpp +@@ -18,7 +18,6 @@ + #include "clang/Driver/Driver.h" + #include "llvm/ADT/ArrayRef.h" + #include "llvm/MC/TargetRegistry.h" +-#include "llvm/Support/Host.h" + #include "llvm/Support/TargetSelect.h" + #include "llvm/Support/VirtualFileSystem.h" + #include "llvm/Support/raw_ostream.h" +@@ -570,95 +569,4 @@ TEST(DxcModeTest, ValidatorVersionValidation) { + Diags.Clear(); + DiagConsumer->clear(); + } +- +-TEST(ToolChainTest, Toolsets) { +- // Ignore this test on Windows hosts. +- llvm::Triple Host(llvm::sys::getProcessTriple()); +- if (Host.isOSWindows()) +- GTEST_SKIP(); +- +- IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); +- IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); +- +- // Check (newer) GCC toolset installation. +- { +- IntrusiveRefCntPtr InMemoryFileSystem( +- new llvm::vfs::InMemoryFileSystem); +- +- // These should be ignored. +- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- +- // File needed for GCC installation detection. +- InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-12/root/usr/lib/gcc/" +- "x86_64-redhat-linux/11/crtbegin.o", +- 0, llvm::MemoryBuffer::getMemBuffer("\n")); +- +- DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); +- Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, +- "clang LLVM compiler", InMemoryFileSystem); +- std::unique_ptr C( +- TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); +- ASSERT_TRUE(C); +- std::string S; +- { +- llvm::raw_string_ostream OS(S); +- C->getDefaultToolChain().printVerboseInfo(OS); +- } +- EXPECT_EQ("Found candidate GCC installation: " +- "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" +- "Selected GCC installation: " +- "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" +- "Candidate multilib: .;@m64\n" +- "Selected multilib: .;@m64\n", +- S); +- } +- +- // And older devtoolset. +- { +- IntrusiveRefCntPtr InMemoryFileSystem( +- new llvm::vfs::InMemoryFileSystem); +- +- // These should be ignored. +- InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0, +- llvm::MemoryBuffer::getMemBuffer("\n")); +- +- // File needed for GCC installation detection. +- InMemoryFileSystem->addFile("/opt/rh/devtoolset-12/root/usr/lib/gcc/" +- "x86_64-redhat-linux/11/crtbegin.o", +- 0, llvm::MemoryBuffer::getMemBuffer("\n")); +- +- DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); +- Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, +- "clang LLVM compiler", InMemoryFileSystem); +- std::unique_ptr C( +- TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); +- ASSERT_TRUE(C); +- std::string S; +- { +- llvm::raw_string_ostream OS(S); +- C->getDefaultToolChain().printVerboseInfo(OS); +- } +- EXPECT_EQ("Found candidate GCC installation: " +- "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" +- "Selected GCC installation: " +- "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" +- "Candidate multilib: .;@m64\n" +- "Selected multilib: .;@m64\n", +- S); +- } +-} +- + } // end anonymous namespace. +diff --git a/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp b/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp +index 77f719ce2..85fc837fb 100644 +--- a/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp ++++ b/src/llvm-project/clang/unittests/Tooling/Syntax/TokensTest.cpp +@@ -743,6 +743,62 @@ TEST_F(TokenBufferTest, SpelledByExpanded) { + ValueIs(SameRange(findSpelled("ID2 ( a4 , a5 a6 a7 )")))); + // Should fail, spans multiple invocations. + EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("a1 a2 a3 a4")), llvm::None); ++ ++ // https://github.com/clangd/clangd/issues/1289 ++ recordTokens(R"cpp( ++ #define FOO(X) foo(X) ++ #define INDIRECT FOO(y) ++ INDIRECT // expands to foo(y) ++ )cpp"); ++ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("y")), llvm::None); ++ ++ recordTokens(R"cpp( ++ #define FOO(X) a X b ++ FOO(y) ++ )cpp"); ++ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("y")), ++ ValueIs(SameRange(findSpelled("y")))); ++ ++ recordTokens(R"cpp( ++ #define ID(X) X ++ #define BAR ID(1) ++ BAR ++ )cpp"); ++ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("1")), ++ ValueIs(SameRange(findSpelled(") BAR").drop_front()))); ++ ++ // Critical cases for mapping of Prev/Next in spelledForExpandedSlow. ++ recordTokens(R"cpp( ++ #define ID(X) X ++ ID(prev ID(good)) ++ #define LARGE ID(prev ID(bad)) ++ LARGE ++ )cpp"); ++ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), ++ ValueIs(SameRange(findSpelled("good")))); ++ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); ++ ++ recordTokens(R"cpp( ++ #define PREV prev ++ #define ID(X) X ++ PREV ID(good) ++ #define LARGE PREV ID(bad) ++ LARGE ++ )cpp"); ++ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), ++ ValueIs(SameRange(findSpelled("good")))); ++ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); ++ ++ recordTokens(R"cpp( ++ #define ID(X) X ++ #define ID2(X, Y) X Y ++ ID2(prev, ID(good)) ++ #define LARGE ID2(prev, bad) ++ LARGE ++ )cpp"); ++ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), ++ ValueIs(SameRange(findSpelled("good")))); ++ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); + } + + TEST_F(TokenBufferTest, ExpandedTokensForRange) { +diff --git a/src/llvm-project/cmake/Modules/FindLibEdit.cmake b/src/llvm-project/cmake/Modules/FindLibEdit.cmake +index 7e62d4d83..de8f5a2e7 100644 +--- a/src/llvm-project/cmake/Modules/FindLibEdit.cmake ++++ b/src/llvm-project/cmake/Modules/FindLibEdit.cmake +@@ -21,6 +21,7 @@ find_library(LibEdit_LIBRARIES NAMES edit HINTS ${PC_LIBEDIT_LIBRARY_DIRS}) + + include(CheckIncludeFile) + if(LibEdit_INCLUDE_DIRS AND EXISTS "${LibEdit_INCLUDE_DIRS}/histedit.h") ++ include(CMakePushCheckState) + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_INCLUDES ${LibEdit_INCLUDE_DIRS}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${LibEdit_LIBRARIES}) +diff --git a/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +index 2c9983c6a..640c7e712 100644 +--- a/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake ++++ b/src/llvm-project/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +@@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs) + if(NOT TEST_COMPILE_ONLY) + message(STATUS "Finding valid architectures for ${os}...") + set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) +- file(WRITE ${SIMPLE_C} "#include \nint main() { printf(__FILE__); return 0; }\n") ++ file(WRITE ${SIMPLE_C} "#include \nint main(void) { printf(__FILE__); return 0; }\n") + + set(os_linker_flags) + foreach(flag ${DARWIN_${os}_LINK_FLAGS}) +diff --git a/src/llvm-project/compiler-rt/cmake/config-ix.cmake b/src/llvm-project/compiler-rt/cmake/config-ix.cmake +index cd45176cf..9077e8f9f 100644 +--- a/src/llvm-project/compiler-rt/cmake/config-ix.cmake ++++ b/src/llvm-project/compiler-rt/cmake/config-ix.cmake +@@ -209,7 +209,7 @@ set(COMPILER_RT_SUPPORTED_ARCH) + # runtime libraries supported by our current compilers cross-compiling + # abilities. + set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) +-file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() { printf(\"hello, world\"); }\n") ++file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") + + # Detect whether the current target platform is 32-bit or 64-bit, and setup + # the correct commandline flags needed to attempt to target 32-bit and 64-bit. +diff --git a/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt b/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt +index ec668e294..df02682ae 100644 +--- a/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt ++++ b/src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt +@@ -745,7 +745,7 @@ else () + SOURCE "#if !(__ARM_FP & 0x8) + #error No double-precision support! + #endif +- int main() { return 0; }") ++ int main(void) { return 0; }") + if(NOT COMPILER_RT_HAS_${arch}_VFP_DP) + list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_DP_SOURCES}) + endif() +diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h +index fc5aeccf2..08c6062ba 100644 +--- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h ++++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.h +@@ -443,7 +443,7 @@ inline uptr RoundUpToPowerOfTwo(uptr size) { + return 1ULL << (up + 1); + } + +-inline uptr RoundUpTo(uptr size, uptr boundary) { ++inline constexpr uptr RoundUpTo(uptr size, uptr boundary) { + RAW_CHECK(IsPowerOfTwo(boundary)); + return (size + boundary - 1) & ~(boundary - 1); + } +diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +index 9af296b18..b29665a63 100644 +--- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc ++++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +@@ -6703,7 +6703,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) { + COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value); + // Workaround a bug in glibc's "old" semaphore implementation by + // zero-initializing the sem_t contents. This has to be done here because +- // interceptors bind to the lowest symbols version by default, hitting the ++ // interceptors bind to the lowest version before glibc 2.36, hitting the + // buggy code path while the non-sanitized build of the same code works fine. + REAL(memset)(s, 0, sizeof(*s)); + int res = REAL(sem_init)(s, pshared, value); +diff --git a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h +index ddb96d2cc..4f1a8caac 100644 +--- a/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h ++++ b/src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h +@@ -61,7 +61,7 @@ class StackStore { + return frame_idx % kBlockSizeFrames; + } + +- static uptr IdToOffset(Id id) { ++ static constexpr uptr IdToOffset(Id id) { + CHECK_NE(id, 0); + return id - 1; // Avoid zero as id. + } +diff --git a/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp b/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp +index d623ccabb..234c5019f 100644 +--- a/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp ++++ b/src/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp +@@ -1,39 +1,36 @@ + // RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t + // This test depends on the glibc layout of struct sem_t and checks that we + // don't leave sem_t::private uninitialized. +-// UNSUPPORTED: android, lsan-x86, ubsan, target-is-mips64, target-is-mips64el ++// UNSUPPORTED: android, lsan-x86, ubsan + #include + #include + #include + #include + #include + +-// On powerpc64be semval_t must be 64 bits even with "old" versions of glibc. +-#if __PPC64__ && __BIG_ENDIAN__ +-typedef uint64_t semval_t; +- +-// This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. +-#elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ +- defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ +- defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) +-typedef uint64_t semval_t; +-#else ++// musl and glibc's __HAVE_64B_ATOMICS==0 ports (e.g. arm, i386) use 32-bit sem ++// values. 64-bit glibc ports defining sem_init@GLIBC_2.0 (mips64) use 32-bit as ++// well, if the sem_init interceptor picks the oldest versioned symbol ++// (glibc<2.36, see https://sourceware.org/PR14932). ++#if !defined(__GLIBC__) || defined(__ILP32__) || \ ++ !__GLIBC_PREREQ(2, 36) && defined(__mips64__) + typedef unsigned semval_t; ++#else ++typedef uint64_t semval_t; + #endif + +-// glibc 2.21 has introduced some changes in the way the semaphore value is +-// handled for 32-bit platforms, but since these changes are not ABI-breaking +-// they are not versioned. On newer platforms such as ARM, there is only one +-// version of the symbol, so it's enough to check the glibc version. However, +-// for old platforms such as i386, glibc contains two or even three versions of +-// the sem_init symbol, and the sanitizers always pick the oldest one. +-// Therefore, it is not enough to rely on the __GLIBC_PREREQ macro - we should +-// instead check the platform as well to make sure we only expect the new +-// behavior on platforms where the older symbols do not exist. +-#if defined(__arm__) && __GLIBC_PREREQ(2, 21) +-#define GET_SEM_VALUE(V) ((V) >> 1) ++// glibc __HAVE_64B_ATOMICS==0 ports define a sem_init which shifts the value by ++// 1 (https://sourceware.org/PR12674 glibc 2.21). The version is picked if ++// either glibc>=2.36 or sem_init@GLIBC_2.0 is absent (arm and newer ports). ++// ++// The __GLIBC_PREREQ check is brittle in that it requires matched ++// __GLIBC_PREREQ values for build time and run time. ++#if defined(__GLIBC__) && defined(__ILP32__) && \ ++ (__GLIBC_PREREQ(2, 36) || (__GLIBC_PREREQ(2, 21) && !defined(__i386__) && \ ++ !defined(__mips__) && !defined(__powerpc__))) ++# define GET_SEM_VALUE(V) ((V) >> 1) + #else +-#define GET_SEM_VALUE(V) (V) ++# define GET_SEM_VALUE(V) (V) + #endif + + void my_sem_init(bool priv, int value, semval_t *a, unsigned char *b) { +diff --git a/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm b/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm +new file mode 100644 +index 000000000..186fe22e6 +--- /dev/null ++++ b/src/llvm-project/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm +@@ -0,0 +1,89 @@ ++//===----------------------------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++// std::function support for "blocks" when ARC is enabled ++ ++// UNSUPPORTED: c++03 ++ ++// This test requires the Blocks runtime, which is (only?) available on Darwin ++// out-of-the-box. ++// REQUIRES: has-fblocks && darwin ++ ++// ADDITIONAL_COMPILE_FLAGS: -fblocks -fobjc-arc ++ ++#include ++ ++#include ++#include ++#include ++ ++struct Foo { ++ Foo() = default; ++ Foo(std::size_t (^bl)()) : f(bl) {} ++ ++ std::function f; ++}; ++ ++Foo Factory(std::size_t (^bl)()) { ++ Foo result(bl); ++ return result; ++} ++ ++Foo Factory2() { ++ auto hello = std::string("Hello world"); ++ return Factory(^() { ++ return hello.size(); ++ }); ++} ++ ++Foo AssignmentFactory(std::size_t (^bl)()) { ++ Foo result; ++ result.f = bl; ++ return result; ++} ++ ++Foo AssignmentFactory2() { ++ auto hello = std::string("Hello world"); ++ return AssignmentFactory(^() { ++ return hello.size(); ++ }); ++} ++ ++int main(int, char **) { ++ // Case 1, works ++ { ++ auto hello = std::string("Hello world"); ++ auto f = AssignmentFactory(^() { ++ return hello.size(); ++ }); ++ assert(f.f() == 11); ++ } ++ ++ // Case 2, works ++ { ++ auto f = AssignmentFactory2(); ++ assert(f.f() == 11); ++ } ++ ++ // Case 3, works ++ { ++ auto hello = std::string("Hello world"); ++ auto f = Factory(^() { ++ return hello.size(); ++ }); ++ assert(f.f() == 11); ++ } ++ ++ // Case 4, used to crash under ARC ++ { ++ auto f = Factory2(); ++ assert(f.f() == 11); ++ } ++ ++ return 0; ++} +diff --git a/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp b/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp +new file mode 100644 +index 000000000..592d733de +--- /dev/null ++++ b/src/llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp +@@ -0,0 +1,141 @@ ++//===----------------------------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++// UNSUPPORTED: no-exceptions ++ ++// (bug report: https://llvm.org/PR58392) ++// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception ++ ++#include ++#include ++ ++#include "count_new.h" ++#include "test_iterators.h" ++ ++template ++struct Allocator { ++ using value_type = T; ++ using is_always_equal = std::false_type; ++ ++ template ++ Allocator(const Allocator&) {} ++ ++ Allocator(bool should_throw = true) { ++ if (should_throw) ++ throw 0; ++ } ++ ++ T* allocate(int n) { return std::allocator().allocate(n); } ++ void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } ++ ++ friend bool operator==(const Allocator&, const Allocator&) { return false; } ++}; ++ ++template ++struct Iterator { ++ using iterator_category = IterCat; ++ using difference_type = std::ptrdiff_t; ++ using value_type = bool; ++ using reference = bool&; ++ using pointer = bool*; ++ ++ int i_; ++ bool b_ = true; ++ Iterator(int i = 0) : i_(i) {} ++ bool& operator*() { ++ if (i_ == 1) ++ throw 1; ++ return b_; ++ } ++ ++ friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } ++ ++ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } ++ ++ Iterator& operator++() { ++ ++i_; ++ return *this; ++ } ++ ++ Iterator operator++(int) { ++ auto tmp = *this; ++ ++i_; ++ return tmp; ++ } ++}; ++ ++void check_new_delete_called() { ++ assert(globalMemCounter.new_called == globalMemCounter.delete_called); ++ assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); ++ assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); ++ assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); ++} ++ ++int main(int, char**) { ++ using AllocVec = std::vector >; ++ ++#if TEST_STD_VER >= 14 ++ try { // Throw in vector(size_type, const allocator_type&) from allocator ++ Allocator alloc(false); ++ AllocVec get_alloc(0, alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++#endif // TEST_STD_VER >= 14 ++ ++ try { // Throw in vector(InputIterator, InputIterator) from input iterator ++ std::vector vec((Iterator()), Iterator(2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator) from forward iterator ++ std::vector vec((Iterator()), Iterator(2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator) from allocator ++ int a[] = {1, 2}; ++ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator ++ std::allocator alloc; ++ std::vector vec(Iterator(), Iterator(2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator ++ std::allocator alloc; ++ std::vector vec(Iterator(), Iterator(2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator ++ bool a[] = {true, false}; ++ Allocator alloc(false); ++ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator ++ bool a[] = {true, false}; ++ Allocator alloc(false); ++ AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ return 0; ++} +diff --git a/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp b/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp +new file mode 100644 +index 000000000..26ad7b4fd +--- /dev/null ++++ b/src/llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp +@@ -0,0 +1,229 @@ ++//===----------------------------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++// UNSUPPORTED: no-exceptions ++ ++// (bug report: https://llvm.org/PR58392) ++// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception ++ ++#include ++#include ++ ++#include "count_new.h" ++#include "test_iterators.h" ++ ++template ++struct Allocator { ++ using value_type = T; ++ using is_always_equal = std::false_type; ++ ++ Allocator(bool should_throw = true) { ++ if (should_throw) ++ throw 0; ++ } ++ ++ T* allocate(int n) { return std::allocator().allocate(n); } ++ void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } ++ ++ friend bool operator==(const Allocator&, const Allocator&) { return false; } ++}; ++ ++struct ThrowingT { ++ int* throw_after_n_ = nullptr; ++ ThrowingT() { throw 0; } ++ ++ ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) { ++ if (throw_after_n == 0) ++ throw 0; ++ --throw_after_n; ++ } ++ ++ ThrowingT(const ThrowingT&) { ++ if (throw_after_n_ == nullptr || *throw_after_n_ == 0) ++ throw 1; ++ --*throw_after_n_; ++ } ++ ++ ThrowingT& operator=(const ThrowingT&) { ++ if (throw_after_n_ == nullptr || *throw_after_n_ == 0) ++ throw 1; ++ --*throw_after_n_; ++ return *this; ++ } ++}; ++ ++template ++struct Iterator { ++ using iterator_category = IterCat; ++ using difference_type = std::ptrdiff_t; ++ using value_type = int; ++ using reference = int&; ++ using pointer = int*; ++ ++ int i_; ++ Iterator(int i = 0) : i_(i) {} ++ int& operator*() { ++ if (i_ == 1) ++ throw 1; ++ return i_; ++ } ++ ++ friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } ++ ++ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } ++ ++ Iterator& operator++() { ++ ++i_; ++ return *this; ++ } ++ ++ Iterator operator++(int) { ++ auto tmp = *this; ++ ++i_; ++ return tmp; ++ } ++}; ++ ++void check_new_delete_called() { ++ assert(globalMemCounter.new_called == globalMemCounter.delete_called); ++ assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); ++ assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); ++ assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); ++} ++ ++int main(int, char**) { ++ using AllocVec = std::vector >; ++ try { // vector() ++ AllocVec vec; ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(size_type) from type ++ std::vector get_alloc(1); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++#if TEST_STD_VER >= 14 ++ try { // Throw in vector(size_type, value_type) from type ++ int throw_after = 1; ++ ThrowingT v(throw_after); ++ std::vector get_alloc(1, v); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(size_type, const allocator_type&) from allocator ++ Allocator alloc(false); ++ AllocVec get_alloc(0, alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(size_type, const allocator_type&) from the type ++ std::vector vec(1, std::allocator()); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++#endif // TEST_STD_VER >= 14 ++ ++ try { // Throw in vector(InputIterator, InputIterator) from input iterator ++ std::vector vec((Iterator()), Iterator(2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator) from forward iterator ++ std::vector vec((Iterator()), Iterator(2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator) from allocator ++ int a[] = {1, 2}; ++ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator ++ std::allocator alloc; ++ std::vector vec(Iterator(), Iterator(2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator ++ std::allocator alloc; ++ std::vector vec(Iterator(), Iterator(2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator ++ int a[] = {1, 2}; ++ Allocator alloc(false); ++ AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator ++ int a[] = {1, 2}; ++ Allocator alloc(false); ++ AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(const vector&) from type ++ std::vector vec; ++ int throw_after = 0; ++ vec.emplace_back(throw_after); ++ auto vec2 = vec; ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(const vector&, const allocator_type&) from type ++ std::vector vec; ++ int throw_after = 1; ++ vec.emplace_back(throw_after); ++ std::vector vec2(vec, std::allocator()); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(vector&&, const allocator_type&) from type ++ std::vector > vec(Allocator(false)); ++ int throw_after = 1; ++ vec.emplace_back(throw_after); ++ std::vector > vec2(std::move(vec), Allocator(false)); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++#if TEST_STD_VER >= 11 ++ try { // Throw in vector(initializer_list) from type ++ int throw_after = 1; ++ std::vector vec({ThrowingT(throw_after)}); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++ ++ try { // Throw in vector(initializer_list, const allocator_type&) constructor from type ++ int throw_after = 1; ++ std::vector vec({ThrowingT(throw_after)}, std::allocator()); ++ } catch (int) { ++ } ++ check_new_delete_called(); ++#endif // TEST_STD_VER >= 11 ++ ++ return 0; ++} +diff --git a/src/llvm-project/libunwind/CMakeLists.txt b/src/llvm-project/libunwind/CMakeLists.txt +index acf3d6dd4..5a06805f0 100644 +--- a/src/llvm-project/libunwind/CMakeLists.txt ++++ b/src/llvm-project/libunwind/CMakeLists.txt +@@ -264,7 +264,7 @@ if (LIBUNWIND_ENABLE_ASSERTIONS) + + # On Release builds cmake automatically defines NDEBUG, so we + # explicitly undefine it: +- if ((NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") AND (NOT RUST_SGX)) ++ if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + add_compile_flags(-UNDEBUG) + endif() + else() +diff --git a/src/llvm-project/libunwind/README_RUST_SGX.md b/src/llvm-project/libunwind/README_RUST_SGX.md +deleted file mode 100644 +index c5d6eb477..000000000 +--- a/src/llvm-project/libunwind/README_RUST_SGX.md ++++ /dev/null +@@ -1,22 +0,0 @@ +-# Libunwind customizations for linking with x86_64-fortanix-unknown-sgx Rust target. +- +-## Description +-### Initial Fork +-Initial Fork has been made from 5.0 release of llvm (commit: 6a075b6de4) +-### Detailed Description +-#### Header files that we do not include for this target +-1. pthread.h +-#### Library that we do not link to for this target. +-1. pthread (Locks used by libunwind is provided by rust stdlib for this target) +- +-## Building unwind for rust-sgx target +-### Generate Make files: +-* `cd where you want to build libunwind` +-* `mkdir build` +-* `cd build` +-* `cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" -DLLVM_ENABLE_WARNINGS=1 -DLIBUNWIND_ENABLE_PEDANTIC=0 -DLLVM_PATH= ` +-* `"DEBUG"` could be used instead of `"RELEASE"` to enable debug logs of libunwind. +- +-### Build: +-* `make unwind_static` +-* `build/lib/` will have the built library. +diff --git a/src/llvm-project/libunwind/cmake/config-ix.cmake b/src/llvm-project/libunwind/cmake/config-ix.cmake +index c9b65b3ce..1b027cf37 100644 +--- a/src/llvm-project/libunwind/cmake/config-ix.cmake ++++ b/src/llvm-project/libunwind/cmake/config-ix.cmake +@@ -85,7 +85,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas") + check_c_source_compiles(" + #pragma comment(lib, \"c\") +-int main() { return 0; } ++int main(void) { return 0; } + " C_SUPPORTS_COMMENT_LIB_PRAGMA) + cmake_pop_check_state() + endif() +diff --git a/src/llvm-project/libunwind/docs/BuildingLibunwind.rst b/src/llvm-project/libunwind/docs/BuildingLibunwind.rst +index abd432c93..79166b476 100644 +--- a/src/llvm-project/libunwind/docs/BuildingLibunwind.rst ++++ b/src/llvm-project/libunwind/docs/BuildingLibunwind.rst +@@ -148,8 +148,3 @@ libunwind specific options + + Path where built libunwind libraries should be installed. If a relative path, + relative to ``CMAKE_INSTALL_PREFIX``. +- +-.. option:: LIBUNWIND_ENABLE_RUST_SGX:BOOL +- +- **Default**: ``OFF`` +- +diff --git a/src/llvm-project/libunwind/src/AddressSpace.hpp b/src/llvm-project/libunwind/src/AddressSpace.hpp +index e9a1f3f7f..36c9f5a9e 100644 +--- a/src/llvm-project/libunwind/src/AddressSpace.hpp ++++ b/src/llvm-project/libunwind/src/AddressSpace.hpp +@@ -90,7 +90,6 @@ char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, + // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; + // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + +-#if !defined(RUST_SGX) + extern char __eh_frame_start; + extern char __eh_frame_end; + +@@ -99,15 +98,6 @@ extern char __eh_frame_hdr_start; + extern char __eh_frame_hdr_end; + #endif + +-#elif defined(RUST_SGX) +-extern "C" char IMAGE_BASE; +-extern "C" uint64_t EH_FRM_HDR_OFFSET; +-extern "C" uint64_t EH_FRM_HDR_LEN; +-extern "C" uint64_t EH_FRM_OFFSET; +-extern "C" uint64_t EH_FRM_LEN; +-#endif +- +- + #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) + + // When statically linked on bare-metal, the symbols for the EH table are looked +@@ -515,10 +505,6 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, + #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) + + +-#if defined(RUST_SGX) +-extern "C" char IMAGE_BASE; +-#endif +- + inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, + UnwindInfoSections &info) { + #ifdef __APPLE__ +@@ -536,8 +522,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, + #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) + info.dso_base = 0; + // Bare metal is statically linked, so no need to ask the dynamic loader +- +-#if !defined(RUST_SGX) + info.dwarf_section_length = (size_t)(&__eh_frame_end - &__eh_frame_start); + info.dwarf_section = (uintptr_t)(&__eh_frame_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", +@@ -548,17 +532,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", + (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); + #endif +- +-#elif defined(RUST_SGX) +- info.dwarf_section = (uintptr_t)EH_FRM_OFFSET + (uintptr_t)(&IMAGE_BASE); +- info.dwarf_section_length = (uintptr_t)EH_FRM_LEN; +-#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) +- info.dwarf_index_section = (uintptr_t)EH_FRM_HDR_OFFSET + (uintptr_t)(&IMAGE_BASE); +- info.dwarf_index_section_length = (uintptr_t)EH_FRM_HDR_LEN; +-#endif +- +-#endif +- + if (info.dwarf_section_length) + return true; + #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) +diff --git a/src/llvm-project/libunwind/src/CMakeLists.txt b/src/llvm-project/libunwind/src/CMakeLists.txt +index 76d4094dc..61df2737b 100644 +--- a/src/llvm-project/libunwind/src/CMakeLists.txt ++++ b/src/llvm-project/libunwind/src/CMakeLists.txt +@@ -1,9 +1,5 @@ + # Get sources + +-enable_language(C CXX ASM) +- +-set(CMAKE_POSITION_INDEPENDENT_CODE ON) +- + set(LIBUNWIND_CXX_SOURCES + libunwind.cpp + Unwind-EHABI.cpp +@@ -26,6 +22,9 @@ set(LIBUNWIND_C_SOURCES + UnwindLevel1-gcc-ext.c + Unwind-sjlj.c + ) ++set_source_files_properties(${LIBUNWIND_C_SOURCES} ++ PROPERTIES ++ COMPILE_FLAGS "-std=c99") + + set(LIBUNWIND_ASM_SOURCES + UnwindRegistersRestore.S +@@ -74,44 +73,6 @@ if (MSVC_IDE) + source_group("Header Files" FILES ${LIBUNWIND_HEADERS}) + endif() + +-if (RUST_SGX) +- # Compile Flags +- add_definitions(-DRUST_SGX) +- add_definitions(-D__NO_STRING_INLINES) +- add_definitions(-D__NO_MATH_INLINES) +- add_definitions(-D_LIBUNWIND_IS_BAREMETAL) +- # Can't use add_definitions because CMake will reorder these arguments +- list(APPEND LIBUNWIND_COMPILE_FLAGS -U_FORTIFY_SOURCE) +- list(APPEND LIBUNWIND_COMPILE_FLAGS -D_FORTIFY_SOURCE=0) +- +- list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-stack-protector) +- list(APPEND LIBUNWIND_COMPILE_FLAGS -ffreestanding) +- list(APPEND LIBUNWIND_COMPILE_FLAGS -fexceptions) +- # Avoid too new relocation types being emitted, which might prevent linking +- # on older platforms. +- # +- # See https://github.com/rust-lang/rust/issues/34978 +- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +- list(APPEND LIBUNWIND_COMPILE_FLAGS -Wa,-mrelax-relocations=no) +- else() +- list(APPEND LIBUNWIND_COMPILE_FLAGS) +- endif() +- +- # Sources +- list(APPEND LIBUNWIND_HEADERS UnwindRustSgx.h) +- list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgx.c) +-endif() +- +- +-set_source_files_properties(${LIBUNWIND_C_SOURCES} +- PROPERTIES +- COMPILE_FLAGS "-std=c99") +- +-# See add_asm_sources() in compiler-rt for explanation of this workaround. +-if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR (MINGW AND CMAKE_VERSION VERSION_LESS 3.17)) +- set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C) +-endif() +- + set(LIBUNWIND_SOURCES + ${LIBUNWIND_CXX_SOURCES} + ${LIBUNWIND_C_SOURCES} +@@ -126,7 +87,7 @@ else() + add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc) + endif() + add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl) +-if (LIBUNWIND_ENABLE_THREADS AND (NOT RUST_SGX)) ++if (LIBUNWIND_ENABLE_THREADS) + add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread) + add_compile_flags_if(LIBUNWIND_WEAK_PTHREAD_LIB -DLIBUNWIND_USE_WEAK_PTHREAD=1) + endif() +diff --git a/src/llvm-project/libunwind/src/RWMutex.hpp b/src/llvm-project/libunwind/src/RWMutex.hpp +index 65bd849aa..344d35641 100644 +--- a/src/llvm-project/libunwind/src/RWMutex.hpp ++++ b/src/llvm-project/libunwind/src/RWMutex.hpp +@@ -15,7 +15,7 @@ + + #if defined(_WIN32) + #include +-#elif !defined(_LIBUNWIND_HAS_NO_THREADS) && !defined(RUST_SGX) ++#elif !defined(_LIBUNWIND_HAS_NO_THREADS) + #include + #if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB) + #pragma comment(lib, "pthread") +diff --git a/src/llvm-project/libunwind/src/UnwindRustSgx.c b/src/llvm-project/libunwind/src/UnwindRustSgx.c +deleted file mode 100644 +index 9be7c1b54..000000000 +--- a/src/llvm-project/libunwind/src/UnwindRustSgx.c ++++ /dev/null +@@ -1,125 +0,0 @@ +-//===--------------------- UnwindRustSgx.c ----------------------------------===// +-// +-//// The LLVM Compiler Infrastructure +-//// +-//// This file is dual licensed under the MIT and the University of Illinois Open +-//// Source Licenses. See LICENSE.TXT for details. +-//// +-//// +-////===----------------------------------------------------------------------===// +- +-#define _GNU_SOURCE +-#include +- +-#include +-#include +-#include +-#include +-#include "UnwindRustSgx.h" +- +-#define max_log 256 +- +-__attribute__((weak)) struct _IO_FILE *stderr = (struct _IO_FILE *)-1; +- +-static int vwrite_err(const char *format, va_list ap) +-{ +- int len = 0; +-#ifndef NDEBUG +- char s[max_log]; +- s[0]='\0'; +- len = vsnprintf(s, max_log, format, ap); +- __rust_print_err((uint8_t *)s, len); +-#endif +- return len; +-} +- +-static int write_err(const char *format, ...) +-{ +- int ret; +- va_list args; +- va_start(args, format); +- ret = vwrite_err(format, args); +- va_end(args); +- +- +- return ret; +-} +- +-__attribute__((weak)) int fprintf (FILE *__restrict __stream, +- const char *__restrict __format, ...) +-{ +- +- int ret; +- if (__stream != stderr) { +- write_err("Rust SGX Unwind supports only writing to stderr\n"); +- return -1; +- } else { +- va_list args; +- ret = 0; +- va_start(args, __format); +- ret += vwrite_err(__format, args); +- va_end(args); +- } +- +- return ret; +-} +- +-__attribute__((weak)) int fflush (FILE *__stream) +-{ +- // We do not need to do anything here. +- return 0; +-} +- +-__attribute__((weak)) void __assert_fail(const char * assertion, +- const char * file, +- unsigned int line, +- const char * function) +-{ +- write_err("%s:%d %s %s\n", file, line, function, assertion); +- abort(); +-} +- +-// We do not report stack over flow detected. +-// Calling write_err uses more stack due to the way we have implemented it. +-// With possible enabling of stack probes, we should not +-// get into __stack_chk_fail() at all. +-__attribute__((weak)) void __stack_chk_fail() { +- abort(); +-} +- +-/* +- * Below are defined for all executibles compiled for +- * x86_64-fortanix-unknown-sgx rust target. +- * Ref: rust/src/libstd/sys/sgx/abi/entry.S +- */ +- +-struct libwu_rs_alloc_meta { +- size_t alloc_size; +- // Should we put a signatre guard before ptr for oob access? +- unsigned char ptr[0]; +-}; +- +-#define META_FROM_PTR(__PTR) (struct libwu_rs_alloc_meta *) \ +- ((unsigned char *)__PTR - offsetof(struct libwu_rs_alloc_meta, ptr)) +- +-void *libuw_malloc(size_t size) +-{ +- struct libwu_rs_alloc_meta *meta; +- size_t alloc_size = size + sizeof(struct libwu_rs_alloc_meta); +- meta = (void *)__rust_c_alloc(alloc_size, sizeof(size_t)); +- if (!meta) { +- return NULL; +- } +- meta->alloc_size = alloc_size; +- return (void *)meta->ptr; +-} +- +-void libuw_free(void *p) +-{ +- struct libwu_rs_alloc_meta *meta; +- if (!p) { +- return; +- } +- meta = META_FROM_PTR(p); +- __rust_c_dealloc((unsigned char *)meta, meta->alloc_size, sizeof(size_t)); +-} +diff --git a/src/llvm-project/libunwind/src/UnwindRustSgx.h b/src/llvm-project/libunwind/src/UnwindRustSgx.h +deleted file mode 100644 +index 3c54b1676..000000000 +--- a/src/llvm-project/libunwind/src/UnwindRustSgx.h ++++ /dev/null +@@ -1,94 +0,0 @@ +-//===--------------------- UnwindRustSgx.h ----------------------------------===// +-// +-//// The LLVM Compiler Infrastructure +-//// +-//// This file is dual licensed under the MIT and the University of Illinois Open +-//// Source Licenses. See LICENSE.TXT for details. +-//// +-//// +-////===----------------------------------------------------------------------===// +- +-#if !defined(UNWIND_RUST_SGX_H) +-#define UNWIND_RUST_SGX_H +- +-#ifdef RUST_SGX +- +-#undef _GNU_SOURCE +-#define _GNU_SOURCE +-#include +-#include +-#include +-#include +- +-// We have to use RWLock from rust repo, it is defined in: +-// src/libstd/sys/sgx/rwlock.rs. +-// rwlock.rs has compile time check to ensure sizeof(RWLock) = 144. +-typedef struct { +- unsigned char opaque[144]; +-} RWLock; +- +-// The below is obtained by printing initialized bytes +-// for RWLock in rust repo: src/libstd/sys/sgx/rwlock.rs. +-#define RWLOCK_INIT { { \ +- /* 0x00 */ 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x30 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x40 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x60 */ 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- /* 0x80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ +- } } +- +-// These are the functions exposed by SGX-Rust. +-// The rust changes are available at: +-#ifdef __cplusplus +-extern "C" { +-#endif +- int __rust_rwlock_rdlock(RWLock *rwlock); +- int __rust_rwlock_wrlock(RWLock *rwlock); +- int __rust_rwlock_unlock(RWLock *rwlock); +- unsigned char *__rust_c_alloc(size_t, size_t); +- void __rust_c_dealloc(unsigned char *, size_t, size_t); +- __attribute__((noreturn)) void __rust_abort(void); +- unsigned char *__rust_encl_address(size_t); +- +-#ifndef NDEBUG +- void __rust_print_err(uint8_t *m, int s); +-#endif +- +-#ifdef __cplusplus +-} +-#endif +- +-#define abort __rust_abort +- +-#undef pthread_rwlock_t +-#undef pthread_rwlock_rdlock +-#undef pthread_rwlock_wrlock +-#undef pthread_rwlock_unlock +-#undef PTHREAD_RWLOCK_INITIALIZER +- +-#define pthread_rwlock_t RWLock +-#define pthread_rwlock_rdlock __rust_rwlock_rdlock +-#define pthread_rwlock_wrlock __rust_rwlock_wrlock +-#define pthread_rwlock_unlock __rust_rwlock_unlock +-#define PTHREAD_RWLOCK_INITIALIZER RWLOCK_INIT +- +-#define malloc libuw_malloc +-#define free libuw_free +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-void *libuw_malloc(size_t size); +-void libuw_free(void *p); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif +-#endif +diff --git a/src/llvm-project/libunwind/src/config.h b/src/llvm-project/libunwind/src/config.h +index 3f997ec3c..cc41b817a 100644 +--- a/src/llvm-project/libunwind/src/config.h ++++ b/src/llvm-project/libunwind/src/config.h +@@ -20,10 +20,6 @@ + + #include <__libunwind_config.h> + +-#ifdef RUST_SGX +-#include "UnwindRustSgx.h" +-#endif +- + // Platform specific configuration defines. + #ifdef __APPLE__ + #if defined(FOR_DYLD) +diff --git a/src/llvm-project/lld/CMakeLists.txt b/src/llvm-project/lld/CMakeLists.txt +index 02b90ece9..dcc649629 100644 +--- a/src/llvm-project/lld/CMakeLists.txt ++++ b/src/llvm-project/lld/CMakeLists.txt +@@ -246,19 +246,6 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + ) + endif() + +-if (MSVC) +- FOREACH(flag +- CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO +- CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT +- CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO +- CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT) +- if (MSVC) +- STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}") +- SET("${flag}" "${${flag}}") +- endif (MSVC) +- ENDFOREACH() +-endif() +- + add_subdirectory(Common) + add_subdirectory(tools/lld) + +diff --git a/src/llvm-project/lld/COFF/CMakeLists.txt b/src/llvm-project/lld/COFF/CMakeLists.txt +index d289bd591..55aec2685 100644 +--- a/src/llvm-project/lld/COFF/CMakeLists.txt ++++ b/src/llvm-project/lld/COFF/CMakeLists.txt +@@ -44,6 +44,7 @@ add_lld_library(lldCOFF + LINK_LIBS + lldCommon + ${LLVM_PTHREAD_LIB} ++ ${LLVM_ATOMIC_LIB} + + DEPENDS + COFFOptionsTableGen +diff --git a/src/llvm-project/lld/Common/CMakeLists.txt b/src/llvm-project/lld/Common/CMakeLists.txt +index 1ae7da1f5..9c23ed395 100644 +--- a/src/llvm-project/lld/Common/CMakeLists.txt ++++ b/src/llvm-project/lld/Common/CMakeLists.txt +@@ -1,9 +1,3 @@ +-set(LLD_SYSTEM_LIBS ${LLVM_PTHREAD_LIB}) +- +-if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) +- list(APPEND LLD_SYSTEM_LIBS atomic) +-endif() +- + find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc) + find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc) + +@@ -54,7 +48,8 @@ add_lld_library(lldCommon + Target + + LINK_LIBS +- ${LLD_SYSTEM_LIBS} ++ ${LLVM_PTHREAD_LIB} ++ ${LLVM_ATOMIC_LIB} + + DEPENDS + intrinsics_gen +diff --git a/src/llvm-project/lld/ELF/Arch/RISCV.cpp b/src/llvm-project/lld/ELF/Arch/RISCV.cpp +index 34f8f1ae0..56a516f9c 100644 +--- a/src/llvm-project/lld/ELF/Arch/RISCV.cpp ++++ b/src/llvm-project/lld/ELF/Arch/RISCV.cpp +@@ -618,9 +618,9 @@ static bool relax(InputSection &sec) { + valueDelta[sa[0].d] = delta; + delta = aux.relocDeltas[it.index()]; + } +- for (const SymbolAnchor &saElem : sa) +- if (!saElem.end) +- valueDelta[saElem.d] = delta; ++ for (const SymbolAnchor &sa : sa) ++ if (!sa.end) ++ valueDelta[sa.d] = delta; + sa = makeArrayRef(aux.anchors); + delta = 0; + +diff --git a/src/llvm-project/lld/ELF/Driver.cpp b/src/llvm-project/lld/ELF/Driver.cpp +index 296fb4220..58d863776 100644 +--- a/src/llvm-project/lld/ELF/Driver.cpp ++++ b/src/llvm-project/lld/ELF/Driver.cpp +@@ -1330,12 +1330,15 @@ static void readConfigs(opt::InputArgList &args) { + parseClangOption(std::string("-") + arg->getValue(), arg->getSpelling()); + + // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or +- // relative path. Just ignore. If not ended with "lto-wrapper", consider it an ++ // relative path. Just ignore. If not ended with "lto-wrapper" (or ++ // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an + // unsupported LLVMgold.so option and error. +- for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) +- if (!StringRef(arg->getValue()).endswith("lto-wrapper")) ++ for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) { ++ StringRef v(arg->getValue()); ++ if (!v.endswith("lto-wrapper") && !v.endswith("lto-wrapper.exe")) + error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() + + "'"); ++ } + + config->passPlugins = args::getStrings(args, OPT_load_pass_plugins); + +diff --git a/src/llvm-project/lld/ELF/InputFiles.cpp b/src/llvm-project/lld/ELF/InputFiles.cpp +index d8bf9ebf7..473809b05 100644 +--- a/src/llvm-project/lld/ELF/InputFiles.cpp ++++ b/src/llvm-project/lld/ELF/InputFiles.cpp +@@ -185,14 +185,14 @@ template static void doParseFile(InputFile *file) { + + // .so file + if (auto *f = dyn_cast(file)) { +- f->template parse(); ++ f->parse(); + return; + } + + // LLVM bitcode file + if (auto *f = dyn_cast(file)) { + ctx->bitcodeFiles.push_back(f); +- f->template parse(); ++ f->parse(); + return; + } + +@@ -1157,7 +1157,7 @@ template void ObjFile::postParse() { + continue; + } + +- if (binding == STB_WEAK) ++ if (sym.binding == STB_WEAK || binding == STB_WEAK) + continue; + std::lock_guard lock(mu); + ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); +diff --git a/src/llvm-project/lld/ELF/InputSection.cpp b/src/llvm-project/lld/ELF/InputSection.cpp +index b71fef583..8fe36eca6 100644 +--- a/src/llvm-project/lld/ELF/InputSection.cpp ++++ b/src/llvm-project/lld/ELF/InputSection.cpp +@@ -130,7 +130,7 @@ template RelsOrRelas InputSectionBase::relsOrRelas() const { + return {}; + RelsOrRelas ret; + typename ELFT::Shdr shdr = +- cast(file)->template getELFShdrs()[relSecIdx]; ++ cast(file)->getELFShdrs()[relSecIdx]; + if (shdr.sh_type == SHT_REL) { + ret.rels = makeArrayRef(reinterpret_cast( + file->mb.getBufferStart() + shdr.sh_offset), +@@ -413,7 +413,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { + // individual "gp" values used by each input object file. + // As a workaround we add the "gp" value to the relocation + // addend and save it back to the file. +- addend += sec->template getFile()->mipsGp0; ++ addend += sec->getFile()->mipsGp0; + } + + if (RelTy::IsRela) +@@ -963,9 +963,9 @@ void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { + // locations with tombstone values. + const RelsOrRelas rels = sec->template relsOrRelas(); + if (rels.areRelocsRel()) +- sec->template relocateNonAlloc(buf, rels.rels); ++ sec->relocateNonAlloc(buf, rels.rels); + else +- sec->template relocateNonAlloc(buf, rels.relas); ++ sec->relocateNonAlloc(buf, rels.relas); + } + + void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { +@@ -1172,8 +1172,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf, + // conservative. + if (Defined *d = dyn_cast(rel.sym)) + if (InputSection *isec = cast_or_null(d->section)) +- if (!isec || !isec->template getFile() || +- isec->template getFile()->splitStack) ++ if (!isec || !isec->getFile() || isec->getFile()->splitStack) + continue; + + if (enclosingPrologueAttempted(rel.offset, prologues)) +diff --git a/src/llvm-project/lld/ELF/SyntheticSections.cpp b/src/llvm-project/lld/ELF/SyntheticSections.cpp +index 9a21fdec6..b359c2e7b 100644 +--- a/src/llvm-project/lld/ELF/SyntheticSections.cpp ++++ b/src/llvm-project/lld/ELF/SyntheticSections.cpp +@@ -197,7 +197,7 @@ std::unique_ptr> MipsOptionsSection::create() { + auto *opt = reinterpret_cast(d.data()); + if (opt->kind == ODK_REGINFO) { + reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; +- sec->template getFile()->mipsGp0 = opt->getRegInfo().ri_gp_value; ++ sec->getFile()->mipsGp0 = opt->getRegInfo().ri_gp_value; + break; + } + +@@ -249,7 +249,7 @@ std::unique_ptr> MipsReginfoSection::create() { + + auto *r = reinterpret_cast(sec->rawData.data()); + reginfo.ri_gprmask |= r->ri_gprmask; +- sec->template getFile()->mipsGp0 = r->ri_gp_value; ++ sec->getFile()->mipsGp0 = r->ri_gp_value; + }; + + return std::make_unique>(reginfo); +@@ -1662,8 +1662,8 @@ void RelocationBaseSection::partitionRels() { + if (!combreloc) + return; + const RelType relativeRel = target->relativeRel; +- numRelativeRelocs = llvm::partition( +- relocs, [=](const DynamicReloc &r) { return r.type == relativeRel; }) - ++ numRelativeRelocs = ++ llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }) - + relocs.begin(); + } + +@@ -3360,7 +3360,7 @@ template void elf::splitSections() { + if (auto *s = dyn_cast(sec)) + s->splitIntoPieces(); + else if (auto *eh = dyn_cast(sec)) +- eh->template split(); ++ eh->split(); + } + }); + } +diff --git a/src/llvm-project/lld/MachO/UnwindInfoSection.cpp b/src/llvm-project/lld/MachO/UnwindInfoSection.cpp +index ca6cbdfbb..8f267251b 100644 +--- a/src/llvm-project/lld/MachO/UnwindInfoSection.cpp ++++ b/src/llvm-project/lld/MachO/UnwindInfoSection.cpp +@@ -158,7 +158,7 @@ class UnwindInfoSectionImpl final : public UnwindInfoSection { + public: + UnwindInfoSectionImpl() : cuOffsets(target->wordSize) {} + uint64_t getSize() const override { return unwindInfoSize; } +- void prepareRelocations() override; ++ void prepare() override; + void finalize() override; + void writeTo(uint8_t *buf) const override; + +@@ -166,6 +166,7 @@ private: + void prepareRelocations(ConcatInputSection *); + void relocateCompactUnwind(std::vector &); + void encodePersonalities(); ++ Symbol *canonicalizePersonality(Symbol *); + + uint64_t unwindInfoSize = 0; + std::vector symbolsVec; +@@ -218,14 +219,24 @@ void UnwindInfoSection::addSymbol(const Defined *d) { + } + } + +-void UnwindInfoSectionImpl::prepareRelocations() { ++void UnwindInfoSectionImpl::prepare() { + // This iteration needs to be deterministic, since prepareRelocations may add + // entries to the GOT. Hence the use of a MapVector for + // UnwindInfoSection::symbols. + for (const Defined *d : make_second_range(symbols)) +- if (d->unwindEntry && +- d->unwindEntry->getName() == section_names::compactUnwind) +- prepareRelocations(d->unwindEntry); ++ if (d->unwindEntry) { ++ if (d->unwindEntry->getName() == section_names::compactUnwind) { ++ prepareRelocations(d->unwindEntry); ++ } else { ++ // We don't have to add entries to the GOT here because FDEs have ++ // explicit GOT relocations, so Writer::scanRelocations() will add those ++ // GOT entries. However, we still need to canonicalize the personality ++ // pointers (like prepareRelocations() does for CU entries) in order ++ // to avoid overflowing the 3-personality limit. ++ FDE &fde = cast(d->getFile())->fdes[d->unwindEntry]; ++ fde.personality = canonicalizePersonality(fde.personality); ++ } ++ } + } + + // Compact unwind relocations have different semantics, so we handle them in a +@@ -279,6 +290,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { + continue; + } + ++ // Similar to canonicalizePersonality(), but we also register a GOT entry. + if (auto *defined = dyn_cast(s)) { + // Check if we have created a synthetic symbol at the same address. + Symbol *&personality = +@@ -291,6 +303,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { + } + continue; + } ++ + assert(isa(s)); + in.got->addEntry(s); + continue; +@@ -320,6 +333,18 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) { + } + } + ++Symbol *UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) { ++ if (auto *defined = dyn_cast_or_null(personality)) { ++ // Check if we have created a synthetic symbol at the same address. ++ Symbol *&synth = personalityTable[{defined->isec, defined->value}]; ++ if (synth == nullptr) ++ synth = defined; ++ else if (synth != defined) ++ return synth; ++ } ++ return personality; ++} ++ + // We need to apply the relocations to the pre-link compact unwind section + // before converting it to post-link form. There should only be absolute + // relocations here: since we are not emitting the pre-link CU section, there +diff --git a/src/llvm-project/lld/MachO/UnwindInfoSection.h b/src/llvm-project/lld/MachO/UnwindInfoSection.h +index c6b334731..f2bc3213a 100644 +--- a/src/llvm-project/lld/MachO/UnwindInfoSection.h ++++ b/src/llvm-project/lld/MachO/UnwindInfoSection.h +@@ -24,7 +24,7 @@ public: + // section entirely. + bool isNeeded() const override { return !allEntriesAreOmitted; } + void addSymbol(const Defined *); +- virtual void prepareRelocations() = 0; ++ virtual void prepare() = 0; + + protected: + UnwindInfoSection(); +diff --git a/src/llvm-project/lld/MachO/Writer.cpp b/src/llvm-project/lld/MachO/Writer.cpp +index 3c44a60f4..ce9672dd0 100644 +--- a/src/llvm-project/lld/MachO/Writer.cpp ++++ b/src/llvm-project/lld/MachO/Writer.cpp +@@ -675,7 +675,7 @@ void Writer::scanRelocations() { + } + } + +- in.unwindInfo->prepareRelocations(); ++ in.unwindInfo->prepare(); + } + + void Writer::scanSymbols() { +diff --git a/src/llvm-project/lld/test/ELF/comdat-binding2.s b/src/llvm-project/lld/test/ELF/comdat-binding2.s +new file mode 100644 +index 000000000..3ffd72528 +--- /dev/null ++++ b/src/llvm-project/lld/test/ELF/comdat-binding2.s +@@ -0,0 +1,42 @@ ++# REQUIRES: x86 ++## Test we don't report duplicate definition errors when mixing Clang STB_WEAK ++## and GCC STB_GNU_UNIQUE symbols. ++ ++# RUN: rm -rf %t && split-file %s %t && cd %t ++# RUN: llvm-mc -filetype=obj -triple=x86_64 weak.s -o weak.o ++# RUN: llvm-mc -filetype=obj -triple=x86_64 unique.s -o unique.o ++# RUN: ld.lld weak.o unique.o -o weak ++# RUN: llvm-readelf -s weak | FileCheck %s --check-prefix=WEAK ++# RUN: ld.lld unique.o weak.o -o unique ++# RUN: llvm-readelf -s unique | FileCheck %s --check-prefix=UNIQUE ++ ++# WEAK: OBJECT WEAK DEFAULT [[#]] _ZN1BIiE1aE ++# UNIQUE: OBJECT UNIQUE DEFAULT [[#]] _ZN1BIiE1aE ++ ++#--- weak.s ++## Clang ++ .type _ZN1BIiE1aE,@object ++ .section .bss._ZN1BIiE1aE,"aGwR",@nobits,_ZN1BIiE1aE,comdat ++ .weak _ZN1BIiE1aE ++_ZN1BIiE1aE: ++ .zero 4 ++ ++ .type _ZGVN1BIiE1aE,@object ++ .section .bss._ZGVN1BIiE1aE,"aGw",@nobits,_ZN1BIiE1aE,comdat ++ .weak _ZGVN1BIiE1aE ++_ZGVN1BIiE1aE: ++ .quad 0 ++ ++#--- unique.s ++## GCC -fgnu-unique. Note the different group signature for the second group. ++ .weak _ZN1BIiE1aE ++ .section .bss._ZN1BIiE1aE,"awG",@nobits,_ZN1BIiE1aE,comdat ++ .type _ZN1BIiE1aE, @gnu_unique_object ++_ZN1BIiE1aE: ++ .zero 4 ++ ++ .weak _ZGVN1BIiE1aE ++ .section .bss._ZGVN1BIiE1aE,"awG",@nobits,_ZGVN1BIiE1aE,comdat ++ .type _ZGVN1BIiE1aE, @gnu_unique_object ++_ZGVN1BIiE1aE: ++ .zero 8 +diff --git a/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s b/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s +index 2935bad14..dd39139b6 100644 +--- a/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s ++++ b/src/llvm-project/lld/test/ELF/lto-plugin-ignore.s +@@ -8,7 +8,9 @@ + # RUN: ld.lld %t.o -o /dev/null \ + # RUN: -plugin path/to/liblto_plugin.so \ + # RUN: -plugin-opt=/path/to/lto-wrapper \ ++# RUN: -plugin-opt=/path/to/lto-wrapper.exe \ + # RUN: -plugin-opt=relative/path/to/lto-wrapper \ ++# RUN: -plugin-opt=relative/path/to/lto-wrapper.exe \ + # RUN: -plugin-opt=-fresolution=zed \ + # RUN: -plugin-opt=-pass-through=-lgcc \ + # RUN: -plugin-opt=-pass-through=-lgcc_eh \ +diff --git a/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s b/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s +new file mode 100644 +index 000000000..b14ddb234 +--- /dev/null ++++ b/src/llvm-project/lld/test/MachO/eh-frame-personality-dedup.s +@@ -0,0 +1,43 @@ ++# REQUIRES: x86 ++# RUN: rm -rf %t; split-file %s %t ++# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/eh-frame.s -o %t/eh-frame.o ++# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/cu.s -o %t/cu.o ++# RUN: %lld -dylib %t/cu.o %t/eh-frame.o -o %t/out ++ ++## Sanity check: we want our input to contain a section (and not symbol) ++## relocation for the personality reference. ++# RUN: llvm-readobj --relocations %t/cu.o | FileCheck %s --check-prefix=SECT-RELOC ++# SECT-RELOC: Section __compact_unwind { ++# SECT-RELOC-NEXT: __text ++# SECT-RELOC-NEXT: __text ++# SECT-RELOC-NEXT: } ++ ++## Verify that the personality referenced via a symbol reloc in eh-frame.s gets ++## dedup'ed with the personality referenced via a section reloc in cu.s. ++# RUN: llvm-objdump --macho --unwind-info %t/out | FileCheck %s ++# CHECK: Personality functions: (count = 1) ++ ++#--- eh-frame.s ++_fun: ++ .cfi_startproc ++ .cfi_personality 155, _my_personality ++ ## cfi_escape cannot be encoded in compact unwind ++ .cfi_escape 0 ++ ret ++ .cfi_endproc ++ ++.subsections_via_symbols ++ ++#--- cu.s ++.globl _my_personality ++_fun: ++ .cfi_startproc ++ .cfi_personality 155, _my_personality ++ .cfi_def_cfa_offset 16 ++ ret ++ .cfi_endproc ++ ++_my_personality: ++ nop ++ ++.subsections_via_symbols +diff --git a/src/llvm-project/lld/test/wasm/export-all.s b/src/llvm-project/lld/test/wasm/export-all.s +index 009da9f6a..5af835ce4 100644 +--- a/src/llvm-project/lld/test/wasm/export-all.s ++++ b/src/llvm-project/lld/test/wasm/export-all.s +@@ -40,9 +40,12 @@ foo: + # CHECK-NEXT: - Name: __heap_base + # CHECK-NEXT: Kind: GLOBAL + # CHECK-NEXT: Index: 4 +-# CHECK-NEXT: - Name: __memory_base ++# CHECK-NEXT: - Name: __heap_end + # CHECK-NEXT: Kind: GLOBAL + # CHECK-NEXT: Index: 5 +-# CHECK-NEXT: - Name: __table_base ++# CHECK-NEXT: - Name: __memory_base + # CHECK-NEXT: Kind: GLOBAL + # CHECK-NEXT: Index: 6 ++# CHECK-NEXT: - Name: __table_base ++# CHECK-NEXT: Kind: GLOBAL ++# CHECK-NEXT: Index: 7 +diff --git a/src/llvm-project/lld/test/wasm/mutable-global-exports.s b/src/llvm-project/lld/test/wasm/mutable-global-exports.s +index e2e45ff93..98009610a 100644 +--- a/src/llvm-project/lld/test/wasm/mutable-global-exports.s ++++ b/src/llvm-project/lld/test/wasm/mutable-global-exports.s +@@ -79,10 +79,13 @@ _start: + # CHECK-ALL-NEXT: - Name: __heap_base + # CHECK-ALL-NEXT: Kind: GLOBAL + # CHECK-ALL-NEXT: Index: 5 +-# CHECK-ALL-NEXT: - Name: __memory_base ++# CHECK-ALL-NEXT: - Name: __heap_end + # CHECK-ALL-NEXT: Kind: GLOBAL + # CHECK-ALL-NEXT: Index: 6 +-# CHECK-ALL-NEXT: - Name: __table_base ++# CHECK-ALL-NEXT: - Name: __memory_base + # CHECK-ALL-NEXT: Kind: GLOBAL + # CHECK-ALL-NEXT: Index: 7 ++# CHECK-ALL-NEXT: - Name: __table_base ++# CHECK-ALL-NEXT: Kind: GLOBAL ++# CHECK-ALL-NEXT: Index: 8 + # CHECK-ALL-NEXT: - Type: CODE +diff --git a/src/llvm-project/lld/wasm/Driver.cpp b/src/llvm-project/lld/wasm/Driver.cpp +index 0a0f0c8a0..4afbfe241 100644 +--- a/src/llvm-project/lld/wasm/Driver.cpp ++++ b/src/llvm-project/lld/wasm/Driver.cpp +@@ -681,6 +681,7 @@ static void createOptionalSymbols() { + if (!config->isPic) { + WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); + WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); ++ WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end"); + WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); + WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); + if (config->is64.value_or(false)) +diff --git a/src/llvm-project/lld/wasm/Symbols.cpp b/src/llvm-project/lld/wasm/Symbols.cpp +index e0670cea6..a79c5bec3 100644 +--- a/src/llvm-project/lld/wasm/Symbols.cpp ++++ b/src/llvm-project/lld/wasm/Symbols.cpp +@@ -83,6 +83,7 @@ DefinedData *WasmSym::dsoHandle; + DefinedData *WasmSym::dataEnd; + DefinedData *WasmSym::globalBase; + DefinedData *WasmSym::heapBase; ++DefinedData *WasmSym::heapEnd; + DefinedData *WasmSym::initMemoryFlag; + GlobalSymbol *WasmSym::stackPointer; + GlobalSymbol *WasmSym::tlsBase; +diff --git a/src/llvm-project/lld/wasm/Symbols.h b/src/llvm-project/lld/wasm/Symbols.h +index c17b720a9..32e75a69c 100644 +--- a/src/llvm-project/lld/wasm/Symbols.h ++++ b/src/llvm-project/lld/wasm/Symbols.h +@@ -538,11 +538,14 @@ struct WasmSym { + // Symbol marking the end of the data and bss. + static DefinedData *dataEnd; + +- // __heap_base +- // Symbol marking the end of the data, bss and explicit stack. Any linear +- // memory following this address is not used by the linked code and can +- // therefore be used as a backing store for brk()/malloc() implementations. ++ // __heap_base/__heap_end ++ // Symbols marking the beginning and end of the "heap". It starts at the end ++ // of the data, bss and explicit stack, and extends to the end of the linear ++ // memory allocated by wasm-ld. This region of memory is not used by the ++ // linked code, so it may be used as a backing store for `sbrk` or `malloc` ++ // implementations. + static DefinedData *heapBase; ++ static DefinedData *heapEnd; + + // __wasm_init_memory_flag + // Symbol whose contents are nonzero iff memory has already been initialized. +diff --git a/src/llvm-project/lld/wasm/Writer.cpp b/src/llvm-project/lld/wasm/Writer.cpp +index f98c95526..f6bbaa02b 100644 +--- a/src/llvm-project/lld/wasm/Writer.cpp ++++ b/src/llvm-project/lld/wasm/Writer.cpp +@@ -340,10 +340,20 @@ void Writer::layoutMemory() { + Twine(maxMemorySetting)); + memoryPtr = config->initialMemory; + } +- out.memorySec->numMemoryPages = +- alignTo(memoryPtr, WasmPageSize) / WasmPageSize; ++ ++ memoryPtr = alignTo(memoryPtr, WasmPageSize); ++ ++ out.memorySec->numMemoryPages = memoryPtr / WasmPageSize; + log("mem: total pages = " + Twine(out.memorySec->numMemoryPages)); + ++ if (WasmSym::heapEnd) { ++ // Set `__heap_end` to follow the end of the statically allocated linear ++ // memory. The fact that this comes last means that a malloc/brk ++ // implementation can grow the heap at runtime. ++ log("mem: heap end = " + Twine(memoryPtr)); ++ WasmSym::heapEnd->setVA(memoryPtr); ++ } ++ + if (config->maxMemory != 0) { + if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize)) + error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); +@@ -363,7 +373,7 @@ void Writer::layoutMemory() { + if (config->isPic) + max = maxMemorySetting; + else +- max = alignTo(memoryPtr, WasmPageSize); ++ max = memoryPtr; + } + out.memorySec->maxMemoryPages = max / WasmPageSize; + log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); +diff --git a/src/llvm-project/lldb/bindings/CMakeLists.txt b/src/llvm-project/lldb/bindings/CMakeLists.txt +index c8aa0bcf9..9eed2f1e6 100644 +--- a/src/llvm-project/lldb/bindings/CMakeLists.txt ++++ b/src/llvm-project/lldb/bindings/CMakeLists.txt +@@ -26,8 +26,6 @@ set(SWIG_COMMON_FLAGS + -features autodoc + -I${LLDB_SOURCE_DIR}/include + -I${CMAKE_CURRENT_SOURCE_DIR} +- -D__STDC_LIMIT_MACROS +- -D__STDC_CONSTANT_MACROS + ${DARWIN_EXTRAS} + ) + +diff --git a/src/llvm-project/lldb/bindings/interfaces.swig b/src/llvm-project/lldb/bindings/interfaces.swig +index c9a6d0f06..021c7683d 100644 +--- a/src/llvm-project/lldb/bindings/interfaces.swig ++++ b/src/llvm-project/lldb/bindings/interfaces.swig +@@ -1,8 +1,5 @@ + /* Various liblldb typedefs that SWIG needs to know about. */ + #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ +-/* The ISO C99 standard specifies that in C++ implementations limit macros such +- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ +-#define __STDC_LIMIT_MACROS + %include "stdint.i" + + %include "lldb/lldb-defines.h" +diff --git a/src/llvm-project/lldb/bindings/python/python-typemaps.swig b/src/llvm-project/lldb/bindings/python/python-typemaps.swig +index bf3de66b9..d45431c77 100644 +--- a/src/llvm-project/lldb/bindings/python/python-typemaps.swig ++++ b/src/llvm-project/lldb/bindings/python/python-typemaps.swig +@@ -435,7 +435,7 @@ template <> bool SetNumberFromPyObject(double &number, PyObject *obj) { + + %typemap(out) lldb::FileSP { + $result = nullptr; +- lldb::FileSP &sp = $1; ++ const lldb::FileSP &sp = $1; + if (sp) { + PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); + if (!pyfile.IsValid()) +diff --git a/src/llvm-project/lldb/include/lldb/API/SBType.h b/src/llvm-project/lldb/include/lldb/API/SBType.h +index 244d328b5..aa45aeeec 100644 +--- a/src/llvm-project/lldb/include/lldb/API/SBType.h ++++ b/src/llvm-project/lldb/include/lldb/API/SBType.h +@@ -182,6 +182,8 @@ public: + + lldb::SBType GetTemplateArgumentType(uint32_t idx); + ++ /// Return the TemplateArgumentKind of the template argument at index idx. ++ /// Variadic argument packs are automatically expanded. + lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx); + + lldb::SBType GetFunctionReturnType(); +diff --git a/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h b/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h +index 0ad05a275..aefd19d0a 100644 +--- a/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h ++++ b/src/llvm-project/lldb/include/lldb/Symbol/CompilerType.h +@@ -338,14 +338,28 @@ public: + GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes, + std::vector &child_indexes) const; + +- size_t GetNumTemplateArguments() const; +- +- lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const; +- CompilerType GetTypeTemplateArgument(size_t idx) const; ++ /// Return the number of template arguments the type has. ++ /// If expand_pack is true, then variadic argument packs are automatically ++ /// expanded to their supplied arguments. If it is false an argument pack ++ /// will only count as 1 argument. ++ size_t GetNumTemplateArguments(bool expand_pack = false) const; ++ ++ // Return the TemplateArgumentKind of the template argument at index idx. ++ // If expand_pack is true, then variadic argument packs are automatically ++ // expanded to their supplied arguments. With expand_pack set to false, an ++ // arguement pack will count as 1 argument and return a type of Pack. ++ lldb::TemplateArgumentKind ++ GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const; ++ CompilerType GetTypeTemplateArgument(size_t idx, ++ bool expand_pack = false) const; + + /// Returns the value of the template argument and its type. ++ /// If expand_pack is true, then variadic argument packs are automatically ++ /// expanded to their supplied arguments. With expand_pack set to false, an ++ /// arguement pack will count as 1 argument and it is invalid to call this ++ /// method on the pack argument. + llvm::Optional +- GetIntegralTemplateArgument(size_t idx) const; ++ GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; + + CompilerType GetTypeForFormatters() const; + +diff --git a/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h b/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h +index be5783596..769449a49 100644 +--- a/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h ++++ b/src/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h +@@ -346,14 +346,18 @@ public: + const char *name, bool omit_empty_base_classes, + std::vector &child_indexes) = 0; + +- virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type); ++ virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, ++ bool expand_pack); + + virtual lldb::TemplateArgumentKind +- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx); +- virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, +- size_t idx); ++ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, ++ bool expand_pack); ++ virtual CompilerType ++ GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, ++ bool expand_pack); + virtual llvm::Optional +- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx); ++ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, ++ bool expand_pack); + + // Dumping types + +diff --git a/src/llvm-project/lldb/source/API/SBType.cpp b/src/llvm-project/lldb/source/API/SBType.cpp +index 533930c05..adc60a084 100644 +--- a/src/llvm-project/lldb/source/API/SBType.cpp ++++ b/src/llvm-project/lldb/source/API/SBType.cpp +@@ -542,7 +542,8 @@ uint32_t SBType::GetNumberOfTemplateArguments() { + LLDB_INSTRUMENT_VA(this); + + if (IsValid()) +- return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(); ++ return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments( ++ /*expand_pack=*/true); + return 0; + } + +@@ -553,13 +554,15 @@ lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) { + return SBType(); + + CompilerType type; ++ const bool expand_pack = true; + switch(GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindType: +- type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx); ++ type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument( ++ idx, expand_pack); + break; + case eTemplateArgumentKindIntegral: + type = m_opaque_sp->GetCompilerType(false) +- .GetIntegralTemplateArgument(idx) ++ .GetIntegralTemplateArgument(idx, expand_pack) + ->type; + break; + default: +@@ -574,7 +577,8 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) { + LLDB_INSTRUMENT_VA(this, idx); + + if (IsValid()) +- return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx); ++ return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind( ++ idx, /*expand_pack=*/true); + return eTemplateArgumentKindNull; + } + +diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp +index fa4e8fb42..c0a879555 100644 +--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp ++++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/Perf.cpp +@@ -127,6 +127,10 @@ llvm::Error PerfEvent::MmapMetadataAndDataBuffer(size_t num_data_pages, + } + + llvm::Error PerfEvent::MmapAuxBuffer(size_t num_aux_pages) { ++#ifndef PERF_ATTR_SIZE_VER5 ++ return createStringError(inconvertibleErrorCode(), ++ "Intel PT Linux perf event not supported"); ++#else + if (num_aux_pages == 0) + return Error::success(); + +@@ -143,6 +147,7 @@ llvm::Error PerfEvent::MmapAuxBuffer(size_t num_aux_pages) { + return Error::success(); + } else + return mmap_aux.takeError(); ++#endif + } + + llvm::Error PerfEvent::MmapMetadataAndBuffers(size_t num_data_pages, +@@ -172,16 +177,24 @@ perf_event_mmap_page &PerfEvent::GetMetadataPage() const { + } + + ArrayRef PerfEvent::GetDataBuffer() const { ++#ifndef PERF_ATTR_SIZE_VER5 ++ llvm_unreachable("Intel PT Linux perf event not supported"); ++#else + perf_event_mmap_page &mmap_metadata = GetMetadataPage(); + return {reinterpret_cast(m_metadata_data_base.get()) + + mmap_metadata.data_offset, +- static_cast(mmap_metadata.data_size)}; ++ static_cast(mmap_metadata.data_size)}; ++#endif + } + + ArrayRef PerfEvent::GetAuxBuffer() const { ++#ifndef PERF_ATTR_SIZE_VER5 ++ llvm_unreachable("Intel PT Linux perf event not supported"); ++#else + perf_event_mmap_page &mmap_metadata = GetMetadataPage(); + return {reinterpret_cast(m_aux_base.get()), +- static_cast(mmap_metadata.aux_size)}; ++ static_cast(mmap_metadata.aux_size)}; ++#endif + } + + Expected> PerfEvent::GetReadOnlyDataBuffer() { +@@ -190,6 +203,10 @@ Expected> PerfEvent::GetReadOnlyDataBuffer() { + // this piece of code updates some pointers. See more about data_tail + // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. + ++#ifndef PERF_ATTR_SIZE_VER5 ++ return createStringError(inconvertibleErrorCode(), ++ "Intel PT Linux perf event not supported"); ++#else + bool was_enabled = m_enabled; + if (Error err = DisableWithIoctl()) + return std::move(err); +@@ -226,6 +243,7 @@ Expected> PerfEvent::GetReadOnlyDataBuffer() { + } + + return output; ++#endif + } + + Expected> PerfEvent::GetReadOnlyAuxBuffer() { +@@ -234,6 +252,10 @@ Expected> PerfEvent::GetReadOnlyAuxBuffer() { + // this piece of code updates some pointers. See more about aux_tail + // in https://man7.org/linux/man-pages/man2/perf_event_open.2.html. + ++#ifndef PERF_ATTR_SIZE_VER5 ++ return createStringError(inconvertibleErrorCode(), ++ "Intel PT Linux perf event not supported"); ++#else + bool was_enabled = m_enabled; + if (Error err = DisableWithIoctl()) + return std::move(err); +@@ -266,6 +288,7 @@ Expected> PerfEvent::GetReadOnlyAuxBuffer() { + } + + return output; ++#endif + } + + Error PerfEvent::DisableWithIoctl() { +@@ -297,11 +320,15 @@ Error PerfEvent::EnableWithIoctl() { + } + + size_t PerfEvent::GetEffectiveDataBufferSize() const { ++#ifndef PERF_ATTR_SIZE_VER5 ++ llvm_unreachable("Intel PT Linux perf event not supported"); ++#else + perf_event_mmap_page &mmap_metadata = GetMetadataPage(); + if (mmap_metadata.data_head < mmap_metadata.data_size) + return mmap_metadata.data_head; + else + return mmap_metadata.data_size; // The buffer has wrapped. ++#endif + } + + Expected +diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +index c6eb693bb..a1ebe5830 100644 +--- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp ++++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +@@ -7096,7 +7096,8 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + } + + size_t +-TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { ++TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, ++ bool expand_pack) { + if (!type) + return 0; + +@@ -7111,8 +7112,17 @@ TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { + const clang::ClassTemplateSpecializationDecl *template_decl = + llvm::dyn_cast( + cxx_record_decl); +- if (template_decl) +- return template_decl->getTemplateArgs().size(); ++ if (template_decl) { ++ const auto &template_arg_list = template_decl->getTemplateArgs(); ++ size_t num_args = template_arg_list.size(); ++ assert(num_args && "template specialization without any args"); ++ if (expand_pack && num_args) { ++ const auto &pack = template_arg_list[num_args - 1]; ++ if (pack.getKind() == clang::TemplateArgument::Pack) ++ num_args += pack.pack_size() - 1; ++ } ++ return num_args; ++ } + } + } + break; +@@ -7149,15 +7159,51 @@ TypeSystemClang::GetAsTemplateSpecialization( + } + } + ++const TemplateArgument * ++GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, ++ size_t idx, bool expand_pack) { ++ const auto &args = decl->getTemplateArgs(); ++ const size_t args_size = args.size(); ++ ++ assert(args_size && "template specialization without any args"); ++ if (!args_size) ++ return nullptr; ++ ++ const size_t last_idx = args_size - 1; ++ ++ // We're asked for a template argument that can't be a parameter pack, so ++ // return it without worrying about 'expand_pack'. ++ if (idx < last_idx) ++ return &args[idx]; ++ ++ // We're asked for the last template argument but we don't want/need to ++ // expand it. ++ if (!expand_pack || args[last_idx].getKind() != clang::TemplateArgument::Pack) ++ return idx >= args.size() ? nullptr : &args[idx]; ++ ++ // Index into the expanded pack. ++ // Note that 'idx' counts from the beginning of all template arguments ++ // (including the ones preceding the parameter pack). ++ const auto &pack = args[last_idx]; ++ const size_t pack_idx = idx - last_idx; ++ const size_t pack_size = pack.pack_size(); ++ assert(pack_idx < pack_size && "parameter pack index out-of-bounds"); ++ return &pack.pack_elements()[pack_idx]; ++} ++ + lldb::TemplateArgumentKind + TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, +- size_t arg_idx) { ++ size_t arg_idx, bool expand_pack) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); +- if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size()) ++ if (!template_decl) ++ return eTemplateArgumentKindNull; ++ ++ const auto *arg = GetNthTemplateArgument(template_decl, arg_idx, expand_pack); ++ if (!arg) + return eTemplateArgumentKindNull; + +- switch (template_decl->getTemplateArgs()[arg_idx].getKind()) { ++ switch (arg->getKind()) { + case clang::TemplateArgument::Null: + return eTemplateArgumentKindNull; + +@@ -7190,35 +7236,32 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, + + CompilerType + TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, +- size_t idx) { ++ size_t idx, bool expand_pack) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); +- if (!template_decl || idx >= template_decl->getTemplateArgs().size()) ++ if (!template_decl) + return CompilerType(); + +- const clang::TemplateArgument &template_arg = +- template_decl->getTemplateArgs()[idx]; +- if (template_arg.getKind() != clang::TemplateArgument::Type) ++ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); ++ if (!arg || arg->getKind() != clang::TemplateArgument::Type) + return CompilerType(); + +- return GetType(template_arg.getAsType()); ++ return GetType(arg->getAsType()); + } + + Optional + TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, +- size_t idx) { ++ size_t idx, bool expand_pack) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); +- if (! template_decl || idx >= template_decl->getTemplateArgs().size()) ++ if (!template_decl) + return llvm::None; + +- const clang::TemplateArgument &template_arg = +- template_decl->getTemplateArgs()[idx]; +- if (template_arg.getKind() != clang::TemplateArgument::Integral) ++ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); ++ if (!arg || arg->getKind() != clang::TemplateArgument::Integral) + return llvm::None; + +- return { +- {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}}; ++ return {{arg->getAsIntegral(), GetType(arg->getIntegralType())}}; + } + + CompilerType TypeSystemClang::GetTypeForFormatters(void *type) { +diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +index 24dbb71c8..7f25a6df5 100644 +--- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h ++++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +@@ -91,7 +91,7 @@ public: + void SetOwningModule(OptionalClangModuleID id); + /// \} + }; +- ++ + /// A TypeSystem implementation based on Clang. + /// + /// This class uses a single clang::ASTContext as the backend for storing +@@ -334,7 +334,7 @@ public: + + llvm::SmallVector names; + llvm::SmallVector args; +- ++ + const char * pack_name = nullptr; + std::unique_ptr packed_args; + }; +@@ -537,7 +537,7 @@ public: + #ifndef NDEBUG + bool Verify(lldb::opaque_compiler_type_t type) override; + #endif +- ++ + bool IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size, + bool *is_incomplete) override; +@@ -810,16 +810,17 @@ public: + const char *name, bool omit_empty_base_classes, + std::vector &child_indexes) override; + +- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; ++ size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, ++ bool expand_pack) override; + + lldb::TemplateArgumentKind +- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, +- size_t idx) override; ++ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, ++ bool expand_pack) override; + CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, +- size_t idx) override; ++ size_t idx, bool expand_pack) override; + llvm::Optional +- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, +- size_t idx) override; ++ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, ++ bool expand_pack) override; + + CompilerType GetTypeForFormatters(void *type) override; + +diff --git a/src/llvm-project/lldb/source/Symbol/CompilerType.cpp b/src/llvm-project/lldb/source/Symbol/CompilerType.cpp +index ac98352c2..bef456583 100644 +--- a/src/llvm-project/lldb/source/Symbol/CompilerType.cpp ++++ b/src/llvm-project/lldb/source/Symbol/CompilerType.cpp +@@ -659,30 +659,32 @@ size_t CompilerType::GetIndexOfChildMemberWithName( + return 0; + } + +-size_t CompilerType::GetNumTemplateArguments() const { ++size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const { + if (IsValid()) { +- return m_type_system->GetNumTemplateArguments(m_type); ++ return m_type_system->GetNumTemplateArguments(m_type, expand_pack); + } + return 0; + } + +-TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const { ++TemplateArgumentKind ++CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const { + if (IsValid()) +- return m_type_system->GetTemplateArgumentKind(m_type, idx); ++ return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack); + return eTemplateArgumentKindNull; + } + +-CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const { ++CompilerType CompilerType::GetTypeTemplateArgument(size_t idx, ++ bool expand_pack) const { + if (IsValid()) { +- return m_type_system->GetTypeTemplateArgument(m_type, idx); ++ return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack); + } + return CompilerType(); + } + + llvm::Optional +-CompilerType::GetIntegralTemplateArgument(size_t idx) const { ++CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const { + if (IsValid()) +- return m_type_system->GetIntegralTemplateArgument(m_type, idx); ++ return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack); + return llvm::None; + } + +diff --git a/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp b/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp +index 3092dc0bf..412373533 100644 +--- a/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp ++++ b/src/llvm-project/lldb/source/Symbol/TypeSystem.cpp +@@ -118,23 +118,25 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) { + return CompilerType(this, type); + } + +-size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { ++size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, ++ bool expand_pack) { + return 0; + } + + TemplateArgumentKind +-TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { ++TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx, ++ bool expand_pack) { + return eTemplateArgumentKindNull; + } + + CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, +- size_t idx) { ++ size_t idx, bool expand_pack) { + return CompilerType(); + } + + llvm::Optional +-TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, +- size_t idx) { ++TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, ++ bool expand_pack) { + return llvm::None; + } + +diff --git a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py +new file mode 100644 +index 000000000..180d3f503 +--- /dev/null ++++ b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py +@@ -0,0 +1,38 @@ ++""" ++Test that the type of arguments to C++ template classes that have variadic ++parameters can be enumerated. ++""" ++import lldb ++from lldbsuite.test.decorators import * ++from lldbsuite.test.lldbtest import * ++from lldbsuite.test import lldbutil ++ ++ ++class TemplatePackArgsTestCase(TestBase): ++ ++ mydir = TestBase.compute_mydir(__file__) ++ ++ def test_template_argument_pack(self): ++ self.build() ++ (_, _, thread, _) = lldbutil.run_to_source_breakpoint(self, ++ 'breakpoint here', lldb.SBFileSpec('main.cpp'), exe_name = 'a.out') ++ frame = thread.GetSelectedFrame() ++ ++ empty_pack = frame.FindVariable('emptyPack') ++ self.assertTrue(empty_pack.IsValid(), ++ 'make sure we find the emptyPack variable') ++ ++ only_pack = frame.FindVariable('onlyPack') ++ self.assertTrue(only_pack.IsValid(), ++ 'make sure we find the onlyPack variable') ++ self.assertEqual(only_pack.GetType().GetNumberOfTemplateArguments(), 4) ++ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(0).GetName(), 'int') ++ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(1).GetName(), 'char') ++ self.assertEqual(only_pack.GetType().GetTemplateArgumentType(2).GetName(), 'double') ++ # Access the C template parameter. ++ nested_template = only_pack.GetType().GetTemplateArgumentType(3) ++ self.assertEqual(nested_template.GetName(), 'D') ++ self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3) ++ self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), 'int') ++ self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), 'int') ++ self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), 'bool') +diff --git a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp +index 8bb0a42b5..26f8eab54 100644 +--- a/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp ++++ b/src/llvm-project/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp +@@ -26,7 +26,13 @@ template <> struct D : D { + bool argsAre_Int_bool() { return true; } + }; + ++template struct OnlyPack {}; ++template struct EmptyPack {}; ++ + int main(int argc, char const *argv[]) { ++ EmptyPack emptyPack; ++ OnlyPack> onlyPack; ++ + C myC; + C myLesserC; + myC.member = 64; +@@ -34,7 +40,7 @@ int main(int argc, char const *argv[]) { + (void)C().argsAre_16_32(); + (void)(myC.member != 64); + D myD; +- D myLesserD; ++ D myLesserD; // breakpoint here + myD.member = 64; + (void)D().argsAre_Int_bool(); + (void)D().argsAre_Int_bool(); +diff --git a/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt b/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt +index f636e387b..c6e7e8cf4 100644 +--- a/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt ++++ b/src/llvm-project/lldb/tools/debugserver/source/CMakeLists.txt +@@ -95,7 +95,7 @@ check_c_source_compiles( + #else + #error Not building for ARM64 + #endif +- int main() { return 0; } ++ int main(void) { return 0; } + " + BUILDING_FOR_ARM64_OSX + ) +diff --git a/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp +index e78a084f5..4da17cf36 100644 +--- a/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp ++++ b/src/llvm-project/lldb/unittests/Symbol/TestTypeSystemClang.cpp +@@ -500,18 +500,24 @@ TEST_F(TestTypeSystemClang, TemplateArguments) { + for (CompilerType t : {type, typedef_type, auto_type}) { + SCOPED_TRACE(t.GetTypeName().AsCString()); + +- EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0), +- eTemplateArgumentKindType); +- EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0), +- int_type); +- EXPECT_EQ(llvm::None, +- m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 0)); +- +- EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1), +- eTemplateArgumentKindIntegral); +- EXPECT_EQ(m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1), +- CompilerType()); +- auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1); ++ const bool expand_pack = false; ++ EXPECT_EQ( ++ m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0, expand_pack), ++ eTemplateArgumentKindType); ++ EXPECT_EQ( ++ m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 0, expand_pack), ++ int_type); ++ EXPECT_EQ(llvm::None, m_ast->GetIntegralTemplateArgument( ++ t.GetOpaqueQualType(), 0, expand_pack)); ++ ++ EXPECT_EQ( ++ m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 1, expand_pack), ++ eTemplateArgumentKindIntegral); ++ EXPECT_EQ( ++ m_ast->GetTypeTemplateArgument(t.GetOpaqueQualType(), 1, expand_pack), ++ CompilerType()); ++ auto result = m_ast->GetIntegralTemplateArgument(t.GetOpaqueQualType(), 1, ++ expand_pack); + ASSERT_NE(llvm::None, result); + EXPECT_EQ(arg, result->value); + EXPECT_EQ(int_type, result->type); +diff --git a/src/llvm-project/llvm/CMakeLists.txt b/src/llvm-project/llvm/CMakeLists.txt +index 57eb01d6f..bae2cebaf 100644 +--- a/src/llvm-project/llvm/CMakeLists.txt ++++ b/src/llvm-project/llvm/CMakeLists.txt +@@ -22,7 +22,7 @@ if(NOT DEFINED LLVM_VERSION_MINOR) + set(LLVM_VERSION_MINOR 0) + endif() + if(NOT DEFINED LLVM_VERSION_PATCH) +- set(LLVM_VERSION_PATCH 2) ++ set(LLVM_VERSION_PATCH 7) + endif() + if(NOT DEFINED LLVM_VERSION_SUFFIX) + set(LLVM_VERSION_SUFFIX) +@@ -373,6 +373,7 @@ set(LLVM_ALL_TARGETS + BPF + Hexagon + Lanai ++ LoongArch + Mips + MSP430 + NVPTX +@@ -446,6 +447,8 @@ set(LLVM_ENABLE_ZLIB "ON" CACHE STRING "Use zlib for compression/decompression i + + set(LLVM_ENABLE_ZSTD "ON" CACHE STRING "Use zstd for compression/decompression if available. Can be ON, OFF, or FORCE_ON") + ++set(LLVM_USE_STATIC_ZSTD FALSE CACHE BOOL "Use static version of zstd. Can be TRUE, FALSE") ++ + set(LLVM_ENABLE_CURL "OFF" CACHE STRING "Use libcurl for the HTTP client if available. Can be ON, OFF, or FORCE_ON") + + set(LLVM_ENABLE_HTTPLIB "OFF" CACHE STRING "Use cpp-httplib HTTP server library if available. Can be ON, OFF, or FORCE_ON") +diff --git a/src/llvm-project/llvm/cmake/config-ix.cmake b/src/llvm-project/llvm/cmake/config-ix.cmake +index 83512760d..b4b9b748c 100644 +--- a/src/llvm-project/llvm/cmake/config-ix.cmake ++++ b/src/llvm-project/llvm/cmake/config-ix.cmake +@@ -71,7 +71,7 @@ if(APPLE) + CHECK_C_SOURCE_COMPILES(" + static const char *__crashreporter_info__ = 0; + asm(\".desc ___crashreporter_info__, 0x10\"); +- int main() { return 0; }" ++ int main(void) { return 0; }" + HAVE_CRASHREPORTER_INFO) + endif() + +@@ -498,6 +498,8 @@ elseif (LLVM_NATIVE_ARCH MATCHES "riscv64") + set(LLVM_NATIVE_ARCH RISCV) + elseif (LLVM_NATIVE_ARCH STREQUAL "m68k") + set(LLVM_NATIVE_ARCH M68k) ++elseif (LLVM_NATIVE_ARCH MATCHES "loongarch") ++ set(LLVM_NATIVE_ARCH LoongArch) + else () + message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") + endif () +diff --git a/src/llvm-project/llvm/cmake/config.guess b/src/llvm-project/llvm/cmake/config.guess +index 60d3f588d..255257d40 100644 +--- a/src/llvm-project/llvm/cmake/config.guess ++++ b/src/llvm-project/llvm/cmake/config.guess +@@ -1021,6 +1021,9 @@ EOF + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; ++ loongarch64:Linux:*:*) ++ echo loongarch64-unknown-linux-gnu ++ exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; +diff --git a/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake b/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake +index 057431208..1f0507f39 100644 +--- a/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake ++++ b/src/llvm-project/llvm/cmake/modules/AddLLVM.cmake +@@ -212,6 +212,7 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) + else() + if("${stdout}" MATCHES "^mold") + set(LLVM_LINKER_DETECTED YES CACHE INTERNAL "") ++ set(LLVM_LINKER_IS_MOLD YES CACHE INTERNAL "") + message(STATUS "Linker detection: mold") + elseif("${stdout}" MATCHES "GNU gold") + set(LLVM_LINKER_DETECTED YES CACHE INTERNAL "") +diff --git a/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake b/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake +index 3c5ba7299..f11cadf39 100644 +--- a/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake ++++ b/src/llvm-project/llvm/cmake/modules/CheckAtomic.cmake +@@ -82,6 +82,19 @@ elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL") + endif() + endif() + ++# Set variable LLVM_ATOMIC_LIB specifying flags for linking against libatomic. ++if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB) ++ # Use options --push-state, --as-needed and --pop-state if linker is known to support them. ++ # Use single option -Wl of compiler driver to avoid incorrect re-ordering of options by CMake. ++ if(LLVM_LINKER_IS_GNULD OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD OR LLVM_LINKER_IS_MOLD) ++ set(LLVM_ATOMIC_LIB "-Wl,--push-state,--as-needed,-latomic,--pop-state") ++ else() ++ set(LLVM_ATOMIC_LIB "-latomic") ++ endif() ++else() ++ set(LLVM_ATOMIC_LIB) ++endif() ++ + ## TODO: This define is only used for the legacy atomic operations in + ## llvm's Atomic.h, which should be replaced. Other code simply + ## assumes C++11 works. +diff --git a/src/llvm-project/llvm/cmake/modules/FindFFI.cmake b/src/llvm-project/llvm/cmake/modules/FindFFI.cmake +index b0d859af8..a493a89d6 100644 +--- a/src/llvm-project/llvm/cmake/modules/FindFFI.cmake ++++ b/src/llvm-project/llvm/cmake/modules/FindFFI.cmake +@@ -45,7 +45,7 @@ if(FFI_LIBRARIES) + struct ffi_cif; + typedef struct ffi_cif ffi_cif; + void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); +- int main() { ffi_call(0, 0, 0, 0); }" ++ int main(void) { ffi_call(0, 0, 0, 0); }" + HAVE_FFI_CALL) + cmake_pop_check_state() + endif() +diff --git a/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake b/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake +index 65edb80fa..eef1f9585 100644 +--- a/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake ++++ b/src/llvm-project/llvm/cmake/modules/FindTerminfo.cmake +@@ -20,7 +20,7 @@ if(Terminfo_LIBRARIES) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${Terminfo_LIBRARIES}) + check_c_source_compiles(" + int setupterm(char *term, int filedes, int *errret); +- int main() { return setupterm(0, 0, 0); }" ++ int main(void) { return setupterm(0, 0, 0); }" + Terminfo_LINKABLE) + cmake_pop_check_state() + endif() +diff --git a/src/llvm-project/llvm/cmake/modules/FindZ3.cmake b/src/llvm-project/llvm/cmake/modules/FindZ3.cmake +index 118b1eac3..6fb56d741 100644 +--- a/src/llvm-project/llvm/cmake/modules/FindZ3.cmake ++++ b/src/llvm-project/llvm/cmake/modules/FindZ3.cmake +@@ -18,8 +18,9 @@ function(check_z3_version z3_include z3_lib) + # The program that will be executed to print Z3's version. + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testz3.cpp + "#include ++ #include + #include +- int main() { ++ int main(void) { + unsigned int major, minor, build, rev; + Z3_get_version(&major, &minor, &build, &rev); + printf(\"%u.%u.%u\", major, minor, build); +diff --git a/src/llvm-project/llvm/cmake/modules/Findzstd.cmake b/src/llvm-project/llvm/cmake/modules/Findzstd.cmake +new file mode 100644 +index 000000000..fab9ea803 +--- /dev/null ++++ b/src/llvm-project/llvm/cmake/modules/Findzstd.cmake +@@ -0,0 +1,49 @@ ++# Try to find the zstd library ++# ++# If successful, the following variables will be defined: ++# zstd_INCLUDE_DIR ++# zstd_LIBRARY ++# zstd_FOUND ++# ++# Additionally, one of the following import targets will be defined: ++# zstd::libzstd_shared ++# zstd::libzstd_static ++ ++if(MSVC) ++ set(zstd_SHARED_LIBRARY_SUFFIX "\\${CMAKE_LINK_LIBRARY_SUFFIX}$") ++ set(zstd_STATIC_LIBRARY_SUFFIX "_static\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") ++else() ++ set(zstd_SHARED_LIBRARY_SUFFIX "\\${CMAKE_SHARED_LIBRARY_SUFFIX}$") ++ set(zstd_STATIC_LIBRARY_SUFFIX "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") ++endif() ++ ++find_path(zstd_INCLUDE_DIR NAMES zstd.h) ++find_library(zstd_LIBRARY NAMES zstd zstd_static) ++ ++include(FindPackageHandleStandardArgs) ++find_package_handle_standard_args( ++ zstd DEFAULT_MSG ++ zstd_LIBRARY zstd_INCLUDE_DIR ++) ++ ++if(zstd_FOUND) ++ if(zstd_LIBRARY MATCHES "${zstd_SHARED_LIBRARY_SUFFIX}$" AND ++ NOT TARGET zstd::libzstd_shared) ++ add_library(zstd::libzstd_shared SHARED IMPORTED) ++ set_target_properties(zstd::libzstd_shared PROPERTIES ++ INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" ++ IMPORTED_LOCATION "${zstd_LIBRARY}") ++ endif() ++ if(zstd_LIBRARY MATCHES "${zstd_STATIC_LIBRARY_SUFFIX}$" AND ++ NOT TARGET zstd::libzstd_static) ++ add_library(zstd::libzstd_static STATIC IMPORTED) ++ set_target_properties(zstd::libzstd_static PROPERTIES ++ INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" ++ IMPORTED_LOCATION "${zstd_LIBRARY}") ++ endif() ++endif() ++ ++unset(zstd_SHARED_LIBRARY_SUFFIX) ++unset(zstd_STATIC_LIBRARY_SUFFIX) ++ ++mark_as_advanced(zstd_INCLUDE_DIR zstd_LIBRARY) +diff --git a/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake b/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake +index 56d05f5b5..0fca934be 100644 +--- a/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake ++++ b/src/llvm-project/llvm/cmake/modules/HandleLLVMOptions.cmake +@@ -779,7 +779,7 @@ if (LLVM_ENABLE_WARNINGS AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL)) + # line is also a // comment. + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror -Wcomment") +- CHECK_C_SOURCE_COMPILES("// \\\\\\n//\\nint main() {return 0;}" ++ CHECK_C_SOURCE_COMPILES("// \\\\\\n//\\nint main(void) {return 0;}" + C_WCOMMENT_ALLOWS_LINE_WRAP) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + if (NOT C_WCOMMENT_ALLOWS_LINE_WRAP) +diff --git a/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in b/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in +index fbf28d36b..f1362fa03 100644 +--- a/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in ++++ b/src/llvm-project/llvm/cmake/modules/LLVMConfig.cmake.in +@@ -75,7 +75,6 @@ endif() + + set(LLVM_ENABLE_ZSTD @LLVM_ENABLE_ZSTD@) + if(LLVM_ENABLE_ZSTD) +- set(zstd_ROOT @zstd_ROOT@) + find_package(zstd) + endif() + +diff --git a/src/llvm-project/llvm/docs/ReleaseNotes.rst b/src/llvm-project/llvm/docs/ReleaseNotes.rst +index 9324d26cb..0660bc134 100644 +--- a/src/llvm-project/llvm/docs/ReleaseNotes.rst ++++ b/src/llvm-project/llvm/docs/ReleaseNotes.rst +@@ -227,6 +227,20 @@ Changes to the WebAssembly Backend + + * ... + ++Changes to the SystemZ Backend ++------------------------------ ++ ++* Support z16 processor name. ++* Machine scheduler description for z16. ++* Add support for inline assembly address operands ("p") as well as for SystemZ ++ specific address operands ("ZQ", "ZR", "ZS" and "ZT"). ++* Efficient handling of small memcpy/memset operations up to 32 bytes. ++* Tuning of the inliner. ++* Fixing emission of library calls so that narrow integer arguments are sign or ++ zero extended per the SystemZ ABI. ++* Support added for libunwind. ++* Various minor improvements and bugfixes. ++ + Changes to the X86 Backend + -------------------------- + +diff --git a/src/llvm-project/llvm/include/llvm/ADT/Triple.h b/src/llvm-project/llvm/include/llvm/ADT/Triple.h +index ba4584dc6..dbd0aeaab 100644 +--- a/src/llvm-project/llvm/include/llvm/ADT/Triple.h ++++ b/src/llvm-project/llvm/include/llvm/ADT/Triple.h +@@ -232,6 +232,7 @@ public: + GNUX32, + GNUILP32, + CODE16, ++ GNUABILPX32, + EABI, + EABIHF, + Android, +@@ -823,6 +824,16 @@ public: + : PointerWidth == 64; + } + ++ /// Tests whether the target is LoongArch 32-bit ++ bool isLoongArch32() const { ++ return getArch() == Triple::loongarch32; ++ } ++ ++ /// Tests whether the target is LoongArch 64-bit. ++ bool isLoongArch64() const { ++ return getArch() == Triple::loongarch64; ++ } ++ + /// Tests whether the target is LoongArch (32- and 64-bit). + bool isLoongArch() const { + return getArch() == Triple::loongarch32 || getArch() == Triple::loongarch64; +diff --git a/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h b/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h +index 99e7a9868..43f09b493 100644 +--- a/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h ++++ b/src/llvm-project/llvm/include/llvm/BinaryFormat/ELF.h +@@ -902,22 +902,13 @@ enum { + + // LoongArch Specific e_flags + enum : unsigned { +- // Reference: https://github.com/loongson/LoongArch-Documentation. +- // The last commit hash (main branch) is +- // 99016636af64d02dee05e39974d4c1e55875c45b. +- // Note that there is an open PR +- // https://github.com/loongson/LoongArch-Documentation/pull/47 +- // talking about using 0x1, 0x2, 0x3 for ILP32S/F/D and use EI_CLASS to +- // distinguish LP64 and ILP32. If this PR get merged, we will update +- // the definition here. +- // Base ABI Types. +- EF_LOONGARCH_BASE_ABI_LP64S = 0x1, // LP64 soft-float ABI +- EF_LOONGARCH_BASE_ABI_LP64F = 0x2, // LP64 single-float ABI +- EF_LOONGARCH_BASE_ABI_LP64D = 0x3, // LP64 double-float ABI +- EF_LOONGARCH_BASE_ABI_ILP32S = 0x5, // ILP32 soft-float ABI +- EF_LOONGARCH_BASE_ABI_ILP32F = 0x6, // ILP32 single-float ABI +- EF_LOONGARCH_BASE_ABI_ILP32D = 0x7, // ILP32 double-float ABI +- EF_LOONGARCH_BASE_ABI_MASK = 0x7, // Mask for selecting base ABI ++ // FIXME: Change these when all ABIs definition were finalized. ++ // See current definitions: ++ // https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version ++ EF_LARCH_ABI = 0x0003, ++ EF_LARCH_ABI_LP32 = 0x0001, ++ EF_LARCH_ABI_LPX32 = 0x0002, ++ EF_LARCH_ABI_LP64 = 0x0003, + }; + + // ELF Relocation types for LoongArch +diff --git a/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt b/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt +index 5151f9125..468d66379 100644 +--- a/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt ++++ b/src/llvm-project/llvm/include/llvm/IR/CMakeLists.txt +@@ -10,6 +10,7 @@ tablegen(LLVM IntrinsicsARM.h -gen-intrinsic-enums -intrinsic-prefix=arm) + tablegen(LLVM IntrinsicsBPF.h -gen-intrinsic-enums -intrinsic-prefix=bpf) + tablegen(LLVM IntrinsicsDirectX.h -gen-intrinsic-enums -intrinsic-prefix=dx) + tablegen(LLVM IntrinsicsHexagon.h -gen-intrinsic-enums -intrinsic-prefix=hexagon) ++tablegen(LLVM IntrinsicsLoongArch.h -gen-intrinsic-enums -intrinsic-prefix=loongarch) + tablegen(LLVM IntrinsicsMips.h -gen-intrinsic-enums -intrinsic-prefix=mips) + tablegen(LLVM IntrinsicsNVPTX.h -gen-intrinsic-enums -intrinsic-prefix=nvvm) + tablegen(LLVM IntrinsicsPowerPC.h -gen-intrinsic-enums -intrinsic-prefix=ppc) +diff --git a/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h b/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h +index 0a8d27aad..3f78eb41f 100644 +--- a/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h ++++ b/src/llvm-project/llvm/include/llvm/IR/InlineAsm.h +@@ -269,6 +269,7 @@ public: + Constraint_Uy, + Constraint_X, + Constraint_Z, ++ Constraint_ZB, + Constraint_ZC, + Constraint_Zy, + +diff --git a/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td b/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td +index d46fa4fbf..76f2d66b7 100644 +--- a/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td ++++ b/src/llvm-project/llvm/include/llvm/IR/Intrinsics.td +@@ -2053,3 +2053,4 @@ include "llvm/IR/IntrinsicsRISCV.td" + include "llvm/IR/IntrinsicsSPIRV.td" + include "llvm/IR/IntrinsicsVE.td" + include "llvm/IR/IntrinsicsDirectX.td" ++include "llvm/IR/IntrinsicsLoongArch.td" +diff --git a/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td b/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td +new file mode 100644 +index 000000000..1cbf1d300 +--- /dev/null ++++ b/src/llvm-project/llvm/include/llvm/IR/IntrinsicsLoongArch.td +@@ -0,0 +1,3657 @@ ++//===- IntrinsicsLoongArch.td - Defines LoongArch intrinsics ---------*- tablegen -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file defines all of the LoongArch-specific intrinsics. ++// ++//===----------------------------------------------------------------------===// ++ ++let TargetPrefix = "loongarch" in { // All intrinsics start with "llvm.loongarch.". ++ ++//===----------------------------------------------------------------------===// ++// LoongArch LSX ++ ++def int_loongarch_lsx_vclo_b : ClangBuiltin<"__builtin_lsx_vclo_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclo_h : ClangBuiltin<"__builtin_lsx_vclo_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclo_w : ClangBuiltin<"__builtin_lsx_vclo_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclo_d : ClangBuiltin<"__builtin_lsx_vclo_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vflogb_s : ClangBuiltin<"__builtin_lsx_vflogb_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vflogb_d : ClangBuiltin<"__builtin_lsx_vflogb_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpickve2gr_b : ClangBuiltin<"__builtin_lsx_vpickve2gr_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_h : ClangBuiltin<"__builtin_lsx_vpickve2gr_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_w : ClangBuiltin<"__builtin_lsx_vpickve2gr_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_d : ClangBuiltin<"__builtin_lsx_vpickve2gr_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpickve2gr_bu : ClangBuiltin<"__builtin_lsx_vpickve2gr_bu">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_hu : ClangBuiltin<"__builtin_lsx_vpickve2gr_hu">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_wu : ClangBuiltin<"__builtin_lsx_vpickve2gr_wu">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickve2gr_du : ClangBuiltin<"__builtin_lsx_vpickve2gr_du">, ++ Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vreplvei_b : ClangBuiltin<"__builtin_lsx_vreplvei_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplvei_h : ClangBuiltin<"__builtin_lsx_vreplvei_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplvei_w : ClangBuiltin<"__builtin_lsx_vreplvei_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplvei_d : ClangBuiltin<"__builtin_lsx_vreplvei_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmskltz_b : ClangBuiltin<"__builtin_lsx_vmskltz_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmskltz_h : ClangBuiltin<"__builtin_lsx_vmskltz_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmskltz_w : ClangBuiltin<"__builtin_lsx_vmskltz_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmskltz_d : ClangBuiltin<"__builtin_lsx_vmskltz_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmadd_s : ClangBuiltin<"__builtin_lsx_vfmadd_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmadd_d : ClangBuiltin<"__builtin_lsx_vfmadd_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmsub_s : ClangBuiltin<"__builtin_lsx_vfmsub_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmsub_d : ClangBuiltin<"__builtin_lsx_vfmsub_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfnmadd_s : ClangBuiltin<"__builtin_lsx_vfnmadd_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfnmadd_d : ClangBuiltin<"__builtin_lsx_vfnmadd_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfnmsub_s : ClangBuiltin<"__builtin_lsx_vfnmsub_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfnmsub_d : ClangBuiltin<"__builtin_lsx_vfnmsub_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_caf_s : ClangBuiltin<"__builtin_lsx_vfcmp_caf_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_caf_d : ClangBuiltin<"__builtin_lsx_vfcmp_caf_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cor_s : ClangBuiltin<"__builtin_lsx_vfcmp_cor_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cor_d : ClangBuiltin<"__builtin_lsx_vfcmp_cor_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cun_s : ClangBuiltin<"__builtin_lsx_vfcmp_cun_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cun_d : ClangBuiltin<"__builtin_lsx_vfcmp_cun_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cune_s : ClangBuiltin<"__builtin_lsx_vfcmp_cune_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cune_d : ClangBuiltin<"__builtin_lsx_vfcmp_cune_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cueq_s : ClangBuiltin<"__builtin_lsx_vfcmp_cueq_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cueq_d : ClangBuiltin<"__builtin_lsx_vfcmp_cueq_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_ceq_s : ClangBuiltin<"__builtin_lsx_vfcmp_ceq_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_ceq_d : ClangBuiltin<"__builtin_lsx_vfcmp_ceq_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cne_s : ClangBuiltin<"__builtin_lsx_vfcmp_cne_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cne_d : ClangBuiltin<"__builtin_lsx_vfcmp_cne_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_clt_s : ClangBuiltin<"__builtin_lsx_vfcmp_clt_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_clt_d : ClangBuiltin<"__builtin_lsx_vfcmp_clt_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cult_s : ClangBuiltin<"__builtin_lsx_vfcmp_cult_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cult_d : ClangBuiltin<"__builtin_lsx_vfcmp_cult_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cle_s : ClangBuiltin<"__builtin_lsx_vfcmp_cle_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cle_d : ClangBuiltin<"__builtin_lsx_vfcmp_cle_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_cule_s : ClangBuiltin<"__builtin_lsx_vfcmp_cule_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_cule_d : ClangBuiltin<"__builtin_lsx_vfcmp_cule_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_saf_s : ClangBuiltin<"__builtin_lsx_vfcmp_saf_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_saf_d : ClangBuiltin<"__builtin_lsx_vfcmp_saf_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sor_s : ClangBuiltin<"__builtin_lsx_vfcmp_sor_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sor_d : ClangBuiltin<"__builtin_lsx_vfcmp_sor_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sun_s : ClangBuiltin<"__builtin_lsx_vfcmp_sun_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sun_d : ClangBuiltin<"__builtin_lsx_vfcmp_sun_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sune_s : ClangBuiltin<"__builtin_lsx_vfcmp_sune_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sune_d : ClangBuiltin<"__builtin_lsx_vfcmp_sune_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sueq_s : ClangBuiltin<"__builtin_lsx_vfcmp_sueq_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sueq_d : ClangBuiltin<"__builtin_lsx_vfcmp_sueq_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_seq_s : ClangBuiltin<"__builtin_lsx_vfcmp_seq_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_seq_d : ClangBuiltin<"__builtin_lsx_vfcmp_seq_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sne_s : ClangBuiltin<"__builtin_lsx_vfcmp_sne_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sne_d : ClangBuiltin<"__builtin_lsx_vfcmp_sne_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_slt_s : ClangBuiltin<"__builtin_lsx_vfcmp_slt_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_slt_d : ClangBuiltin<"__builtin_lsx_vfcmp_slt_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sult_s : ClangBuiltin<"__builtin_lsx_vfcmp_sult_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sult_d : ClangBuiltin<"__builtin_lsx_vfcmp_sult_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sle_s : ClangBuiltin<"__builtin_lsx_vfcmp_sle_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sle_d : ClangBuiltin<"__builtin_lsx_vfcmp_sle_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcmp_sule_s : ClangBuiltin<"__builtin_lsx_vfcmp_sule_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcmp_sule_d : ClangBuiltin<"__builtin_lsx_vfcmp_sule_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitsel_v : ClangBuiltin<"__builtin_lsx_vbitsel_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vshuf_b : ClangBuiltin<"__builtin_lsx_vshuf_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vldrepl_b : ClangBuiltin<"__builtin_lsx_vldrepl_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lsx_vldrepl_h : ClangBuiltin<"__builtin_lsx_vldrepl_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lsx_vldrepl_w : ClangBuiltin<"__builtin_lsx_vldrepl_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lsx_vldrepl_d : ClangBuiltin<"__builtin_lsx_vldrepl_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_vstelm_b : ClangBuiltin<"__builtin_lsx_vstelm_b">, ++ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lsx_vstelm_h : ClangBuiltin<"__builtin_lsx_vstelm_h">, ++ Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lsx_vstelm_w : ClangBuiltin<"__builtin_lsx_vstelm_w">, ++ Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lsx_vstelm_d : ClangBuiltin<"__builtin_lsx_vstelm_d">, ++ Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_vldx : ClangBuiltin<"__builtin_lsx_vldx">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i64_ty], ++ [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_vstx : ClangBuiltin<"__builtin_lsx_vstx">, ++ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i64_ty], ++ [IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_vaddwev_d_w : ClangBuiltin<"__builtin_lsx_vaddwev_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_w_h : ClangBuiltin<"__builtin_lsx_vaddwev_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_h_b : ClangBuiltin<"__builtin_lsx_vaddwev_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_q_d : ClangBuiltin<"__builtin_lsx_vaddwev_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsubwev_d_w : ClangBuiltin<"__builtin_lsx_vsubwev_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_w_h : ClangBuiltin<"__builtin_lsx_vsubwev_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_h_b : ClangBuiltin<"__builtin_lsx_vsubwev_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_q_d : ClangBuiltin<"__builtin_lsx_vsubwev_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++ ++def int_loongarch_lsx_vaddwod_d_w : ClangBuiltin<"__builtin_lsx_vaddwod_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_w_h : ClangBuiltin<"__builtin_lsx_vaddwod_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_h_b : ClangBuiltin<"__builtin_lsx_vaddwod_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_q_d : ClangBuiltin<"__builtin_lsx_vaddwod_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsubwod_d_w : ClangBuiltin<"__builtin_lsx_vsubwod_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_w_h : ClangBuiltin<"__builtin_lsx_vsubwod_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_h_b : ClangBuiltin<"__builtin_lsx_vsubwod_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_q_d : ClangBuiltin<"__builtin_lsx_vsubwod_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vaddwev_d_wu : ClangBuiltin<"__builtin_lsx_vaddwev_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_w_hu : ClangBuiltin<"__builtin_lsx_vaddwev_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_h_bu : ClangBuiltin<"__builtin_lsx_vaddwev_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_q_du : ClangBuiltin<"__builtin_lsx_vaddwev_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsubwev_d_wu : ClangBuiltin<"__builtin_lsx_vsubwev_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_w_hu : ClangBuiltin<"__builtin_lsx_vsubwev_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_h_bu : ClangBuiltin<"__builtin_lsx_vsubwev_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwev_q_du : ClangBuiltin<"__builtin_lsx_vsubwev_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vaddwod_d_wu : ClangBuiltin<"__builtin_lsx_vaddwod_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_w_hu : ClangBuiltin<"__builtin_lsx_vaddwod_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_h_bu : ClangBuiltin<"__builtin_lsx_vaddwod_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_q_du : ClangBuiltin<"__builtin_lsx_vaddwod_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsubwod_d_wu : ClangBuiltin<"__builtin_lsx_vsubwod_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_w_hu : ClangBuiltin<"__builtin_lsx_vsubwod_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_h_bu : ClangBuiltin<"__builtin_lsx_vsubwod_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubwod_q_du : ClangBuiltin<"__builtin_lsx_vsubwod_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vaddwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vaddwev_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vaddwev_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vaddwev_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwev_q_du_d : ClangBuiltin<"__builtin_lsx_vaddwev_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vaddwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vaddwod_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vaddwod_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vaddwod_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vaddwod_q_du_d : ClangBuiltin<"__builtin_lsx_vaddwod_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhaddw_qu_du : ClangBuiltin<"__builtin_lsx_vhaddw_qu_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_qu_du : ClangBuiltin<"__builtin_lsx_vhsubw_qu_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhaddw_q_d : ClangBuiltin<"__builtin_lsx_vhaddw_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_q_d : ClangBuiltin<"__builtin_lsx_vhsubw_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmuh_b : ClangBuiltin<"__builtin_lsx_vmuh_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_h : ClangBuiltin<"__builtin_lsx_vmuh_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_w : ClangBuiltin<"__builtin_lsx_vmuh_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_d : ClangBuiltin<"__builtin_lsx_vmuh_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmuh_bu : ClangBuiltin<"__builtin_lsx_vmuh_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_hu : ClangBuiltin<"__builtin_lsx_vmuh_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_wu : ClangBuiltin<"__builtin_lsx_vmuh_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmuh_du : ClangBuiltin<"__builtin_lsx_vmuh_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwev_d_w : ClangBuiltin<"__builtin_lsx_vmulwev_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_w_h : ClangBuiltin<"__builtin_lsx_vmulwev_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_h_b : ClangBuiltin<"__builtin_lsx_vmulwev_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_q_d : ClangBuiltin<"__builtin_lsx_vmulwev_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwod_d_w : ClangBuiltin<"__builtin_lsx_vmulwod_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_w_h : ClangBuiltin<"__builtin_lsx_vmulwod_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_h_b : ClangBuiltin<"__builtin_lsx_vmulwod_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_q_d : ClangBuiltin<"__builtin_lsx_vmulwod_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwev_d_wu : ClangBuiltin<"__builtin_lsx_vmulwev_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_w_hu : ClangBuiltin<"__builtin_lsx_vmulwev_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_h_bu : ClangBuiltin<"__builtin_lsx_vmulwev_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_q_du : ClangBuiltin<"__builtin_lsx_vmulwev_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwod_d_wu : ClangBuiltin<"__builtin_lsx_vmulwod_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_w_hu : ClangBuiltin<"__builtin_lsx_vmulwod_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_h_bu : ClangBuiltin<"__builtin_lsx_vmulwod_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_q_du : ClangBuiltin<"__builtin_lsx_vmulwod_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vmulwev_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vmulwev_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vmulwev_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwev_q_du_d : ClangBuiltin<"__builtin_lsx_vmulwev_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmulwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vmulwod_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vmulwod_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vmulwod_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmulwod_q_du_d : ClangBuiltin<"__builtin_lsx_vmulwod_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwev_d_w : ClangBuiltin<"__builtin_lsx_vmaddwev_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_w_h : ClangBuiltin<"__builtin_lsx_vmaddwev_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_h_b : ClangBuiltin<"__builtin_lsx_vmaddwev_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_q_d : ClangBuiltin<"__builtin_lsx_vmaddwev_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwod_d_w : ClangBuiltin<"__builtin_lsx_vmaddwod_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_w_h : ClangBuiltin<"__builtin_lsx_vmaddwod_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_h_b : ClangBuiltin<"__builtin_lsx_vmaddwod_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_q_d : ClangBuiltin<"__builtin_lsx_vmaddwod_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwev_d_wu : ClangBuiltin<"__builtin_lsx_vmaddwev_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_w_hu : ClangBuiltin<"__builtin_lsx_vmaddwev_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_h_bu : ClangBuiltin<"__builtin_lsx_vmaddwev_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_q_du : ClangBuiltin<"__builtin_lsx_vmaddwev_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwod_d_wu : ClangBuiltin<"__builtin_lsx_vmaddwod_d_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_w_hu : ClangBuiltin<"__builtin_lsx_vmaddwod_w_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_h_bu : ClangBuiltin<"__builtin_lsx_vmaddwod_h_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_q_du : ClangBuiltin<"__builtin_lsx_vmaddwod_q_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwev_d_wu_w : ClangBuiltin<"__builtin_lsx_vmaddwev_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_w_hu_h : ClangBuiltin<"__builtin_lsx_vmaddwev_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_h_bu_b : ClangBuiltin<"__builtin_lsx_vmaddwev_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwev_q_du_d : ClangBuiltin<"__builtin_lsx_vmaddwev_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaddwod_d_wu_w : ClangBuiltin<"__builtin_lsx_vmaddwod_d_wu_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_w_hu_h : ClangBuiltin<"__builtin_lsx_vmaddwod_w_hu_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_h_bu_b : ClangBuiltin<"__builtin_lsx_vmaddwod_h_bu_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaddwod_q_du_d : ClangBuiltin<"__builtin_lsx_vmaddwod_q_du_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrln_b_h : ClangBuiltin<"__builtin_lsx_vsrln_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrln_h_w : ClangBuiltin<"__builtin_lsx_vsrln_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrln_w_d : ClangBuiltin<"__builtin_lsx_vsrln_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsran_b_h : ClangBuiltin<"__builtin_lsx_vsran_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsran_h_w : ClangBuiltin<"__builtin_lsx_vsran_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsran_w_d : ClangBuiltin<"__builtin_lsx_vsran_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrlrn_b_h : ClangBuiltin<"__builtin_lsx_vsrlrn_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlrn_h_w : ClangBuiltin<"__builtin_lsx_vsrlrn_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlrn_w_d : ClangBuiltin<"__builtin_lsx_vsrlrn_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrarn_b_h : ClangBuiltin<"__builtin_lsx_vsrarn_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrarn_h_w : ClangBuiltin<"__builtin_lsx_vsrarn_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrarn_w_d : ClangBuiltin<"__builtin_lsx_vsrarn_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrln_b_h : ClangBuiltin<"__builtin_lsx_vssrln_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrln_h_w : ClangBuiltin<"__builtin_lsx_vssrln_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrln_w_d : ClangBuiltin<"__builtin_lsx_vssrln_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssran_b_h : ClangBuiltin<"__builtin_lsx_vssran_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssran_h_w : ClangBuiltin<"__builtin_lsx_vssran_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssran_w_d : ClangBuiltin<"__builtin_lsx_vssran_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlrn_b_h : ClangBuiltin<"__builtin_lsx_vssrlrn_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrn_h_w : ClangBuiltin<"__builtin_lsx_vssrlrn_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrn_w_d : ClangBuiltin<"__builtin_lsx_vssrlrn_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrarn_b_h : ClangBuiltin<"__builtin_lsx_vssrarn_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarn_h_w : ClangBuiltin<"__builtin_lsx_vssrarn_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarn_w_d : ClangBuiltin<"__builtin_lsx_vssrarn_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrln_bu_h : ClangBuiltin<"__builtin_lsx_vssrln_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrln_hu_w : ClangBuiltin<"__builtin_lsx_vssrln_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrln_wu_d : ClangBuiltin<"__builtin_lsx_vssrln_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssran_bu_h : ClangBuiltin<"__builtin_lsx_vssran_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssran_hu_w : ClangBuiltin<"__builtin_lsx_vssran_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssran_wu_d : ClangBuiltin<"__builtin_lsx_vssran_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlrn_bu_h : ClangBuiltin<"__builtin_lsx_vssrlrn_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrn_hu_w : ClangBuiltin<"__builtin_lsx_vssrlrn_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrn_wu_d : ClangBuiltin<"__builtin_lsx_vssrlrn_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrarn_bu_h : ClangBuiltin<"__builtin_lsx_vssrarn_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarn_hu_w : ClangBuiltin<"__builtin_lsx_vssrarn_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarn_wu_d : ClangBuiltin<"__builtin_lsx_vssrarn_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vandn_v : ClangBuiltin<"__builtin_lsx_vandn_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vorn_v : ClangBuiltin<"__builtin_lsx_vorn_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrstp_b : ClangBuiltin<"__builtin_lsx_vfrstp_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vfrstp_h : ClangBuiltin<"__builtin_lsx_vfrstp_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vadd_q : ClangBuiltin<"__builtin_lsx_vadd_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsub_q : ClangBuiltin<"__builtin_lsx_vsub_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsigncov_b : ClangBuiltin<"__builtin_lsx_vsigncov_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vsigncov_h : ClangBuiltin<"__builtin_lsx_vsigncov_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vsigncov_w : ClangBuiltin<"__builtin_lsx_vsigncov_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vsigncov_d : ClangBuiltin<"__builtin_lsx_vsigncov_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcvt_h_s : ClangBuiltin<"__builtin_lsx_vfcvt_h_s">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcvt_s_d : ClangBuiltin<"__builtin_lsx_vfcvt_s_d">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vffint_s_l : ClangBuiltin<"__builtin_lsx_vffint_s_l">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftint_w_d : ClangBuiltin<"__builtin_lsx_vftint_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrz_w_d : ClangBuiltin<"__builtin_lsx_vftintrz_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrp_w_d : ClangBuiltin<"__builtin_lsx_vftintrp_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrm_w_d : ClangBuiltin<"__builtin_lsx_vftintrm_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrne_w_d : ClangBuiltin<"__builtin_lsx_vftintrne_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbsrl_v : ClangBuiltin<"__builtin_lsx_vbsrl_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbsll_v : ClangBuiltin<"__builtin_lsx_vbsll_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrstpi_b : ClangBuiltin<"__builtin_lsx_vfrstpi_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrstpi_h : ClangBuiltin<"__builtin_lsx_vfrstpi_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vneg_b : ClangBuiltin<"__builtin_lsx_vneg_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vneg_h : ClangBuiltin<"__builtin_lsx_vneg_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vneg_w : ClangBuiltin<"__builtin_lsx_vneg_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vneg_d : ClangBuiltin<"__builtin_lsx_vneg_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmskgez_b : ClangBuiltin<"__builtin_lsx_vmskgez_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmsknz_b : ClangBuiltin<"__builtin_lsx_vmsknz_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrintrm_s : ClangBuiltin<"__builtin_lsx_vfrintrm_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrintrm_d : ClangBuiltin<"__builtin_lsx_vfrintrm_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrintrp_s : ClangBuiltin<"__builtin_lsx_vfrintrp_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrintrp_d : ClangBuiltin<"__builtin_lsx_vfrintrp_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrintrz_s : ClangBuiltin<"__builtin_lsx_vfrintrz_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrintrz_d : ClangBuiltin<"__builtin_lsx_vfrintrz_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrintrne_s : ClangBuiltin<"__builtin_lsx_vfrintrne_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrintrne_d : ClangBuiltin<"__builtin_lsx_vfrintrne_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vffinth_d_w : ClangBuiltin<"__builtin_lsx_vffinth_d_w">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vffintl_d_w : ClangBuiltin<"__builtin_lsx_vffintl_d_w">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrm_w_s : ClangBuiltin<"__builtin_lsx_vftintrm_w_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrm_l_d : ClangBuiltin<"__builtin_lsx_vftintrm_l_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrp_w_s : ClangBuiltin<"__builtin_lsx_vftintrp_w_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrp_l_d : ClangBuiltin<"__builtin_lsx_vftintrp_l_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrz_w_s : ClangBuiltin<"__builtin_lsx_vftintrz_w_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrz_l_d : ClangBuiltin<"__builtin_lsx_vftintrz_l_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrne_w_s : ClangBuiltin<"__builtin_lsx_vftintrne_w_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrne_l_d : ClangBuiltin<"__builtin_lsx_vftintrne_l_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftinth_l_s : ClangBuiltin<"__builtin_lsx_vftinth_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintl_l_s : ClangBuiltin<"__builtin_lsx_vftintl_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrmh_l_s : ClangBuiltin<"__builtin_lsx_vftintrmh_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrml_l_s : ClangBuiltin<"__builtin_lsx_vftintrml_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrph_l_s : ClangBuiltin<"__builtin_lsx_vftintrph_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrpl_l_s : ClangBuiltin<"__builtin_lsx_vftintrpl_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrzh_l_s : ClangBuiltin<"__builtin_lsx_vftintrzh_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrzl_l_s : ClangBuiltin<"__builtin_lsx_vftintrzl_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrneh_l_s : ClangBuiltin<"__builtin_lsx_vftintrneh_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrnel_l_s : ClangBuiltin<"__builtin_lsx_vftintrnel_l_s">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vexth_d_w : ClangBuiltin<"__builtin_lsx_vexth_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_w_h : ClangBuiltin<"__builtin_lsx_vexth_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_h_b : ClangBuiltin<"__builtin_lsx_vexth_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_q_d : ClangBuiltin<"__builtin_lsx_vexth_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vexth_du_wu : ClangBuiltin<"__builtin_lsx_vexth_du_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_wu_hu : ClangBuiltin<"__builtin_lsx_vexth_wu_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_hu_bu : ClangBuiltin<"__builtin_lsx_vexth_hu_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vexth_qu_du : ClangBuiltin<"__builtin_lsx_vexth_qu_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvexth_du_wu : ClangBuiltin<"__builtin_lasx_xvexth_du_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_wu_hu : ClangBuiltin<"__builtin_lasx_xvexth_wu_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_hu_bu : ClangBuiltin<"__builtin_lasx_xvexth_hu_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_qu_du : ClangBuiltin<"__builtin_lasx_xvexth_qu_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsllwil_d_w : ClangBuiltin<"__builtin_lsx_vsllwil_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsllwil_w_h : ClangBuiltin<"__builtin_lsx_vsllwil_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsllwil_h_b : ClangBuiltin<"__builtin_lsx_vsllwil_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vextl_q_d : ClangBuiltin<"__builtin_lsx_vextl_q_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsllwil_du_wu : ClangBuiltin<"__builtin_lsx_vsllwil_du_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsllwil_wu_hu : ClangBuiltin<"__builtin_lsx_vsllwil_wu_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsllwil_hu_bu : ClangBuiltin<"__builtin_lsx_vsllwil_hu_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vextl_qu_du : ClangBuiltin<"__builtin_lsx_vextl_qu_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitclri_b : ClangBuiltin<"__builtin_lsx_vbitclri_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclri_h : ClangBuiltin<"__builtin_lsx_vbitclri_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclri_w : ClangBuiltin<"__builtin_lsx_vbitclri_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclri_d : ClangBuiltin<"__builtin_lsx_vbitclri_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitseti_b : ClangBuiltin<"__builtin_lsx_vbitseti_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitseti_h : ClangBuiltin<"__builtin_lsx_vbitseti_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitseti_w : ClangBuiltin<"__builtin_lsx_vbitseti_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitseti_d : ClangBuiltin<"__builtin_lsx_vbitseti_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitrevi_b : ClangBuiltin<"__builtin_lsx_vbitrevi_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrevi_h : ClangBuiltin<"__builtin_lsx_vbitrevi_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrevi_w : ClangBuiltin<"__builtin_lsx_vbitrevi_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrevi_d : ClangBuiltin<"__builtin_lsx_vbitrevi_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlrni_b_h : ClangBuiltin<"__builtin_lsx_vssrlrni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_h_w : ClangBuiltin<"__builtin_lsx_vssrlrni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_w_d : ClangBuiltin<"__builtin_lsx_vssrlrni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_d_q : ClangBuiltin<"__builtin_lsx_vssrlrni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrani_b_h : ClangBuiltin<"__builtin_lsx_vsrani_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrani_h_w : ClangBuiltin<"__builtin_lsx_vsrani_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrani_w_d : ClangBuiltin<"__builtin_lsx_vsrani_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrani_d_q : ClangBuiltin<"__builtin_lsx_vsrani_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vextrins_b : ClangBuiltin<"__builtin_lsx_vextrins_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vextrins_h : ClangBuiltin<"__builtin_lsx_vextrins_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vextrins_w : ClangBuiltin<"__builtin_lsx_vextrins_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vextrins_d : ClangBuiltin<"__builtin_lsx_vextrins_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitseli_b : ClangBuiltin<"__builtin_lsx_vbitseli_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vandi_b : ClangBuiltin<"__builtin_lsx_vandi_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vori_b : ClangBuiltin<"__builtin_lsx_vori_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vxori_b : ClangBuiltin<"__builtin_lsx_vxori_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vnori_b : ClangBuiltin<"__builtin_lsx_vnori_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vldi : ClangBuiltin<"__builtin_lsx_vldi">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrepli_b : ClangBuiltin<"__builtin_lsx_vrepli_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrepli_h : ClangBuiltin<"__builtin_lsx_vrepli_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrepli_w : ClangBuiltin<"__builtin_lsx_vrepli_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrepli_d : ClangBuiltin<"__builtin_lsx_vrepli_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpermi_w : ClangBuiltin<"__builtin_lsx_vpermi_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsadd_b : ClangBuiltin<"__builtin_lsx_vsadd_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_h : ClangBuiltin<"__builtin_lsx_vsadd_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_w : ClangBuiltin<"__builtin_lsx_vsadd_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_d : ClangBuiltin<"__builtin_lsx_vsadd_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vssub_b : ClangBuiltin<"__builtin_lsx_vssub_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_h : ClangBuiltin<"__builtin_lsx_vssub_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_w : ClangBuiltin<"__builtin_lsx_vssub_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_d : ClangBuiltin<"__builtin_lsx_vssub_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsadd_bu : ClangBuiltin<"__builtin_lsx_vsadd_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_hu : ClangBuiltin<"__builtin_lsx_vsadd_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_wu : ClangBuiltin<"__builtin_lsx_vsadd_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vsadd_du : ClangBuiltin<"__builtin_lsx_vsadd_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vssub_bu : ClangBuiltin<"__builtin_lsx_vssub_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_hu : ClangBuiltin<"__builtin_lsx_vssub_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_wu : ClangBuiltin<"__builtin_lsx_vssub_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssub_du : ClangBuiltin<"__builtin_lsx_vssub_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhaddw_h_b : ClangBuiltin<"__builtin_lsx_vhaddw_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhaddw_w_h : ClangBuiltin<"__builtin_lsx_vhaddw_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhaddw_d_w : ClangBuiltin<"__builtin_lsx_vhaddw_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhsubw_h_b : ClangBuiltin<"__builtin_lsx_vhsubw_h_b">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_w_h : ClangBuiltin<"__builtin_lsx_vhsubw_w_h">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_d_w : ClangBuiltin<"__builtin_lsx_vhsubw_d_w">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhaddw_hu_bu : ClangBuiltin<"__builtin_lsx_vhaddw_hu_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhaddw_wu_hu : ClangBuiltin<"__builtin_lsx_vhaddw_wu_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhaddw_du_wu : ClangBuiltin<"__builtin_lsx_vhaddw_du_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vhsubw_hu_bu : ClangBuiltin<"__builtin_lsx_vhsubw_hu_bu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_wu_hu : ClangBuiltin<"__builtin_lsx_vhsubw_wu_hu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vhsubw_du_wu : ClangBuiltin<"__builtin_lsx_vhsubw_du_wu">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vadda_b : ClangBuiltin<"__builtin_lsx_vadda_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadda_h : ClangBuiltin<"__builtin_lsx_vadda_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadda_w : ClangBuiltin<"__builtin_lsx_vadda_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadda_d : ClangBuiltin<"__builtin_lsx_vadda_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vabsd_b : ClangBuiltin<"__builtin_lsx_vabsd_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_h : ClangBuiltin<"__builtin_lsx_vabsd_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_w : ClangBuiltin<"__builtin_lsx_vabsd_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_d : ClangBuiltin<"__builtin_lsx_vabsd_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vabsd_bu : ClangBuiltin<"__builtin_lsx_vabsd_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_hu : ClangBuiltin<"__builtin_lsx_vabsd_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_wu : ClangBuiltin<"__builtin_lsx_vabsd_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vabsd_du : ClangBuiltin<"__builtin_lsx_vabsd_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vavg_b : ClangBuiltin<"__builtin_lsx_vavg_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_h : ClangBuiltin<"__builtin_lsx_vavg_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_w : ClangBuiltin<"__builtin_lsx_vavg_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_d : ClangBuiltin<"__builtin_lsx_vavg_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vavg_bu : ClangBuiltin<"__builtin_lsx_vavg_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_hu : ClangBuiltin<"__builtin_lsx_vavg_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_wu : ClangBuiltin<"__builtin_lsx_vavg_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavg_du : ClangBuiltin<"__builtin_lsx_vavg_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vavgr_b : ClangBuiltin<"__builtin_lsx_vavgr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_h : ClangBuiltin<"__builtin_lsx_vavgr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_w : ClangBuiltin<"__builtin_lsx_vavgr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_d : ClangBuiltin<"__builtin_lsx_vavgr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vavgr_bu : ClangBuiltin<"__builtin_lsx_vavgr_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_hu : ClangBuiltin<"__builtin_lsx_vavgr_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_wu : ClangBuiltin<"__builtin_lsx_vavgr_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vavgr_du : ClangBuiltin<"__builtin_lsx_vavgr_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrlr_b : ClangBuiltin<"__builtin_lsx_vsrlr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlr_h : ClangBuiltin<"__builtin_lsx_vsrlr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlr_w : ClangBuiltin<"__builtin_lsx_vsrlr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlr_d : ClangBuiltin<"__builtin_lsx_vsrlr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrar_b : ClangBuiltin<"__builtin_lsx_vsrar_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrar_h : ClangBuiltin<"__builtin_lsx_vsrar_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrar_w : ClangBuiltin<"__builtin_lsx_vsrar_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrar_d : ClangBuiltin<"__builtin_lsx_vsrar_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmax_s : ClangBuiltin<"__builtin_lsx_vfmax_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmax_d : ClangBuiltin<"__builtin_lsx_vfmax_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmin_s : ClangBuiltin<"__builtin_lsx_vfmin_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmin_d : ClangBuiltin<"__builtin_lsx_vfmin_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmaxa_s : ClangBuiltin<"__builtin_lsx_vfmaxa_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmaxa_d : ClangBuiltin<"__builtin_lsx_vfmaxa_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmina_s : ClangBuiltin<"__builtin_lsx_vfmina_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmina_d : ClangBuiltin<"__builtin_lsx_vfmina_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfclass_s : ClangBuiltin<"__builtin_lsx_vfclass_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfclass_d : ClangBuiltin<"__builtin_lsx_vfclass_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrecip_s : ClangBuiltin<"__builtin_lsx_vfrecip_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrecip_d : ClangBuiltin<"__builtin_lsx_vfrecip_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrsqrt_s : ClangBuiltin<"__builtin_lsx_vfrsqrt_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrsqrt_d : ClangBuiltin<"__builtin_lsx_vfrsqrt_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcvtl_s_h : ClangBuiltin<"__builtin_lsx_vfcvtl_s_h">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcvtl_d_s : ClangBuiltin<"__builtin_lsx_vfcvtl_d_s">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfcvth_s_h : ClangBuiltin<"__builtin_lsx_vfcvth_s_h">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfcvth_d_s : ClangBuiltin<"__builtin_lsx_vfcvth_d_s">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftint_w_s : ClangBuiltin<"__builtin_lsx_vftint_w_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftint_l_d : ClangBuiltin<"__builtin_lsx_vftint_l_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftint_wu_s : ClangBuiltin<"__builtin_lsx_vftint_wu_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftint_lu_d : ClangBuiltin<"__builtin_lsx_vftint_lu_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrlri_b : ClangBuiltin<"__builtin_lsx_vsrlri_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlri_h : ClangBuiltin<"__builtin_lsx_vsrlri_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlri_w : ClangBuiltin<"__builtin_lsx_vsrlri_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlri_d : ClangBuiltin<"__builtin_lsx_vsrlri_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrari_b : ClangBuiltin<"__builtin_lsx_vsrari_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrari_h : ClangBuiltin<"__builtin_lsx_vsrari_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrari_w : ClangBuiltin<"__builtin_lsx_vsrari_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrari_d : ClangBuiltin<"__builtin_lsx_vsrari_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsat_b : ClangBuiltin<"__builtin_lsx_vsat_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_h : ClangBuiltin<"__builtin_lsx_vsat_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_w : ClangBuiltin<"__builtin_lsx_vsat_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_d : ClangBuiltin<"__builtin_lsx_vsat_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsat_bu : ClangBuiltin<"__builtin_lsx_vsat_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_hu : ClangBuiltin<"__builtin_lsx_vsat_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_wu : ClangBuiltin<"__builtin_lsx_vsat_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsat_du : ClangBuiltin<"__builtin_lsx_vsat_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrlni_b_h : ClangBuiltin<"__builtin_lsx_vsrlni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlni_h_w : ClangBuiltin<"__builtin_lsx_vsrlni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlni_w_d : ClangBuiltin<"__builtin_lsx_vsrlni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlni_d_q : ClangBuiltin<"__builtin_lsx_vsrlni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrlrni_b_h : ClangBuiltin<"__builtin_lsx_vsrlrni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlrni_h_w : ClangBuiltin<"__builtin_lsx_vsrlrni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlrni_w_d : ClangBuiltin<"__builtin_lsx_vsrlrni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrlrni_d_q : ClangBuiltin<"__builtin_lsx_vsrlrni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlni_b_h : ClangBuiltin<"__builtin_lsx_vssrlni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_h_w : ClangBuiltin<"__builtin_lsx_vssrlni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_w_d : ClangBuiltin<"__builtin_lsx_vssrlni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_d_q : ClangBuiltin<"__builtin_lsx_vssrlni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlrni_bu_h : ClangBuiltin<"__builtin_lsx_vssrlrni_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_hu_w : ClangBuiltin<"__builtin_lsx_vssrlrni_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_wu_d : ClangBuiltin<"__builtin_lsx_vssrlrni_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlrni_du_q : ClangBuiltin<"__builtin_lsx_vssrlrni_du_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrarni_b_h : ClangBuiltin<"__builtin_lsx_vsrarni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrarni_h_w : ClangBuiltin<"__builtin_lsx_vsrarni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrarni_w_d : ClangBuiltin<"__builtin_lsx_vsrarni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrarni_d_q : ClangBuiltin<"__builtin_lsx_vsrarni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrani_b_h : ClangBuiltin<"__builtin_lsx_vssrani_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_h_w : ClangBuiltin<"__builtin_lsx_vssrani_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_w_d : ClangBuiltin<"__builtin_lsx_vssrani_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_d_q : ClangBuiltin<"__builtin_lsx_vssrani_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrani_bu_h : ClangBuiltin<"__builtin_lsx_vssrani_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_hu_w : ClangBuiltin<"__builtin_lsx_vssrani_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_wu_d : ClangBuiltin<"__builtin_lsx_vssrani_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrani_du_q : ClangBuiltin<"__builtin_lsx_vssrani_du_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrarni_b_h : ClangBuiltin<"__builtin_lsx_vssrarni_b_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_h_w : ClangBuiltin<"__builtin_lsx_vssrarni_h_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_w_d : ClangBuiltin<"__builtin_lsx_vssrarni_w_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_d_q : ClangBuiltin<"__builtin_lsx_vssrarni_d_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrarni_bu_h : ClangBuiltin<"__builtin_lsx_vssrarni_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_hu_w : ClangBuiltin<"__builtin_lsx_vssrarni_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_wu_d : ClangBuiltin<"__builtin_lsx_vssrarni_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrarni_du_q : ClangBuiltin<"__builtin_lsx_vssrarni_du_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vssrlni_bu_h : ClangBuiltin<"__builtin_lsx_vssrlni_bu_h">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_hu_w : ClangBuiltin<"__builtin_lsx_vssrlni_hu_w">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_wu_d : ClangBuiltin<"__builtin_lsx_vssrlni_wu_d">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vssrlni_du_q : ClangBuiltin<"__builtin_lsx_vssrlni_du_q">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vseq_b : ClangBuiltin<"__builtin_lsx_vseq_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseq_h : ClangBuiltin<"__builtin_lsx_vseq_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseq_w : ClangBuiltin<"__builtin_lsx_vseq_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseq_d : ClangBuiltin<"__builtin_lsx_vseq_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsle_b : ClangBuiltin<"__builtin_lsx_vsle_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_h : ClangBuiltin<"__builtin_lsx_vsle_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_w : ClangBuiltin<"__builtin_lsx_vsle_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_d : ClangBuiltin<"__builtin_lsx_vsle_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsle_bu : ClangBuiltin<"__builtin_lsx_vsle_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_hu : ClangBuiltin<"__builtin_lsx_vsle_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_wu : ClangBuiltin<"__builtin_lsx_vsle_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsle_du : ClangBuiltin<"__builtin_lsx_vsle_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslt_b : ClangBuiltin<"__builtin_lsx_vslt_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_h : ClangBuiltin<"__builtin_lsx_vslt_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_w : ClangBuiltin<"__builtin_lsx_vslt_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_d : ClangBuiltin<"__builtin_lsx_vslt_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslt_bu : ClangBuiltin<"__builtin_lsx_vslt_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_hu : ClangBuiltin<"__builtin_lsx_vslt_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_wu : ClangBuiltin<"__builtin_lsx_vslt_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslt_du : ClangBuiltin<"__builtin_lsx_vslt_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vadd_b : ClangBuiltin<"__builtin_lsx_vadd_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadd_h : ClangBuiltin<"__builtin_lsx_vadd_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadd_w : ClangBuiltin<"__builtin_lsx_vadd_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vadd_d : ClangBuiltin<"__builtin_lsx_vadd_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vsub_b : ClangBuiltin<"__builtin_lsx_vsub_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsub_h : ClangBuiltin<"__builtin_lsx_vsub_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsub_w : ClangBuiltin<"__builtin_lsx_vsub_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsub_d : ClangBuiltin<"__builtin_lsx_vsub_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmax_b : ClangBuiltin<"__builtin_lsx_vmax_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_h : ClangBuiltin<"__builtin_lsx_vmax_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_w : ClangBuiltin<"__builtin_lsx_vmax_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_d : ClangBuiltin<"__builtin_lsx_vmax_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmin_b : ClangBuiltin<"__builtin_lsx_vmin_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_h : ClangBuiltin<"__builtin_lsx_vmin_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_w : ClangBuiltin<"__builtin_lsx_vmin_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_d : ClangBuiltin<"__builtin_lsx_vmin_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmax_bu : ClangBuiltin<"__builtin_lsx_vmax_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_hu : ClangBuiltin<"__builtin_lsx_vmax_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_wu : ClangBuiltin<"__builtin_lsx_vmax_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmax_du : ClangBuiltin<"__builtin_lsx_vmax_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmin_bu : ClangBuiltin<"__builtin_lsx_vmin_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_hu : ClangBuiltin<"__builtin_lsx_vmin_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_wu : ClangBuiltin<"__builtin_lsx_vmin_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmin_du : ClangBuiltin<"__builtin_lsx_vmin_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmul_b : ClangBuiltin<"__builtin_lsx_vmul_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmul_h : ClangBuiltin<"__builtin_lsx_vmul_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmul_w : ClangBuiltin<"__builtin_lsx_vmul_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmul_d : ClangBuiltin<"__builtin_lsx_vmul_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmadd_b : ClangBuiltin<"__builtin_lsx_vmadd_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmadd_h : ClangBuiltin<"__builtin_lsx_vmadd_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmadd_w : ClangBuiltin<"__builtin_lsx_vmadd_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmadd_d : ClangBuiltin<"__builtin_lsx_vmadd_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmsub_b : ClangBuiltin<"__builtin_lsx_vmsub_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmsub_h : ClangBuiltin<"__builtin_lsx_vmsub_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmsub_w : ClangBuiltin<"__builtin_lsx_vmsub_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vmsub_d : ClangBuiltin<"__builtin_lsx_vmsub_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vdiv_b : ClangBuiltin<"__builtin_lsx_vdiv_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_h : ClangBuiltin<"__builtin_lsx_vdiv_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_w : ClangBuiltin<"__builtin_lsx_vdiv_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_d : ClangBuiltin<"__builtin_lsx_vdiv_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmod_b : ClangBuiltin<"__builtin_lsx_vmod_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_h : ClangBuiltin<"__builtin_lsx_vmod_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_w : ClangBuiltin<"__builtin_lsx_vmod_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_d : ClangBuiltin<"__builtin_lsx_vmod_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vdiv_bu : ClangBuiltin<"__builtin_lsx_vdiv_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_hu : ClangBuiltin<"__builtin_lsx_vdiv_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_wu : ClangBuiltin<"__builtin_lsx_vdiv_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vdiv_du : ClangBuiltin<"__builtin_lsx_vdiv_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsll_b : ClangBuiltin<"__builtin_lsx_vsll_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsll_h : ClangBuiltin<"__builtin_lsx_vsll_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsll_w : ClangBuiltin<"__builtin_lsx_vsll_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsll_d : ClangBuiltin<"__builtin_lsx_vsll_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrl_b : ClangBuiltin<"__builtin_lsx_vsrl_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrl_h : ClangBuiltin<"__builtin_lsx_vsrl_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrl_w : ClangBuiltin<"__builtin_lsx_vsrl_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrl_d : ClangBuiltin<"__builtin_lsx_vsrl_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitclr_b : ClangBuiltin<"__builtin_lsx_vbitclr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclr_h : ClangBuiltin<"__builtin_lsx_vbitclr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclr_w : ClangBuiltin<"__builtin_lsx_vbitclr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitclr_d : ClangBuiltin<"__builtin_lsx_vbitclr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitset_b : ClangBuiltin<"__builtin_lsx_vbitset_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitset_h : ClangBuiltin<"__builtin_lsx_vbitset_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitset_w : ClangBuiltin<"__builtin_lsx_vbitset_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitset_d : ClangBuiltin<"__builtin_lsx_vbitset_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpackev_b : ClangBuiltin<"__builtin_lsx_vpackev_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackev_h : ClangBuiltin<"__builtin_lsx_vpackev_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackev_w : ClangBuiltin<"__builtin_lsx_vpackev_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackev_d : ClangBuiltin<"__builtin_lsx_vpackev_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpackod_b : ClangBuiltin<"__builtin_lsx_vpackod_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackod_h : ClangBuiltin<"__builtin_lsx_vpackod_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackod_w : ClangBuiltin<"__builtin_lsx_vpackod_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpackod_d : ClangBuiltin<"__builtin_lsx_vpackod_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vilvl_b : ClangBuiltin<"__builtin_lsx_vilvl_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvl_h : ClangBuiltin<"__builtin_lsx_vilvl_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvl_w : ClangBuiltin<"__builtin_lsx_vilvl_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvl_d : ClangBuiltin<"__builtin_lsx_vilvl_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vilvh_b : ClangBuiltin<"__builtin_lsx_vilvh_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvh_h : ClangBuiltin<"__builtin_lsx_vilvh_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvh_w : ClangBuiltin<"__builtin_lsx_vilvh_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vilvh_d : ClangBuiltin<"__builtin_lsx_vilvh_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpickev_b : ClangBuiltin<"__builtin_lsx_vpickev_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickev_h : ClangBuiltin<"__builtin_lsx_vpickev_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickev_w : ClangBuiltin<"__builtin_lsx_vpickev_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickev_d : ClangBuiltin<"__builtin_lsx_vpickev_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vand_v : ClangBuiltin<"__builtin_lsx_vand_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vor_v : ClangBuiltin<"__builtin_lsx_vor_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vbitrev_b : ClangBuiltin<"__builtin_lsx_vbitrev_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrev_h : ClangBuiltin<"__builtin_lsx_vbitrev_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrev_w : ClangBuiltin<"__builtin_lsx_vbitrev_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vbitrev_d : ClangBuiltin<"__builtin_lsx_vbitrev_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmod_bu : ClangBuiltin<"__builtin_lsx_vmod_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_hu : ClangBuiltin<"__builtin_lsx_vmod_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_wu : ClangBuiltin<"__builtin_lsx_vmod_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmod_du : ClangBuiltin<"__builtin_lsx_vmod_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpickod_b : ClangBuiltin<"__builtin_lsx_vpickod_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickod_h : ClangBuiltin<"__builtin_lsx_vpickod_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickod_w : ClangBuiltin<"__builtin_lsx_vpickod_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpickod_d : ClangBuiltin<"__builtin_lsx_vpickod_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vreplve_b : ClangBuiltin<"__builtin_lsx_vreplve_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplve_h : ClangBuiltin<"__builtin_lsx_vreplve_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplve_w : ClangBuiltin<"__builtin_lsx_vreplve_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplve_d : ClangBuiltin<"__builtin_lsx_vreplve_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsra_b : ClangBuiltin<"__builtin_lsx_vsra_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsra_h : ClangBuiltin<"__builtin_lsx_vsra_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsra_w : ClangBuiltin<"__builtin_lsx_vsra_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsra_d : ClangBuiltin<"__builtin_lsx_vsra_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vxor_v : ClangBuiltin<"__builtin_lsx_vxor_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vnor_v : ClangBuiltin<"__builtin_lsx_vnor_v">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfadd_s : ClangBuiltin<"__builtin_lsx_vfadd_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfadd_d : ClangBuiltin<"__builtin_lsx_vfadd_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfsub_s : ClangBuiltin<"__builtin_lsx_vfsub_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfsub_d : ClangBuiltin<"__builtin_lsx_vfsub_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfmul_s : ClangBuiltin<"__builtin_lsx_vfmul_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfmul_d : ClangBuiltin<"__builtin_lsx_vfmul_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vshuf_h : ClangBuiltin<"__builtin_lsx_vshuf_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vshuf_w : ClangBuiltin<"__builtin_lsx_vshuf_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vshuf_d : ClangBuiltin<"__builtin_lsx_vshuf_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vseqi_b : ClangBuiltin<"__builtin_lsx_vseqi_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseqi_h : ClangBuiltin<"__builtin_lsx_vseqi_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseqi_w : ClangBuiltin<"__builtin_lsx_vseqi_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vseqi_d : ClangBuiltin<"__builtin_lsx_vseqi_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslei_b : ClangBuiltin<"__builtin_lsx_vslei_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_h : ClangBuiltin<"__builtin_lsx_vslei_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_w : ClangBuiltin<"__builtin_lsx_vslei_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_d : ClangBuiltin<"__builtin_lsx_vslei_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslei_bu : ClangBuiltin<"__builtin_lsx_vslei_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_hu : ClangBuiltin<"__builtin_lsx_vslei_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_wu : ClangBuiltin<"__builtin_lsx_vslei_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslei_du : ClangBuiltin<"__builtin_lsx_vslei_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslti_b : ClangBuiltin<"__builtin_lsx_vslti_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_h : ClangBuiltin<"__builtin_lsx_vslti_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_w : ClangBuiltin<"__builtin_lsx_vslti_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_d : ClangBuiltin<"__builtin_lsx_vslti_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslti_bu : ClangBuiltin<"__builtin_lsx_vslti_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_hu : ClangBuiltin<"__builtin_lsx_vslti_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_wu : ClangBuiltin<"__builtin_lsx_vslti_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslti_du : ClangBuiltin<"__builtin_lsx_vslti_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vaddi_bu : ClangBuiltin<"__builtin_lsx_vaddi_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vaddi_hu : ClangBuiltin<"__builtin_lsx_vaddi_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vaddi_wu : ClangBuiltin<"__builtin_lsx_vaddi_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lsx_vaddi_du : ClangBuiltin<"__builtin_lsx_vaddi_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lsx_vsubi_bu : ClangBuiltin<"__builtin_lsx_vsubi_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubi_hu : ClangBuiltin<"__builtin_lsx_vsubi_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubi_wu : ClangBuiltin<"__builtin_lsx_vsubi_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsubi_du : ClangBuiltin<"__builtin_lsx_vsubi_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaxi_b : ClangBuiltin<"__builtin_lsx_vmaxi_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_h : ClangBuiltin<"__builtin_lsx_vmaxi_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_w : ClangBuiltin<"__builtin_lsx_vmaxi_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_d : ClangBuiltin<"__builtin_lsx_vmaxi_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmini_b : ClangBuiltin<"__builtin_lsx_vmini_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_h : ClangBuiltin<"__builtin_lsx_vmini_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_w : ClangBuiltin<"__builtin_lsx_vmini_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_d : ClangBuiltin<"__builtin_lsx_vmini_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmaxi_bu : ClangBuiltin<"__builtin_lsx_vmaxi_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_hu : ClangBuiltin<"__builtin_lsx_vmaxi_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_wu : ClangBuiltin<"__builtin_lsx_vmaxi_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmaxi_du : ClangBuiltin<"__builtin_lsx_vmaxi_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vmini_bu : ClangBuiltin<"__builtin_lsx_vmini_bu">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_hu : ClangBuiltin<"__builtin_lsx_vmini_hu">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_wu : ClangBuiltin<"__builtin_lsx_vmini_wu">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vmini_du : ClangBuiltin<"__builtin_lsx_vmini_du">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vclz_b : ClangBuiltin<"__builtin_lsx_vclz_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclz_h : ClangBuiltin<"__builtin_lsx_vclz_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclz_w : ClangBuiltin<"__builtin_lsx_vclz_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vclz_d : ClangBuiltin<"__builtin_lsx_vclz_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vpcnt_b : ClangBuiltin<"__builtin_lsx_vpcnt_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpcnt_h : ClangBuiltin<"__builtin_lsx_vpcnt_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpcnt_w : ClangBuiltin<"__builtin_lsx_vpcnt_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vpcnt_d : ClangBuiltin<"__builtin_lsx_vpcnt_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfsqrt_s : ClangBuiltin<"__builtin_lsx_vfsqrt_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfsqrt_d : ClangBuiltin<"__builtin_lsx_vfsqrt_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfrint_s : ClangBuiltin<"__builtin_lsx_vfrint_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfrint_d : ClangBuiltin<"__builtin_lsx_vfrint_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vffint_s_w : ClangBuiltin<"__builtin_lsx_vffint_s_w">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vffint_d_l : ClangBuiltin<"__builtin_lsx_vffint_d_l">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vffint_s_wu : ClangBuiltin<"__builtin_lsx_vffint_s_wu">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vffint_d_lu : ClangBuiltin<"__builtin_lsx_vffint_d_lu">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vftintrz_wu_s : ClangBuiltin<"__builtin_lsx_vftintrz_wu_s">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vftintrz_lu_d : ClangBuiltin<"__builtin_lsx_vftintrz_lu_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vreplgr2vr_b : ClangBuiltin<"__builtin_lsx_vreplgr2vr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplgr2vr_h : ClangBuiltin<"__builtin_lsx_vreplgr2vr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplgr2vr_w : ClangBuiltin<"__builtin_lsx_vreplgr2vr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vreplgr2vr_d : ClangBuiltin<"__builtin_lsx_vreplgr2vr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vinsgr2vr_b : ClangBuiltin<"__builtin_lsx_vinsgr2vr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vinsgr2vr_h : ClangBuiltin<"__builtin_lsx_vinsgr2vr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vinsgr2vr_w : ClangBuiltin<"__builtin_lsx_vinsgr2vr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lsx_vinsgr2vr_d : ClangBuiltin<"__builtin_lsx_vinsgr2vr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i64_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lsx_vfdiv_s : ClangBuiltin<"__builtin_lsx_vfdiv_s">, ++ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vfdiv_d : ClangBuiltin<"__builtin_lsx_vfdiv_d">, ++ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vslli_b : ClangBuiltin<"__builtin_lsx_vslli_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslli_h : ClangBuiltin<"__builtin_lsx_vslli_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslli_w : ClangBuiltin<"__builtin_lsx_vslli_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vslli_d : ClangBuiltin<"__builtin_lsx_vslli_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrli_b : ClangBuiltin<"__builtin_lsx_vsrli_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrli_h : ClangBuiltin<"__builtin_lsx_vsrli_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrli_w : ClangBuiltin<"__builtin_lsx_vsrli_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrli_d : ClangBuiltin<"__builtin_lsx_vsrli_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vsrai_b : ClangBuiltin<"__builtin_lsx_vsrai_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrai_h : ClangBuiltin<"__builtin_lsx_vsrai_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrai_w : ClangBuiltin<"__builtin_lsx_vsrai_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vsrai_d : ClangBuiltin<"__builtin_lsx_vsrai_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vshuf4i_b : ClangBuiltin<"__builtin_lsx_vshuf4i_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vshuf4i_h : ClangBuiltin<"__builtin_lsx_vshuf4i_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vshuf4i_w : ClangBuiltin<"__builtin_lsx_vshuf4i_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vshuf4i_d : ClangBuiltin<"__builtin_lsx_vshuf4i_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrotr_b : ClangBuiltin<"__builtin_lsx_vrotr_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotr_h : ClangBuiltin<"__builtin_lsx_vrotr_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotr_w : ClangBuiltin<"__builtin_lsx_vrotr_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotr_d : ClangBuiltin<"__builtin_lsx_vrotr_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vrotri_b : ClangBuiltin<"__builtin_lsx_vrotri_b">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotri_h : ClangBuiltin<"__builtin_lsx_vrotri_h">, ++ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotri_w : ClangBuiltin<"__builtin_lsx_vrotri_w">, ++ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_vrotri_d : ClangBuiltin<"__builtin_lsx_vrotri_d">, ++ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_vld : ClangBuiltin<"__builtin_lsx_vld">, ++ Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], ++ [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_vst : ClangBuiltin<"__builtin_lsx_vst">, ++ Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], ++ [IntrArgMemOnly]>; ++ ++def int_loongarch_lsx_bz_v : ClangBuiltin<"__builtin_lsx_bz_v">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_bnz_v : ClangBuiltin<"__builtin_lsx_bnz_v">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_bz_b : ClangBuiltin<"__builtin_lsx_bz_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bz_h : ClangBuiltin<"__builtin_lsx_bz_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bz_w : ClangBuiltin<"__builtin_lsx_bz_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bz_d : ClangBuiltin<"__builtin_lsx_bz_d">, ++ Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lsx_bnz_b : ClangBuiltin<"__builtin_lsx_bnz_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bnz_h : ClangBuiltin<"__builtin_lsx_bnz_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bnz_w : ClangBuiltin<"__builtin_lsx_bnz_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; ++def int_loongarch_lsx_bnz_d : ClangBuiltin<"__builtin_lsx_bnz_d">, ++ Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; ++ ++//===----------------------------------------------------------------------===// ++//LoongArch LASX ++ ++def int_loongarch_lasx_xvfmadd_s : ClangBuiltin<"__builtin_lasx_xvfmadd_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvfmadd_d : ClangBuiltin<"__builtin_lasx_xvfmadd_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmsub_s : ClangBuiltin<"__builtin_lasx_xvfmsub_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvfmsub_d : ClangBuiltin<"__builtin_lasx_xvfmsub_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], ++ [IntrNoMem]>; ++ ++ ++def int_loongarch_lasx_xvfnmadd_s : ClangBuiltin<"__builtin_lasx_xvfnmadd_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvfnmadd_d : ClangBuiltin<"__builtin_lasx_xvfnmadd_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfnmsub_s : ClangBuiltin<"__builtin_lasx_xvfnmsub_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvfnmsub_d : ClangBuiltin<"__builtin_lasx_xvfnmsub_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvclo_b : ClangBuiltin<"__builtin_lasx_xvclo_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclo_h : ClangBuiltin<"__builtin_lasx_xvclo_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclo_w : ClangBuiltin<"__builtin_lasx_xvclo_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclo_d : ClangBuiltin<"__builtin_lasx_xvclo_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvflogb_s : ClangBuiltin<"__builtin_lasx_xvflogb_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvflogb_d : ClangBuiltin<"__builtin_lasx_xvflogb_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickve2gr_w : ClangBuiltin<"__builtin_lasx_xvpickve2gr_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickve2gr_d : ClangBuiltin<"__builtin_lasx_xvpickve2gr_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickve2gr_wu : ClangBuiltin<"__builtin_lasx_xvpickve2gr_wu">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickve2gr_du : ClangBuiltin<"__builtin_lasx_xvpickve2gr_du">, ++ Intrinsic<[llvm_i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmskltz_b : ClangBuiltin<"__builtin_lasx_xvmskltz_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmskltz_h : ClangBuiltin<"__builtin_lasx_xvmskltz_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmskltz_w : ClangBuiltin<"__builtin_lasx_xvmskltz_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmskltz_d : ClangBuiltin<"__builtin_lasx_xvmskltz_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_caf_s : ClangBuiltin<"__builtin_lasx_xvfcmp_caf_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_caf_d : ClangBuiltin<"__builtin_lasx_xvfcmp_caf_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cor_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cor_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cor_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cor_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cun_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cun_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cun_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cun_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cune_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cune_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cune_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cune_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cueq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cueq_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cueq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cueq_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_ceq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_ceq_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_ceq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_ceq_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cne_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cne_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cne_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cne_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_clt_s : ClangBuiltin<"__builtin_lasx_xvfcmp_clt_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_clt_d : ClangBuiltin<"__builtin_lasx_xvfcmp_clt_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cult_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cult_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cult_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cult_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cle_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cle_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cle_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cle_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_cule_s : ClangBuiltin<"__builtin_lasx_xvfcmp_cule_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_cule_d : ClangBuiltin<"__builtin_lasx_xvfcmp_cule_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_saf_s : ClangBuiltin<"__builtin_lasx_xvfcmp_saf_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_saf_d : ClangBuiltin<"__builtin_lasx_xvfcmp_saf_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sor_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sor_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sor_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sor_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sun_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sun_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sun_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sun_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sune_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sune_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sune_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sune_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sueq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sueq_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sueq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sueq_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_seq_s : ClangBuiltin<"__builtin_lasx_xvfcmp_seq_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_seq_d : ClangBuiltin<"__builtin_lasx_xvfcmp_seq_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sne_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sne_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sne_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sne_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_slt_s : ClangBuiltin<"__builtin_lasx_xvfcmp_slt_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_slt_d : ClangBuiltin<"__builtin_lasx_xvfcmp_slt_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sult_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sult_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sult_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sult_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sle_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sle_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sle_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sle_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcmp_sule_s : ClangBuiltin<"__builtin_lasx_xvfcmp_sule_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcmp_sule_d : ClangBuiltin<"__builtin_lasx_xvfcmp_sule_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitsel_v : ClangBuiltin<"__builtin_lasx_xvbitsel_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvshuf_b : ClangBuiltin<"__builtin_lasx_xvshuf_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvldrepl_b : ClangBuiltin<"__builtin_lasx_xvldrepl_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lasx_xvldrepl_h : ClangBuiltin<"__builtin_lasx_xvldrepl_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lasx_xvldrepl_w : ClangBuiltin<"__builtin_lasx_xvldrepl_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++def int_loongarch_lasx_xvldrepl_d : ClangBuiltin<"__builtin_lasx_xvldrepl_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvstelm_b : ClangBuiltin<"__builtin_lasx_xvstelm_b">, ++ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lasx_xvstelm_h : ClangBuiltin<"__builtin_lasx_xvstelm_h">, ++ Intrinsic<[], [llvm_v16i16_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lasx_xvstelm_w : ClangBuiltin<"__builtin_lasx_xvstelm_w">, ++ Intrinsic<[], [llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++def int_loongarch_lasx_xvstelm_d : ClangBuiltin<"__builtin_lasx_xvstelm_d">, ++ Intrinsic<[], [llvm_v4i64_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvldx : ClangBuiltin<"__builtin_lasx_xvldx">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i64_ty], ++ [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvstx : ClangBuiltin<"__builtin_lasx_xvstx">, ++ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i64_ty], ++ [IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvaddwev_d_w : ClangBuiltin<"__builtin_lasx_xvaddwev_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_w_h : ClangBuiltin<"__builtin_lasx_xvaddwev_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_h_b : ClangBuiltin<"__builtin_lasx_xvaddwev_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_q_d : ClangBuiltin<"__builtin_lasx_xvaddwev_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsubwev_d_w : ClangBuiltin<"__builtin_lasx_xvsubwev_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_w_h : ClangBuiltin<"__builtin_lasx_xvsubwev_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_h_b : ClangBuiltin<"__builtin_lasx_xvsubwev_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_q_d : ClangBuiltin<"__builtin_lasx_xvsubwev_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddwod_d_w : ClangBuiltin<"__builtin_lasx_xvaddwod_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_w_h : ClangBuiltin<"__builtin_lasx_xvaddwod_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_h_b : ClangBuiltin<"__builtin_lasx_xvaddwod_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_q_d : ClangBuiltin<"__builtin_lasx_xvaddwod_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsubwod_d_w : ClangBuiltin<"__builtin_lasx_xvsubwod_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_w_h : ClangBuiltin<"__builtin_lasx_xvsubwod_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_h_b : ClangBuiltin<"__builtin_lasx_xvsubwod_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_q_d : ClangBuiltin<"__builtin_lasx_xvsubwod_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddwev_d_wu : ClangBuiltin<"__builtin_lasx_xvaddwev_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_w_hu : ClangBuiltin<"__builtin_lasx_xvaddwev_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_h_bu : ClangBuiltin<"__builtin_lasx_xvaddwev_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_q_du : ClangBuiltin<"__builtin_lasx_xvaddwev_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsubwev_d_wu : ClangBuiltin<"__builtin_lasx_xvsubwev_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_w_hu : ClangBuiltin<"__builtin_lasx_xvsubwev_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_h_bu : ClangBuiltin<"__builtin_lasx_xvsubwev_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwev_q_du : ClangBuiltin<"__builtin_lasx_xvsubwev_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddwod_d_wu : ClangBuiltin<"__builtin_lasx_xvaddwod_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_w_hu : ClangBuiltin<"__builtin_lasx_xvaddwod_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_h_bu : ClangBuiltin<"__builtin_lasx_xvaddwod_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_q_du : ClangBuiltin<"__builtin_lasx_xvaddwod_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsubwod_d_wu : ClangBuiltin<"__builtin_lasx_xvsubwod_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_w_hu : ClangBuiltin<"__builtin_lasx_xvsubwod_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_h_bu : ClangBuiltin<"__builtin_lasx_xvsubwod_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubwod_q_du : ClangBuiltin<"__builtin_lasx_xvsubwod_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvaddwev_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvaddwev_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvaddwev_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvaddwev_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvaddwod_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvaddwod_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvaddwod_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvaddwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvaddwod_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhaddw_qu_du : ClangBuiltin<"__builtin_lasx_xvhaddw_qu_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_qu_du : ClangBuiltin<"__builtin_lasx_xvhsubw_qu_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhaddw_q_d : ClangBuiltin<"__builtin_lasx_xvhaddw_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_q_d : ClangBuiltin<"__builtin_lasx_xvhsubw_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmuh_b : ClangBuiltin<"__builtin_lasx_xvmuh_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_h : ClangBuiltin<"__builtin_lasx_xvmuh_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_w : ClangBuiltin<"__builtin_lasx_xvmuh_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_d : ClangBuiltin<"__builtin_lasx_xvmuh_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmuh_bu : ClangBuiltin<"__builtin_lasx_xvmuh_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_hu : ClangBuiltin<"__builtin_lasx_xvmuh_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_wu : ClangBuiltin<"__builtin_lasx_xvmuh_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmuh_du : ClangBuiltin<"__builtin_lasx_xvmuh_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwev_d_w : ClangBuiltin<"__builtin_lasx_xvmulwev_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_w_h : ClangBuiltin<"__builtin_lasx_xvmulwev_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_h_b : ClangBuiltin<"__builtin_lasx_xvmulwev_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_q_d : ClangBuiltin<"__builtin_lasx_xvmulwev_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwod_d_w : ClangBuiltin<"__builtin_lasx_xvmulwod_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_w_h : ClangBuiltin<"__builtin_lasx_xvmulwod_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_h_b : ClangBuiltin<"__builtin_lasx_xvmulwod_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_q_d : ClangBuiltin<"__builtin_lasx_xvmulwod_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwev_d_wu : ClangBuiltin<"__builtin_lasx_xvmulwev_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_w_hu : ClangBuiltin<"__builtin_lasx_xvmulwev_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_h_bu : ClangBuiltin<"__builtin_lasx_xvmulwev_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_q_du : ClangBuiltin<"__builtin_lasx_xvmulwev_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwod_d_wu : ClangBuiltin<"__builtin_lasx_xvmulwod_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_w_hu : ClangBuiltin<"__builtin_lasx_xvmulwod_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_h_bu : ClangBuiltin<"__builtin_lasx_xvmulwod_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_q_du : ClangBuiltin<"__builtin_lasx_xvmulwod_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmulwev_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmulwev_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmulwev_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvmulwev_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmulwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmulwod_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmulwod_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmulwod_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmulwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvmulwod_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwev_d_w : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_w_h : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_h_b : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_q_d : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwod_d_w : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_w_h : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_h_b : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_q_d : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwev_d_wu : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_w_hu : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_h_bu : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_q_du : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwod_d_wu : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_w_hu : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_h_bu : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_q_du : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwev_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmaddwev_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmaddwev_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmaddwev_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwev_q_du_d : ClangBuiltin<"__builtin_lasx_xvmaddwev_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaddwod_d_wu_w : ClangBuiltin<"__builtin_lasx_xvmaddwod_d_wu_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_w_hu_h : ClangBuiltin<"__builtin_lasx_xvmaddwod_w_hu_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_h_bu_b : ClangBuiltin<"__builtin_lasx_xvmaddwod_h_bu_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaddwod_q_du_d : ClangBuiltin<"__builtin_lasx_xvmaddwod_q_du_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrln_b_h : ClangBuiltin<"__builtin_lasx_xvsrln_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrln_h_w : ClangBuiltin<"__builtin_lasx_xvsrln_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrln_w_d : ClangBuiltin<"__builtin_lasx_xvsrln_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsran_b_h : ClangBuiltin<"__builtin_lasx_xvsran_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsran_h_w : ClangBuiltin<"__builtin_lasx_xvsran_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsran_w_d : ClangBuiltin<"__builtin_lasx_xvsran_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrlrn_b_h : ClangBuiltin<"__builtin_lasx_xvsrlrn_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlrn_h_w : ClangBuiltin<"__builtin_lasx_xvsrlrn_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlrn_w_d : ClangBuiltin<"__builtin_lasx_xvsrlrn_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrarn_b_h : ClangBuiltin<"__builtin_lasx_xvsrarn_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrarn_h_w : ClangBuiltin<"__builtin_lasx_xvsrarn_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrarn_w_d : ClangBuiltin<"__builtin_lasx_xvsrarn_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrln_b_h : ClangBuiltin<"__builtin_lasx_xvssrln_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrln_h_w : ClangBuiltin<"__builtin_lasx_xvssrln_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrln_w_d : ClangBuiltin<"__builtin_lasx_xvssrln_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssran_b_h : ClangBuiltin<"__builtin_lasx_xvssran_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssran_h_w : ClangBuiltin<"__builtin_lasx_xvssran_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssran_w_d : ClangBuiltin<"__builtin_lasx_xvssran_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlrn_b_h : ClangBuiltin<"__builtin_lasx_xvssrlrn_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrn_h_w : ClangBuiltin<"__builtin_lasx_xvssrlrn_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrn_w_d : ClangBuiltin<"__builtin_lasx_xvssrlrn_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrarn_b_h : ClangBuiltin<"__builtin_lasx_xvssrarn_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarn_h_w : ClangBuiltin<"__builtin_lasx_xvssrarn_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarn_w_d : ClangBuiltin<"__builtin_lasx_xvssrarn_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrln_bu_h : ClangBuiltin<"__builtin_lasx_xvssrln_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrln_hu_w : ClangBuiltin<"__builtin_lasx_xvssrln_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrln_wu_d : ClangBuiltin<"__builtin_lasx_xvssrln_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssran_bu_h : ClangBuiltin<"__builtin_lasx_xvssran_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssran_hu_w : ClangBuiltin<"__builtin_lasx_xvssran_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssran_wu_d : ClangBuiltin<"__builtin_lasx_xvssran_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlrn_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlrn_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrn_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlrn_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrn_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlrn_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrarn_bu_h : ClangBuiltin<"__builtin_lasx_xvssrarn_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarn_hu_w : ClangBuiltin<"__builtin_lasx_xvssrarn_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarn_wu_d : ClangBuiltin<"__builtin_lasx_xvssrarn_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvandn_v : ClangBuiltin<"__builtin_lasx_xvandn_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvorn_v : ClangBuiltin<"__builtin_lasx_xvorn_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrstp_b : ClangBuiltin<"__builtin_lasx_xvfrstp_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvfrstp_h : ClangBuiltin<"__builtin_lasx_xvfrstp_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvadd_q : ClangBuiltin<"__builtin_lasx_xvadd_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsub_q : ClangBuiltin<"__builtin_lasx_xvsub_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsigncov_b : ClangBuiltin<"__builtin_lasx_xvsigncov_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvsigncov_h : ClangBuiltin<"__builtin_lasx_xvsigncov_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvsigncov_w : ClangBuiltin<"__builtin_lasx_xvsigncov_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvsigncov_d : ClangBuiltin<"__builtin_lasx_xvsigncov_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcvt_h_s : ClangBuiltin<"__builtin_lasx_xvfcvt_h_s">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcvt_s_d : ClangBuiltin<"__builtin_lasx_xvfcvt_s_d">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvffint_s_l : ClangBuiltin<"__builtin_lasx_xvffint_s_l">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftint_w_d : ClangBuiltin<"__builtin_lasx_xvftint_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrz_w_d : ClangBuiltin<"__builtin_lasx_xvftintrz_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrp_w_d : ClangBuiltin<"__builtin_lasx_xvftintrp_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrm_w_d : ClangBuiltin<"__builtin_lasx_xvftintrm_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrne_w_d : ClangBuiltin<"__builtin_lasx_xvftintrne_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbsrl_v : ClangBuiltin<"__builtin_lasx_xvbsrl_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbsll_v : ClangBuiltin<"__builtin_lasx_xvbsll_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrstpi_b : ClangBuiltin<"__builtin_lasx_xvfrstpi_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrstpi_h : ClangBuiltin<"__builtin_lasx_xvfrstpi_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvneg_b : ClangBuiltin<"__builtin_lasx_xvneg_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvneg_h : ClangBuiltin<"__builtin_lasx_xvneg_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvneg_w : ClangBuiltin<"__builtin_lasx_xvneg_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvneg_d : ClangBuiltin<"__builtin_lasx_xvneg_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmskgez_b : ClangBuiltin<"__builtin_lasx_xvmskgez_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmsknz_b : ClangBuiltin<"__builtin_lasx_xvmsknz_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrintrm_s : ClangBuiltin<"__builtin_lasx_xvfrintrm_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrintrm_d : ClangBuiltin<"__builtin_lasx_xvfrintrm_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrintrp_s : ClangBuiltin<"__builtin_lasx_xvfrintrp_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrintrp_d : ClangBuiltin<"__builtin_lasx_xvfrintrp_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrintrz_s : ClangBuiltin<"__builtin_lasx_xvfrintrz_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrintrz_d : ClangBuiltin<"__builtin_lasx_xvfrintrz_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrintrne_s : ClangBuiltin<"__builtin_lasx_xvfrintrne_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrintrne_d : ClangBuiltin<"__builtin_lasx_xvfrintrne_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvffinth_d_w : ClangBuiltin<"__builtin_lasx_xvffinth_d_w">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvffintl_d_w : ClangBuiltin<"__builtin_lasx_xvffintl_d_w">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrm_w_s : ClangBuiltin<"__builtin_lasx_xvftintrm_w_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrm_l_d : ClangBuiltin<"__builtin_lasx_xvftintrm_l_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrp_w_s : ClangBuiltin<"__builtin_lasx_xvftintrp_w_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrp_l_d : ClangBuiltin<"__builtin_lasx_xvftintrp_l_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrz_w_s : ClangBuiltin<"__builtin_lasx_xvftintrz_w_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrz_l_d : ClangBuiltin<"__builtin_lasx_xvftintrz_l_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrne_w_s : ClangBuiltin<"__builtin_lasx_xvftintrne_w_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrne_l_d : ClangBuiltin<"__builtin_lasx_xvftintrne_l_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftinth_l_s : ClangBuiltin<"__builtin_lasx_xvftinth_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintl_l_s : ClangBuiltin<"__builtin_lasx_xvftintl_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrmh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrmh_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrml_l_s : ClangBuiltin<"__builtin_lasx_xvftintrml_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrph_l_s : ClangBuiltin<"__builtin_lasx_xvftintrph_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrpl_l_s : ClangBuiltin<"__builtin_lasx_xvftintrpl_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrzh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrzh_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrzl_l_s : ClangBuiltin<"__builtin_lasx_xvftintrzl_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrneh_l_s : ClangBuiltin<"__builtin_lasx_xvftintrneh_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrnel_l_s : ClangBuiltin<"__builtin_lasx_xvftintrnel_l_s">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvexth_d_w : ClangBuiltin<"__builtin_lasx_xvexth_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_w_h : ClangBuiltin<"__builtin_lasx_xvexth_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_h_b : ClangBuiltin<"__builtin_lasx_xvexth_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvexth_q_d : ClangBuiltin<"__builtin_lasx_xvexth_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsllwil_d_w : ClangBuiltin<"__builtin_lasx_xvsllwil_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsllwil_w_h : ClangBuiltin<"__builtin_lasx_xvsllwil_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsllwil_h_b : ClangBuiltin<"__builtin_lasx_xvsllwil_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsllwil_du_wu : ClangBuiltin<"__builtin_lasx_xvsllwil_du_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsllwil_wu_hu : ClangBuiltin<"__builtin_lasx_xvsllwil_wu_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsllwil_hu_bu : ClangBuiltin<"__builtin_lasx_xvsllwil_hu_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitclri_b : ClangBuiltin<"__builtin_lasx_xvbitclri_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclri_h : ClangBuiltin<"__builtin_lasx_xvbitclri_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclri_w : ClangBuiltin<"__builtin_lasx_xvbitclri_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclri_d : ClangBuiltin<"__builtin_lasx_xvbitclri_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitseti_b : ClangBuiltin<"__builtin_lasx_xvbitseti_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitseti_h : ClangBuiltin<"__builtin_lasx_xvbitseti_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitseti_w : ClangBuiltin<"__builtin_lasx_xvbitseti_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitseti_d : ClangBuiltin<"__builtin_lasx_xvbitseti_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitrevi_b : ClangBuiltin<"__builtin_lasx_xvbitrevi_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrevi_h : ClangBuiltin<"__builtin_lasx_xvbitrevi_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrevi_w : ClangBuiltin<"__builtin_lasx_xvbitrevi_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrevi_d : ClangBuiltin<"__builtin_lasx_xvbitrevi_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlrni_b_h : ClangBuiltin<"__builtin_lasx_xvssrlrni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_h_w : ClangBuiltin<"__builtin_lasx_xvssrlrni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_w_d : ClangBuiltin<"__builtin_lasx_xvssrlrni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_d_q : ClangBuiltin<"__builtin_lasx_xvssrlrni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrani_b_h : ClangBuiltin<"__builtin_lasx_xvsrani_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrani_h_w : ClangBuiltin<"__builtin_lasx_xvsrani_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrani_w_d : ClangBuiltin<"__builtin_lasx_xvsrani_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrani_d_q : ClangBuiltin<"__builtin_lasx_xvsrani_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvextrins_b : ClangBuiltin<"__builtin_lasx_xvextrins_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvextrins_h : ClangBuiltin<"__builtin_lasx_xvextrins_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvextrins_w : ClangBuiltin<"__builtin_lasx_xvextrins_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvextrins_d : ClangBuiltin<"__builtin_lasx_xvextrins_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitseli_b : ClangBuiltin<"__builtin_lasx_xvbitseli_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvandi_b : ClangBuiltin<"__builtin_lasx_xvandi_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvori_b : ClangBuiltin<"__builtin_lasx_xvori_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvxori_b : ClangBuiltin<"__builtin_lasx_xvxori_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvnori_b : ClangBuiltin<"__builtin_lasx_xvnori_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvldi : ClangBuiltin<"__builtin_lasx_xvldi">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrepli_b : ClangBuiltin<"__builtin_lasx_xvrepli_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrepli_h : ClangBuiltin<"__builtin_lasx_xvrepli_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrepli_w : ClangBuiltin<"__builtin_lasx_xvrepli_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrepli_d : ClangBuiltin<"__builtin_lasx_xvrepli_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpermi_w : ClangBuiltin<"__builtin_lasx_xvpermi_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsadd_b : ClangBuiltin<"__builtin_lasx_xvsadd_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_h : ClangBuiltin<"__builtin_lasx_xvsadd_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_w : ClangBuiltin<"__builtin_lasx_xvsadd_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_d : ClangBuiltin<"__builtin_lasx_xvsadd_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssub_b : ClangBuiltin<"__builtin_lasx_xvssub_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_h : ClangBuiltin<"__builtin_lasx_xvssub_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_w : ClangBuiltin<"__builtin_lasx_xvssub_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_d : ClangBuiltin<"__builtin_lasx_xvssub_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsadd_bu : ClangBuiltin<"__builtin_lasx_xvsadd_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_hu : ClangBuiltin<"__builtin_lasx_xvsadd_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_wu : ClangBuiltin<"__builtin_lasx_xvsadd_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvsadd_du : ClangBuiltin<"__builtin_lasx_xvsadd_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssub_bu : ClangBuiltin<"__builtin_lasx_xvssub_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_hu : ClangBuiltin<"__builtin_lasx_xvssub_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_wu : ClangBuiltin<"__builtin_lasx_xvssub_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssub_du : ClangBuiltin<"__builtin_lasx_xvssub_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhaddw_h_b : ClangBuiltin<"__builtin_lasx_xvhaddw_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhaddw_w_h : ClangBuiltin<"__builtin_lasx_xvhaddw_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhaddw_d_w : ClangBuiltin<"__builtin_lasx_xvhaddw_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhsubw_h_b : ClangBuiltin<"__builtin_lasx_xvhsubw_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_w_h : ClangBuiltin<"__builtin_lasx_xvhsubw_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_d_w : ClangBuiltin<"__builtin_lasx_xvhsubw_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhaddw_hu_bu : ClangBuiltin<"__builtin_lasx_xvhaddw_hu_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhaddw_wu_hu : ClangBuiltin<"__builtin_lasx_xvhaddw_wu_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhaddw_du_wu : ClangBuiltin<"__builtin_lasx_xvhaddw_du_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvhsubw_hu_bu : ClangBuiltin<"__builtin_lasx_xvhsubw_hu_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_wu_hu : ClangBuiltin<"__builtin_lasx_xvhsubw_wu_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvhsubw_du_wu : ClangBuiltin<"__builtin_lasx_xvhsubw_du_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvadda_b : ClangBuiltin<"__builtin_lasx_xvadda_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadda_h : ClangBuiltin<"__builtin_lasx_xvadda_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadda_w : ClangBuiltin<"__builtin_lasx_xvadda_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadda_d : ClangBuiltin<"__builtin_lasx_xvadda_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvabsd_b : ClangBuiltin<"__builtin_lasx_xvabsd_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_h : ClangBuiltin<"__builtin_lasx_xvabsd_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_w : ClangBuiltin<"__builtin_lasx_xvabsd_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_d : ClangBuiltin<"__builtin_lasx_xvabsd_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvabsd_bu : ClangBuiltin<"__builtin_lasx_xvabsd_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_hu : ClangBuiltin<"__builtin_lasx_xvabsd_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_wu : ClangBuiltin<"__builtin_lasx_xvabsd_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvabsd_du : ClangBuiltin<"__builtin_lasx_xvabsd_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvavg_b : ClangBuiltin<"__builtin_lasx_xvavg_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_h : ClangBuiltin<"__builtin_lasx_xvavg_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_w : ClangBuiltin<"__builtin_lasx_xvavg_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_d : ClangBuiltin<"__builtin_lasx_xvavg_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvavg_bu : ClangBuiltin<"__builtin_lasx_xvavg_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_hu : ClangBuiltin<"__builtin_lasx_xvavg_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_wu : ClangBuiltin<"__builtin_lasx_xvavg_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavg_du : ClangBuiltin<"__builtin_lasx_xvavg_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvavgr_b : ClangBuiltin<"__builtin_lasx_xvavgr_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_h : ClangBuiltin<"__builtin_lasx_xvavgr_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_w : ClangBuiltin<"__builtin_lasx_xvavgr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_d : ClangBuiltin<"__builtin_lasx_xvavgr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvavgr_bu : ClangBuiltin<"__builtin_lasx_xvavgr_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_hu : ClangBuiltin<"__builtin_lasx_xvavgr_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_wu : ClangBuiltin<"__builtin_lasx_xvavgr_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvavgr_du : ClangBuiltin<"__builtin_lasx_xvavgr_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrlr_b : ClangBuiltin<"__builtin_lasx_xvsrlr_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlr_h : ClangBuiltin<"__builtin_lasx_xvsrlr_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlr_w : ClangBuiltin<"__builtin_lasx_xvsrlr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlr_d : ClangBuiltin<"__builtin_lasx_xvsrlr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrar_b : ClangBuiltin<"__builtin_lasx_xvsrar_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrar_h : ClangBuiltin<"__builtin_lasx_xvsrar_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrar_w : ClangBuiltin<"__builtin_lasx_xvsrar_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrar_d : ClangBuiltin<"__builtin_lasx_xvsrar_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmax_s : ClangBuiltin<"__builtin_lasx_xvfmax_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfmax_d : ClangBuiltin<"__builtin_lasx_xvfmax_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmin_s : ClangBuiltin<"__builtin_lasx_xvfmin_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfmin_d : ClangBuiltin<"__builtin_lasx_xvfmin_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmaxa_s : ClangBuiltin<"__builtin_lasx_xvfmaxa_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfmaxa_d : ClangBuiltin<"__builtin_lasx_xvfmaxa_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmina_s : ClangBuiltin<"__builtin_lasx_xvfmina_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfmina_d : ClangBuiltin<"__builtin_lasx_xvfmina_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfclass_s : ClangBuiltin<"__builtin_lasx_xvfclass_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfclass_d : ClangBuiltin<"__builtin_lasx_xvfclass_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrecip_s : ClangBuiltin<"__builtin_lasx_xvfrecip_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrecip_d : ClangBuiltin<"__builtin_lasx_xvfrecip_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrsqrt_s : ClangBuiltin<"__builtin_lasx_xvfrsqrt_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrsqrt_d : ClangBuiltin<"__builtin_lasx_xvfrsqrt_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcvtl_s_h : ClangBuiltin<"__builtin_lasx_xvfcvtl_s_h">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcvtl_d_s : ClangBuiltin<"__builtin_lasx_xvfcvtl_d_s">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfcvth_s_h : ClangBuiltin<"__builtin_lasx_xvfcvth_s_h">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfcvth_d_s : ClangBuiltin<"__builtin_lasx_xvfcvth_d_s">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftint_w_s : ClangBuiltin<"__builtin_lasx_xvftint_w_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftint_l_d : ClangBuiltin<"__builtin_lasx_xvftint_l_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftint_wu_s : ClangBuiltin<"__builtin_lasx_xvftint_wu_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftint_lu_d : ClangBuiltin<"__builtin_lasx_xvftint_lu_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrlri_b : ClangBuiltin<"__builtin_lasx_xvsrlri_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlri_h : ClangBuiltin<"__builtin_lasx_xvsrlri_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlri_w : ClangBuiltin<"__builtin_lasx_xvsrlri_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlri_d : ClangBuiltin<"__builtin_lasx_xvsrlri_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrari_b : ClangBuiltin<"__builtin_lasx_xvsrari_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrari_h : ClangBuiltin<"__builtin_lasx_xvsrari_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrari_w : ClangBuiltin<"__builtin_lasx_xvsrari_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrari_d : ClangBuiltin<"__builtin_lasx_xvsrari_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsat_b : ClangBuiltin<"__builtin_lasx_xvsat_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_h : ClangBuiltin<"__builtin_lasx_xvsat_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_w : ClangBuiltin<"__builtin_lasx_xvsat_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_d : ClangBuiltin<"__builtin_lasx_xvsat_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsat_bu : ClangBuiltin<"__builtin_lasx_xvsat_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_hu : ClangBuiltin<"__builtin_lasx_xvsat_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_wu : ClangBuiltin<"__builtin_lasx_xvsat_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsat_du : ClangBuiltin<"__builtin_lasx_xvsat_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrlni_b_h : ClangBuiltin<"__builtin_lasx_xvsrlni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlni_h_w : ClangBuiltin<"__builtin_lasx_xvsrlni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlni_w_d : ClangBuiltin<"__builtin_lasx_xvsrlni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlni_d_q : ClangBuiltin<"__builtin_lasx_xvsrlni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlni_b_h : ClangBuiltin<"__builtin_lasx_xvssrlni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_h_w : ClangBuiltin<"__builtin_lasx_xvssrlni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_w_d : ClangBuiltin<"__builtin_lasx_xvssrlni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_d_q : ClangBuiltin<"__builtin_lasx_xvssrlni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlrni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlrni_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlrni_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlrni_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlrni_du_q : ClangBuiltin<"__builtin_lasx_xvssrlrni_du_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrarni_b_h : ClangBuiltin<"__builtin_lasx_xvsrarni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrarni_h_w : ClangBuiltin<"__builtin_lasx_xvsrarni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrarni_w_d : ClangBuiltin<"__builtin_lasx_xvsrarni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrarni_d_q : ClangBuiltin<"__builtin_lasx_xvsrarni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrani_b_h : ClangBuiltin<"__builtin_lasx_xvssrani_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_h_w : ClangBuiltin<"__builtin_lasx_xvssrani_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_w_d : ClangBuiltin<"__builtin_lasx_xvssrani_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_d_q : ClangBuiltin<"__builtin_lasx_xvssrani_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrani_bu_h : ClangBuiltin<"__builtin_lasx_xvssrani_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_hu_w : ClangBuiltin<"__builtin_lasx_xvssrani_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_wu_d : ClangBuiltin<"__builtin_lasx_xvssrani_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrani_du_q : ClangBuiltin<"__builtin_lasx_xvssrani_du_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrarni_b_h : ClangBuiltin<"__builtin_lasx_xvssrarni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_h_w : ClangBuiltin<"__builtin_lasx_xvssrarni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_w_d : ClangBuiltin<"__builtin_lasx_xvssrarni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_d_q : ClangBuiltin<"__builtin_lasx_xvssrarni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrarni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrarni_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrarni_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrarni_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrarni_du_q : ClangBuiltin<"__builtin_lasx_xvssrarni_du_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvssrlni_bu_h : ClangBuiltin<"__builtin_lasx_xvssrlni_bu_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_hu_w : ClangBuiltin<"__builtin_lasx_xvssrlni_hu_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_wu_d : ClangBuiltin<"__builtin_lasx_xvssrlni_wu_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvssrlni_du_q : ClangBuiltin<"__builtin_lasx_xvssrlni_du_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvseq_b : ClangBuiltin<"__builtin_lasx_xvseq_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseq_h : ClangBuiltin<"__builtin_lasx_xvseq_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseq_w : ClangBuiltin<"__builtin_lasx_xvseq_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseq_d : ClangBuiltin<"__builtin_lasx_xvseq_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsle_b : ClangBuiltin<"__builtin_lasx_xvsle_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_h : ClangBuiltin<"__builtin_lasx_xvsle_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_w : ClangBuiltin<"__builtin_lasx_xvsle_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_d : ClangBuiltin<"__builtin_lasx_xvsle_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsle_bu : ClangBuiltin<"__builtin_lasx_xvsle_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_hu : ClangBuiltin<"__builtin_lasx_xvsle_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_wu : ClangBuiltin<"__builtin_lasx_xvsle_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsle_du : ClangBuiltin<"__builtin_lasx_xvsle_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslt_b : ClangBuiltin<"__builtin_lasx_xvslt_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_h : ClangBuiltin<"__builtin_lasx_xvslt_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_w : ClangBuiltin<"__builtin_lasx_xvslt_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_d : ClangBuiltin<"__builtin_lasx_xvslt_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslt_bu : ClangBuiltin<"__builtin_lasx_xvslt_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_hu : ClangBuiltin<"__builtin_lasx_xvslt_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_wu : ClangBuiltin<"__builtin_lasx_xvslt_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslt_du : ClangBuiltin<"__builtin_lasx_xvslt_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvadd_b : ClangBuiltin<"__builtin_lasx_xvadd_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadd_h : ClangBuiltin<"__builtin_lasx_xvadd_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadd_w : ClangBuiltin<"__builtin_lasx_xvadd_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvadd_d : ClangBuiltin<"__builtin_lasx_xvadd_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsub_b : ClangBuiltin<"__builtin_lasx_xvsub_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsub_h : ClangBuiltin<"__builtin_lasx_xvsub_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsub_w : ClangBuiltin<"__builtin_lasx_xvsub_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsub_d : ClangBuiltin<"__builtin_lasx_xvsub_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmax_b : ClangBuiltin<"__builtin_lasx_xvmax_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_h : ClangBuiltin<"__builtin_lasx_xvmax_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_w : ClangBuiltin<"__builtin_lasx_xvmax_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_d : ClangBuiltin<"__builtin_lasx_xvmax_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmin_b : ClangBuiltin<"__builtin_lasx_xvmin_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_h : ClangBuiltin<"__builtin_lasx_xvmin_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_w : ClangBuiltin<"__builtin_lasx_xvmin_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_d : ClangBuiltin<"__builtin_lasx_xvmin_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmax_bu : ClangBuiltin<"__builtin_lasx_xvmax_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_hu : ClangBuiltin<"__builtin_lasx_xvmax_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_wu : ClangBuiltin<"__builtin_lasx_xvmax_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmax_du : ClangBuiltin<"__builtin_lasx_xvmax_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmin_bu : ClangBuiltin<"__builtin_lasx_xvmin_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_hu : ClangBuiltin<"__builtin_lasx_xvmin_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_wu : ClangBuiltin<"__builtin_lasx_xvmin_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmin_du : ClangBuiltin<"__builtin_lasx_xvmin_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmul_b : ClangBuiltin<"__builtin_lasx_xvmul_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmul_h : ClangBuiltin<"__builtin_lasx_xvmul_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmul_w : ClangBuiltin<"__builtin_lasx_xvmul_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmul_d : ClangBuiltin<"__builtin_lasx_xvmul_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmadd_b : ClangBuiltin<"__builtin_lasx_xvmadd_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmadd_h : ClangBuiltin<"__builtin_lasx_xvmadd_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmadd_w : ClangBuiltin<"__builtin_lasx_xvmadd_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmadd_d : ClangBuiltin<"__builtin_lasx_xvmadd_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmsub_b : ClangBuiltin<"__builtin_lasx_xvmsub_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmsub_h : ClangBuiltin<"__builtin_lasx_xvmsub_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmsub_w : ClangBuiltin<"__builtin_lasx_xvmsub_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvmsub_d : ClangBuiltin<"__builtin_lasx_xvmsub_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvdiv_b : ClangBuiltin<"__builtin_lasx_xvdiv_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_h : ClangBuiltin<"__builtin_lasx_xvdiv_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_w : ClangBuiltin<"__builtin_lasx_xvdiv_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_d : ClangBuiltin<"__builtin_lasx_xvdiv_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmod_b : ClangBuiltin<"__builtin_lasx_xvmod_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_h : ClangBuiltin<"__builtin_lasx_xvmod_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_w : ClangBuiltin<"__builtin_lasx_xvmod_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_d : ClangBuiltin<"__builtin_lasx_xvmod_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvdiv_bu : ClangBuiltin<"__builtin_lasx_xvdiv_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_hu : ClangBuiltin<"__builtin_lasx_xvdiv_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_wu : ClangBuiltin<"__builtin_lasx_xvdiv_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvdiv_du : ClangBuiltin<"__builtin_lasx_xvdiv_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsll_b : ClangBuiltin<"__builtin_lasx_xvsll_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsll_h : ClangBuiltin<"__builtin_lasx_xvsll_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsll_w : ClangBuiltin<"__builtin_lasx_xvsll_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsll_d : ClangBuiltin<"__builtin_lasx_xvsll_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrl_b : ClangBuiltin<"__builtin_lasx_xvsrl_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrl_h : ClangBuiltin<"__builtin_lasx_xvsrl_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrl_w : ClangBuiltin<"__builtin_lasx_xvsrl_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrl_d : ClangBuiltin<"__builtin_lasx_xvsrl_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitclr_b : ClangBuiltin<"__builtin_lasx_xvbitclr_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclr_h : ClangBuiltin<"__builtin_lasx_xvbitclr_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclr_w : ClangBuiltin<"__builtin_lasx_xvbitclr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitclr_d : ClangBuiltin<"__builtin_lasx_xvbitclr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitset_b : ClangBuiltin<"__builtin_lasx_xvbitset_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitset_h : ClangBuiltin<"__builtin_lasx_xvbitset_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitset_w : ClangBuiltin<"__builtin_lasx_xvbitset_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitset_d : ClangBuiltin<"__builtin_lasx_xvbitset_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpackev_b : ClangBuiltin<"__builtin_lasx_xvpackev_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackev_h : ClangBuiltin<"__builtin_lasx_xvpackev_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackev_w : ClangBuiltin<"__builtin_lasx_xvpackev_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackev_d : ClangBuiltin<"__builtin_lasx_xvpackev_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpackod_b : ClangBuiltin<"__builtin_lasx_xvpackod_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackod_h : ClangBuiltin<"__builtin_lasx_xvpackod_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackod_w : ClangBuiltin<"__builtin_lasx_xvpackod_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpackod_d : ClangBuiltin<"__builtin_lasx_xvpackod_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvilvl_b : ClangBuiltin<"__builtin_lasx_xvilvl_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvl_h : ClangBuiltin<"__builtin_lasx_xvilvl_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvl_w : ClangBuiltin<"__builtin_lasx_xvilvl_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvl_d : ClangBuiltin<"__builtin_lasx_xvilvl_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvilvh_b : ClangBuiltin<"__builtin_lasx_xvilvh_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvh_h : ClangBuiltin<"__builtin_lasx_xvilvh_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvh_w : ClangBuiltin<"__builtin_lasx_xvilvh_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvilvh_d : ClangBuiltin<"__builtin_lasx_xvilvh_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickev_b : ClangBuiltin<"__builtin_lasx_xvpickev_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickev_h : ClangBuiltin<"__builtin_lasx_xvpickev_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickev_w : ClangBuiltin<"__builtin_lasx_xvpickev_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickev_d : ClangBuiltin<"__builtin_lasx_xvpickev_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvand_v : ClangBuiltin<"__builtin_lasx_xvand_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvor_v : ClangBuiltin<"__builtin_lasx_xvor_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvbitrev_b : ClangBuiltin<"__builtin_lasx_xvbitrev_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrev_h : ClangBuiltin<"__builtin_lasx_xvbitrev_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrev_w : ClangBuiltin<"__builtin_lasx_xvbitrev_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvbitrev_d : ClangBuiltin<"__builtin_lasx_xvbitrev_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmod_bu : ClangBuiltin<"__builtin_lasx_xvmod_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_hu : ClangBuiltin<"__builtin_lasx_xvmod_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_wu : ClangBuiltin<"__builtin_lasx_xvmod_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmod_du : ClangBuiltin<"__builtin_lasx_xvmod_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickod_b : ClangBuiltin<"__builtin_lasx_xvpickod_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickod_h : ClangBuiltin<"__builtin_lasx_xvpickod_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickod_w : ClangBuiltin<"__builtin_lasx_xvpickod_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickod_d : ClangBuiltin<"__builtin_lasx_xvpickod_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvreplve_b : ClangBuiltin<"__builtin_lasx_xvreplve_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve_h : ClangBuiltin<"__builtin_lasx_xvreplve_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve_w : ClangBuiltin<"__builtin_lasx_xvreplve_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve_d : ClangBuiltin<"__builtin_lasx_xvreplve_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsra_b : ClangBuiltin<"__builtin_lasx_xvsra_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsra_h : ClangBuiltin<"__builtin_lasx_xvsra_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsra_w : ClangBuiltin<"__builtin_lasx_xvsra_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsra_d : ClangBuiltin<"__builtin_lasx_xvsra_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvxor_v : ClangBuiltin<"__builtin_lasx_xvxor_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvnor_v : ClangBuiltin<"__builtin_lasx_xvnor_v">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfadd_s : ClangBuiltin<"__builtin_lasx_xvfadd_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfadd_d : ClangBuiltin<"__builtin_lasx_xvfadd_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfsub_s : ClangBuiltin<"__builtin_lasx_xvfsub_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfsub_d : ClangBuiltin<"__builtin_lasx_xvfsub_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfmul_s : ClangBuiltin<"__builtin_lasx_xvfmul_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfmul_d : ClangBuiltin<"__builtin_lasx_xvfmul_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvshuf_h : ClangBuiltin<"__builtin_lasx_xvshuf_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvshuf_w : ClangBuiltin<"__builtin_lasx_xvshuf_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvshuf_d : ClangBuiltin<"__builtin_lasx_xvshuf_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvseqi_b : ClangBuiltin<"__builtin_lasx_xvseqi_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseqi_h : ClangBuiltin<"__builtin_lasx_xvseqi_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseqi_w : ClangBuiltin<"__builtin_lasx_xvseqi_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvseqi_d : ClangBuiltin<"__builtin_lasx_xvseqi_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslei_b : ClangBuiltin<"__builtin_lasx_xvslei_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_h : ClangBuiltin<"__builtin_lasx_xvslei_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_w : ClangBuiltin<"__builtin_lasx_xvslei_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_d : ClangBuiltin<"__builtin_lasx_xvslei_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslei_bu : ClangBuiltin<"__builtin_lasx_xvslei_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_hu : ClangBuiltin<"__builtin_lasx_xvslei_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_wu : ClangBuiltin<"__builtin_lasx_xvslei_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslei_du : ClangBuiltin<"__builtin_lasx_xvslei_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslti_b : ClangBuiltin<"__builtin_lasx_xvslti_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_h : ClangBuiltin<"__builtin_lasx_xvslti_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_w : ClangBuiltin<"__builtin_lasx_xvslti_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_d : ClangBuiltin<"__builtin_lasx_xvslti_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslti_bu : ClangBuiltin<"__builtin_lasx_xvslti_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_hu : ClangBuiltin<"__builtin_lasx_xvslti_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_wu : ClangBuiltin<"__builtin_lasx_xvslti_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslti_du : ClangBuiltin<"__builtin_lasx_xvslti_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvaddi_bu : ClangBuiltin<"__builtin_lasx_xvaddi_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvaddi_hu : ClangBuiltin<"__builtin_lasx_xvaddi_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvaddi_wu : ClangBuiltin<"__builtin_lasx_xvaddi_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++def int_loongarch_lasx_xvaddi_du : ClangBuiltin<"__builtin_lasx_xvaddi_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], ++ [Commutative, IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsubi_bu : ClangBuiltin<"__builtin_lasx_xvsubi_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubi_hu : ClangBuiltin<"__builtin_lasx_xvsubi_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubi_wu : ClangBuiltin<"__builtin_lasx_xvsubi_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsubi_du : ClangBuiltin<"__builtin_lasx_xvsubi_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaxi_b : ClangBuiltin<"__builtin_lasx_xvmaxi_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_h : ClangBuiltin<"__builtin_lasx_xvmaxi_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_w : ClangBuiltin<"__builtin_lasx_xvmaxi_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_d : ClangBuiltin<"__builtin_lasx_xvmaxi_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmini_b : ClangBuiltin<"__builtin_lasx_xvmini_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_h : ClangBuiltin<"__builtin_lasx_xvmini_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_w : ClangBuiltin<"__builtin_lasx_xvmini_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_d : ClangBuiltin<"__builtin_lasx_xvmini_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmaxi_bu : ClangBuiltin<"__builtin_lasx_xvmaxi_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_hu : ClangBuiltin<"__builtin_lasx_xvmaxi_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_wu : ClangBuiltin<"__builtin_lasx_xvmaxi_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmaxi_du : ClangBuiltin<"__builtin_lasx_xvmaxi_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvmini_bu : ClangBuiltin<"__builtin_lasx_xvmini_bu">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_hu : ClangBuiltin<"__builtin_lasx_xvmini_hu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_wu : ClangBuiltin<"__builtin_lasx_xvmini_wu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvmini_du : ClangBuiltin<"__builtin_lasx_xvmini_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvclz_b : ClangBuiltin<"__builtin_lasx_xvclz_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclz_h : ClangBuiltin<"__builtin_lasx_xvclz_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclz_w : ClangBuiltin<"__builtin_lasx_xvclz_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvclz_d : ClangBuiltin<"__builtin_lasx_xvclz_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpcnt_b : ClangBuiltin<"__builtin_lasx_xvpcnt_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpcnt_h : ClangBuiltin<"__builtin_lasx_xvpcnt_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpcnt_w : ClangBuiltin<"__builtin_lasx_xvpcnt_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpcnt_d : ClangBuiltin<"__builtin_lasx_xvpcnt_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfsqrt_s : ClangBuiltin<"__builtin_lasx_xvfsqrt_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfsqrt_d : ClangBuiltin<"__builtin_lasx_xvfsqrt_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfrint_s : ClangBuiltin<"__builtin_lasx_xvfrint_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfrint_d : ClangBuiltin<"__builtin_lasx_xvfrint_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvffint_s_w : ClangBuiltin<"__builtin_lasx_xvffint_s_w">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvffint_d_l : ClangBuiltin<"__builtin_lasx_xvffint_d_l">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvffint_s_wu : ClangBuiltin<"__builtin_lasx_xvffint_s_wu">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvffint_d_lu : ClangBuiltin<"__builtin_lasx_xvffint_d_lu">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvftintrz_wu_s : ClangBuiltin<"__builtin_lasx_xvftintrz_wu_s">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvftintrz_lu_d : ClangBuiltin<"__builtin_lasx_xvftintrz_lu_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvreplgr2vr_b : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplgr2vr_h : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplgr2vr_w : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplgr2vr_d : ClangBuiltin<"__builtin_lasx_xvreplgr2vr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvinsgr2vr_w : ClangBuiltin<"__builtin_lasx_xvinsgr2vr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++def int_loongarch_lasx_xvinsgr2vr_d : ClangBuiltin<"__builtin_lasx_xvinsgr2vr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i64_ty, llvm_i32_ty], ++ [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvfdiv_s : ClangBuiltin<"__builtin_lasx_xvfdiv_s">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvfdiv_d : ClangBuiltin<"__builtin_lasx_xvfdiv_d">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvslli_b : ClangBuiltin<"__builtin_lasx_xvslli_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslli_h : ClangBuiltin<"__builtin_lasx_xvslli_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslli_w : ClangBuiltin<"__builtin_lasx_xvslli_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvslli_d : ClangBuiltin<"__builtin_lasx_xvslli_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrli_b : ClangBuiltin<"__builtin_lasx_xvsrli_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrli_h : ClangBuiltin<"__builtin_lasx_xvsrli_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrli_w : ClangBuiltin<"__builtin_lasx_xvsrli_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrli_d : ClangBuiltin<"__builtin_lasx_xvsrli_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrai_b : ClangBuiltin<"__builtin_lasx_xvsrai_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrai_h : ClangBuiltin<"__builtin_lasx_xvsrai_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrai_w : ClangBuiltin<"__builtin_lasx_xvsrai_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrai_d : ClangBuiltin<"__builtin_lasx_xvsrai_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvshuf4i_b : ClangBuiltin<"__builtin_lasx_xvshuf4i_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvshuf4i_h : ClangBuiltin<"__builtin_lasx_xvshuf4i_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvshuf4i_w : ClangBuiltin<"__builtin_lasx_xvshuf4i_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvshuf4i_d : ClangBuiltin<"__builtin_lasx_xvshuf4i_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrotr_b : ClangBuiltin<"__builtin_lasx_xvrotr_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotr_h : ClangBuiltin<"__builtin_lasx_xvrotr_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotr_w : ClangBuiltin<"__builtin_lasx_xvrotr_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotr_d : ClangBuiltin<"__builtin_lasx_xvrotr_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvrotri_b : ClangBuiltin<"__builtin_lasx_xvrotri_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotri_h : ClangBuiltin<"__builtin_lasx_xvrotri_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotri_w : ClangBuiltin<"__builtin_lasx_xvrotri_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrotri_d : ClangBuiltin<"__builtin_lasx_xvrotri_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvld : ClangBuiltin<"__builtin_lasx_xvld">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_i32_ty], ++ [IntrReadMem, IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvst : ClangBuiltin<"__builtin_lasx_xvst">, ++ Intrinsic<[], [llvm_v32i8_ty, llvm_ptr_ty, llvm_i32_ty], ++ [IntrArgMemOnly]>; ++ ++def int_loongarch_lasx_xvrepl128vei_b : ClangBuiltin<"__builtin_lasx_xvrepl128vei_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrepl128vei_h : ClangBuiltin<"__builtin_lasx_xvrepl128vei_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrepl128vei_w : ClangBuiltin<"__builtin_lasx_xvrepl128vei_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvrepl128vei_d : ClangBuiltin<"__builtin_lasx_xvrepl128vei_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvinsve0_w : ClangBuiltin<"__builtin_lasx_xvinsve0_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvinsve0_d : ClangBuiltin<"__builtin_lasx_xvinsve0_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickve_w : ClangBuiltin<"__builtin_lasx_xvpickve_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickve_d : ClangBuiltin<"__builtin_lasx_xvpickve_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpickve_w_f : ClangBuiltin<"__builtin_lasx_xvpickve_w_f">, ++ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpickve_d_f : ClangBuiltin<"__builtin_lasx_xvpickve_d_f">, ++ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvreplve0_b : ClangBuiltin<"__builtin_lasx_xvreplve0_b">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve0_h : ClangBuiltin<"__builtin_lasx_xvreplve0_h">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve0_w : ClangBuiltin<"__builtin_lasx_xvreplve0_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve0_d : ClangBuiltin<"__builtin_lasx_xvreplve0_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvreplve0_q : ClangBuiltin<"__builtin_lasx_xvreplve0_q">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_vext2xv_d_w : ClangBuiltin<"__builtin_lasx_vext2xv_d_w">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_w_h : ClangBuiltin<"__builtin_lasx_vext2xv_w_h">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_h_b : ClangBuiltin<"__builtin_lasx_vext2xv_h_b">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_vext2xv_d_h : ClangBuiltin<"__builtin_lasx_vext2xv_d_h">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_w_b : ClangBuiltin<"__builtin_lasx_vext2xv_w_b">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_d_b : ClangBuiltin<"__builtin_lasx_vext2xv_d_b">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_vext2xv_du_wu : ClangBuiltin<"__builtin_lasx_vext2xv_du_wu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_wu_hu : ClangBuiltin<"__builtin_lasx_vext2xv_wu_hu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_hu_bu : ClangBuiltin<"__builtin_lasx_vext2xv_hu_bu">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_vext2xv_du_hu : ClangBuiltin<"__builtin_lasx_vext2xv_du_hu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_wu_bu : ClangBuiltin<"__builtin_lasx_vext2xv_wu_bu">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_vext2xv_du_bu : ClangBuiltin<"__builtin_lasx_vext2xv_du_bu">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvpermi_q : ClangBuiltin<"__builtin_lasx_xvpermi_q">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvpermi_d : ClangBuiltin<"__builtin_lasx_xvpermi_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvperm_w : ClangBuiltin<"__builtin_lasx_xvperm_w">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvsrlrni_b_h : ClangBuiltin<"__builtin_lasx_xvsrlrni_b_h">, ++ Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlrni_h_w : ClangBuiltin<"__builtin_lasx_xvsrlrni_h_w">, ++ Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlrni_w_d : ClangBuiltin<"__builtin_lasx_xvsrlrni_w_d">, ++ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvsrlrni_d_q : ClangBuiltin<"__builtin_lasx_xvsrlrni_d_q">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xbz_v : ClangBuiltin<"__builtin_lasx_xbz_v">, ++ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xbnz_v : ClangBuiltin<"__builtin_lasx_xbnz_v">, ++ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xbz_b : ClangBuiltin<"__builtin_lasx_xbz_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbz_h : ClangBuiltin<"__builtin_lasx_xbz_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbz_w : ClangBuiltin<"__builtin_lasx_xbz_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbz_d : ClangBuiltin<"__builtin_lasx_xbz_d">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xbnz_b : ClangBuiltin<"__builtin_lasx_xbnz_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbnz_h : ClangBuiltin<"__builtin_lasx_xbnz_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_v16i16_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbnz_w : ClangBuiltin<"__builtin_lasx_xbnz_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xbnz_d : ClangBuiltin<"__builtin_lasx_xbnz_d">, ++ Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++def int_loongarch_lasx_xvextl_q_d : ClangBuiltin<"__builtin_lasx_xvextl_q_d">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++def int_loongarch_lasx_xvextl_qu_du : ClangBuiltin<"__builtin_lasx_xvextl_qu_du">, ++ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; ++ ++//===----------------------------------------------------------------------===// ++// LoongArch BASE ++ ++def int_loongarch_cpucfg : ClangBuiltin<"__builtin_loongarch_cpucfg">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_csrrd_w : ClangBuiltin<"__builtin_loongarch_csrrd_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_csrrd_d : ClangBuiltin<"__builtin_loongarch_csrrd_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_i64_ty], []>; ++ ++def int_loongarch_csrwr_w : ClangBuiltin<"__builtin_loongarch_csrwr_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_csrwr_d : ClangBuiltin<"__builtin_loongarch_csrwr_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], []>; ++ ++def int_loongarch_csrxchg_w : ClangBuiltin<"__builtin_loongarch_csrxchg_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_csrxchg_d : ClangBuiltin<"__builtin_loongarch_csrxchg_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], []>; ++ ++def int_loongarch_iocsrrd_b : ClangBuiltin<"__builtin_loongarch_iocsrrd_b">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrrd_h : ClangBuiltin<"__builtin_loongarch_iocsrrd_h">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrrd_w : ClangBuiltin<"__builtin_loongarch_iocsrrd_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrrd_d : ClangBuiltin<"__builtin_loongarch_iocsrrd_d">, ++ Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrwr_b : ClangBuiltin<"__builtin_loongarch_iocsrwr_b">, ++ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrwr_h : ClangBuiltin<"__builtin_loongarch_iocsrwr_h">, ++ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrwr_w : ClangBuiltin<"__builtin_loongarch_iocsrwr_w">, ++ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_iocsrwr_d : ClangBuiltin<"__builtin_loongarch_iocsrwr_d">, ++ Intrinsic<[], [llvm_i64_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_cacop_w : ClangBuiltin<"__builtin_loongarch_cacop_w">, ++ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_cacop_d : ClangBuiltin<"__builtin_loongarch_cacop_d">, ++ Intrinsic<[], [llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], []>; ++ ++def int_loongarch_crc_w_b_w : ClangBuiltin<"__builtin_loongarch_crc_w_b_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crc_w_h_w : ClangBuiltin<"__builtin_loongarch_crc_w_h_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crc_w_w_w : ClangBuiltin<"__builtin_loongarch_crc_w_w_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crc_w_d_w : ClangBuiltin<"__builtin_loongarch_crc_w_d_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crcc_w_b_w : ClangBuiltin<"__builtin_loongarch_crcc_w_b_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crcc_w_h_w : ClangBuiltin<"__builtin_loongarch_crcc_w_h_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crcc_w_w_w : ClangBuiltin<"__builtin_loongarch_crcc_w_w_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_crcc_w_d_w : ClangBuiltin<"__builtin_loongarch_crcc_w_d_w">, ++ Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; ++ ++def int_loongarch_tlbclr : ClangBuiltin<"__builtin_loongarch_tlbclr">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_tlbflush : ClangBuiltin<"__builtin_loongarch_tlbflush">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_tlbfill : ClangBuiltin<"__builtin_loongarch_tlbfill">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_tlbrd : ClangBuiltin<"__builtin_loongarch_tlbrd">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_tlbwr : ClangBuiltin<"__builtin_loongarch_tlbwr">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_tlbsrch : ClangBuiltin<"__builtin_loongarch_tlbsrch">, ++ Intrinsic<[], [], []>; ++ ++def int_loongarch_syscall : ClangBuiltin<"__builtin_loongarch_syscall">, ++ Intrinsic<[], [llvm_i64_ty], []>; ++ ++def int_loongarch_break : ClangBuiltin<"__builtin_loongarch_break">, ++ Intrinsic<[], [llvm_i64_ty], []>; ++ ++def int_loongarch_asrtle_d : ClangBuiltin<"__builtin_loongarch_asrtle_d">, ++ Intrinsic<[], [llvm_i64_ty, llvm_i64_ty], []>; ++ ++def int_loongarch_asrtgt_d : ClangBuiltin<"__builtin_loongarch_asrtgt_d">, ++ Intrinsic<[], [llvm_i64_ty, llvm_i64_ty], []>; ++ ++def int_loongarch_dbar : ClangBuiltin<"__builtin_loongarch_dbar">, ++ Intrinsic<[], [llvm_i64_ty], []>; ++ ++def int_loongarch_ibar : ClangBuiltin<"__builtin_loongarch_ibar">, ++ Intrinsic<[], [llvm_i64_ty], []>; ++ ++} +diff --git a/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp b/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp +index 2958a5054..c784c27d3 100644 +--- a/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp ++++ b/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp +@@ -5917,8 +5917,13 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { + if (const SCEV *S = createNodeFromSelectLikePHI(PN)) + return S; + ++ // If the PHI has a single incoming value, follow that value, unless the ++ // PHI's incoming blocks are in a different loop, in which case doing so ++ // risks breaking LCSSA form. Instcombine would normally zap these, but ++ // it doesn't have DominatorTree information, so it may miss cases. + if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC})) +- return getSCEV(V); ++ if (LI.replacementPreservesLCSSAForm(PN, V)) ++ return getSCEV(V); + + // If it's not a loop phi, we can't handle it yet. + return getUnknown(PN); +diff --git a/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp b/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp +index c4795a80e..bc20f33f1 100644 +--- a/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp ++++ b/src/llvm-project/llvm/lib/Analysis/VectorUtils.cpp +@@ -1110,6 +1110,12 @@ void InterleavedAccessInfo::collectConstStrideAccesses( + continue; + Type *ElementTy = getLoadStoreType(&I); + ++ // Currently, codegen doesn't support cases where the type size doesn't ++ // match the alloc size. Skip them for now. ++ uint64_t Size = DL.getTypeAllocSize(ElementTy); ++ if (Size * 8 != DL.getTypeSizeInBits(ElementTy)) ++ continue; ++ + // We don't check wrapping here because we don't know yet if Ptr will be + // part of a full group or a group with gaps. Checking wrapping for all + // pointers (even those that end up in groups with no gaps) will be overly +@@ -1121,7 +1127,6 @@ void InterleavedAccessInfo::collectConstStrideAccesses( + /*Assume=*/true, /*ShouldCheckWrap=*/false); + + const SCEV *Scev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); +- uint64_t Size = DL.getTypeAllocSize(ElementTy); + AccessStrideInfo[&I] = StrideDescriptor(Stride, Scev, Size, + getLoadStoreAlignment(&I)); + } +diff --git a/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp +index 85d051cfd..a8d40edd8 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/PrologEpilogInserter.cpp +@@ -1237,7 +1237,13 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) { + if (!MO.isReg()) + continue; + +- for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(MO.getReg())) ++ MCRegister Reg = MO.getReg(); ++ ++ // This picks up sibling registers (e.q. %al -> %ah). ++ for (MCRegUnitIterator Unit(Reg, &TRI); Unit.isValid(); ++Unit) ++ RegsToZero.reset(*Unit); ++ ++ for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(Reg)) + RegsToZero.reset(SReg); + } + } +diff --git a/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp b/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp +index 9e4e26f13..cb552f212 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/RegAllocFast.cpp +@@ -443,6 +443,9 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg, + SpilledOperandsMap[MO->getParent()].push_back(MO); + for (auto MISpilledOperands : SpilledOperandsMap) { + MachineInstr &DBG = *MISpilledOperands.first; ++ // We don't have enough support for tracking operands of DBG_VALUE_LISTs. ++ if (DBG.isDebugValueList()) ++ continue; + MachineInstr *NewDV = buildDbgValueForSpill( + *MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second); + assert(NewDV->getParent() == MBB && "dangling parent pointer"); +diff --git a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +index 3d3b504c6..96cfe1fc0 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +@@ -701,6 +701,9 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD, + MIB.addMetadata(Var); + MIB.addMetadata(Expr); + AddDbgValueLocationOps(MIB, DbgValDesc, LocationOps, VRBaseMap); ++ // FIXME: Fix rustc build error with lto=thin option on loongarch. ++ if (MF->getTarget().getTargetTriple().isLoongArch()) ++ return nullptr; + return &*MIB; + } + +diff --git a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +index 35650b9bd..ecdaef044 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@@ -9693,6 +9693,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { + Entry.Alignment = Alignment; + CLI.getArgs().insert(CLI.getArgs().begin(), Entry); + CLI.NumFixedArgs += 1; ++ CLI.getArgs()[0].IndirectType = CLI.RetTy; + CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext()); + + // sret demotion isn't compatible with tail-calls, since the sret argument +diff --git a/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +index 2badbe34a..88b8d1cf3 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +@@ -207,6 +207,16 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + PersonalityEncoding = dwarf::DW_EH_PE_absptr; + TTypeEncoding = dwarf::DW_EH_PE_absptr; + break; ++ case Triple::loongarch32: ++ case Triple::loongarch64: ++ PersonalityEncoding = dwarf::DW_EH_PE_indirect; ++ ++ // Note: gas does not support pc-relative LSDA references. ++ LSDAEncoding = dwarf::DW_EH_PE_absptr; ++ ++ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ++ dwarf::DW_EH_PE_sdata4; ++ break; + case Triple::mips: + case Triple::mipsel: + case Triple::mips64: +diff --git a/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp b/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp +index 8dc8d381a..36e3c1245 100644 +--- a/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp ++++ b/src/llvm-project/llvm/lib/CodeGen/TypePromotion.cpp +@@ -569,7 +569,7 @@ void IRPromoter::TruncateSinks() { + void IRPromoter::Cleanup() { + LLVM_DEBUG(dbgs() << "IR Promotion: Cleanup..\n"); + // Some zexts will now have become redundant, along with their trunc +- // operands, so remove them ++ // operands, so remove them. + for (auto *V : Visited) { + if (!isa(V)) + continue; +@@ -620,6 +620,8 @@ void IRPromoter::ConvertTruncs() { + ConstantInt *Mask = + ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue()); + Value *Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask); ++ if (SrcTy != ExtTy) ++ Masked = Builder.CreateTrunc(Masked, ExtTy); + + if (auto *I = dyn_cast(Masked)) + NewInsts.insert(I); +diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +index aec42d295..2be2a12aa 100644 +--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp ++++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +@@ -413,12 +413,12 @@ unsigned DWARFVerifier::verifyIndex(StringRef Name, + uint64_t Sig = E.getSignature(); + if (!E.getContributions()) + continue; +- for (auto P : enumerate(InfoColumnKind == DW_SECT_INFO ++ for (auto E : enumerate(InfoColumnKind == DW_SECT_INFO + ? makeArrayRef(E.getContributions(), + Index.getColumnKinds().size()) + : makeArrayRef(E.getContribution(), 1))) { +- const DWARFUnitIndex::Entry::SectionContribution &SC = P.value(); +- int Col = P.index(); ++ const DWARFUnitIndex::Entry::SectionContribution &SC = E.value(); ++ int Col = E.index(); + if (SC.Length == 0) + continue; + if (!Sections[Col]) +diff --git a/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp b/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp +index 75594f90c..b9962da1d 100644 +--- a/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp ++++ b/src/llvm-project/llvm/lib/IR/AutoUpgrade.cpp +@@ -1040,7 +1040,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { + Name, F->getParent()); + + // The new function may also need remangling. +- if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F)) ++ if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn)) + NewFn = *Result; + return true; + } +diff --git a/src/llvm-project/llvm/lib/IR/Function.cpp b/src/llvm-project/llvm/lib/IR/Function.cpp +index d41381337..3ef27601f 100644 +--- a/src/llvm-project/llvm/lib/IR/Function.cpp ++++ b/src/llvm-project/llvm/lib/IR/Function.cpp +@@ -38,6 +38,7 @@ + #include "llvm/IR/IntrinsicsBPF.h" + #include "llvm/IR/IntrinsicsDirectX.h" + #include "llvm/IR/IntrinsicsHexagon.h" ++#include "llvm/IR/IntrinsicsLoongArch.h" + #include "llvm/IR/IntrinsicsMips.h" + #include "llvm/IR/IntrinsicsNVPTX.h" + #include "llvm/IR/IntrinsicsPowerPC.h" +diff --git a/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp b/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp +index d6fe952c0..254c2fa60 100644 +--- a/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp ++++ b/src/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp +@@ -332,6 +332,12 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { + + void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { + switch (T.getArch()) { ++ case Triple::loongarch32: ++ case Triple::loongarch64: ++ FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4 ++ ? dwarf::DW_EH_PE_sdata4 ++ : dwarf::DW_EH_PE_sdata8; ++ break; + case Triple::mips: + case Triple::mipsel: + case Triple::mips64: +diff --git a/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp +index e14301663..ec54d7b59 100644 +--- a/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp ++++ b/src/llvm-project/llvm/lib/Object/RelocationResolver.cpp +@@ -511,6 +511,28 @@ static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S, + } + } + ++static bool supportsLoongArch(uint64_t Type) { ++ switch (Type) { ++ case ELF::R_LARCH_32: ++ case ELF::R_LARCH_64: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S, ++ uint64_t LocData, int64_t Addend) { ++ switch (Type) { ++ case ELF::R_LARCH_32: ++ return (S + Addend) & 0xFFFFFFFF; ++ case ELF::R_LARCH_64: ++ return S + Addend; ++ default: ++ llvm_unreachable("Invalid relocation type"); ++ } ++} ++ + static bool supportsCOFFX86(uint64_t Type) { + switch (Type) { + case COFF::IMAGE_REL_I386_SECREL: +@@ -725,6 +747,8 @@ getRelocationResolver(const ObjectFile &Obj) { + return {supportsAmdgpu, resolveAmdgpu}; + case Triple::riscv64: + return {supportsRISCV, resolveRISCV}; ++ case Triple::loongarch64: ++ return {supportsLoongArch, resolveLoongArch}; + default: + return {nullptr, nullptr}; + } +@@ -760,6 +784,8 @@ getRelocationResolver(const ObjectFile &Obj) { + return {supportsRISCV, resolveRISCV}; + case Triple::csky: + return {supportsCSKY, resolveCSKY}; ++ case Triple::loongarch32: ++ return {supportsLoongArch, resolveLoongArch}; + default: + return {nullptr, nullptr}; + } +diff --git a/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp b/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp +index 9ad2c4135..b778006cf 100644 +--- a/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp ++++ b/src/llvm-project/llvm/lib/ObjectYAML/ELFYAML.cpp +@@ -518,14 +518,6 @@ void ScalarBitSetTraits::bitset(IO &IO, + BCaseMask(EF_AVR_ARCH_XMEGA7, EF_AVR_ARCH_MASK); + BCase(EF_AVR_LINKRELAX_PREPARED); + break; +- case ELF::EM_LOONGARCH: +- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32S, EF_LOONGARCH_BASE_ABI_MASK); +- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32F, EF_LOONGARCH_BASE_ABI_MASK); +- BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32D, EF_LOONGARCH_BASE_ABI_MASK); +- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64S, EF_LOONGARCH_BASE_ABI_MASK); +- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64F, EF_LOONGARCH_BASE_ABI_MASK); +- BCaseMask(EF_LOONGARCH_BASE_ABI_LP64D, EF_LOONGARCH_BASE_ABI_MASK); +- break; + case ELF::EM_RISCV: + BCase(EF_RISCV_RVC); + BCaseMask(EF_RISCV_FLOAT_ABI_SOFT, EF_RISCV_FLOAT_ABI); +diff --git a/src/llvm-project/llvm/lib/Support/CMakeLists.txt b/src/llvm-project/llvm/lib/Support/CMakeLists.txt +index 5044b2639..ff23ec74d 100644 +--- a/src/llvm-project/llvm/lib/Support/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Support/CMakeLists.txt +@@ -22,11 +22,19 @@ if (HAS_WERROR_GLOBAL_CTORS) + endif() + + if(LLVM_ENABLE_ZLIB) +- set(imported_libs ZLIB::ZLIB) ++ list(APPEND imported_libs ZLIB::ZLIB) + endif() + + if(LLVM_ENABLE_ZSTD) +- list(APPEND imported_libs zstd::libzstd_shared) ++ if(TARGET zstd::libzstd_shared AND NOT LLVM_USE_STATIC_ZSTD) ++ set(zstd_target zstd::libzstd_shared) ++ else() ++ set(zstd_target zstd::libzstd_static) ++ endif() ++endif() ++ ++if(LLVM_ENABLE_ZSTD) ++ list(APPEND imported_libs ${zstd_target}) + endif() + + if( MSVC OR MINGW ) +@@ -51,9 +59,7 @@ elseif( CMAKE_HOST_UNIX ) + if( LLVM_ENABLE_TERMINFO ) + set(imported_libs ${imported_libs} Terminfo::terminfo) + endif() +- if( LLVM_ENABLE_THREADS AND (HAVE_LIBATOMIC OR HAVE_CXX_LIBATOMICS64) ) +- set(system_libs ${system_libs} atomic) +- endif() ++ set(system_libs ${system_libs} ${LLVM_ATOMIC_LIB}) + set(system_libs ${system_libs} ${LLVM_PTHREAD_LIB}) + if( UNIX AND NOT (BEOS OR HAIKU) ) + set(system_libs ${system_libs} m) +@@ -300,11 +306,12 @@ if(LLVM_ENABLE_ZSTD) + # CMAKE_BUILD_TYPE is only meaningful to single-configuration generators. + if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} build_type) +- get_property(zstd_library TARGET zstd::libzstd_shared PROPERTY LOCATION_${build_type}) ++ get_property(zstd_library TARGET ${zstd_target} PROPERTY LOCATION_${build_type}) + endif() + if(NOT zstd_library) +- get_property(zstd_library TARGET zstd::libzstd_shared PROPERTY LOCATION) ++ get_property(zstd_library TARGET ${zstd_target} PROPERTY LOCATION) + endif() ++ get_library_name(${zstd_library} zstd_library) + set(llvm_system_libs ${llvm_system_libs} "${zstd_library}") + endif() + +diff --git a/src/llvm-project/llvm/lib/Support/Triple.cpp b/src/llvm-project/llvm/lib/Support/Triple.cpp +index 6696d158b..2c07c1a29 100644 +--- a/src/llvm-project/llvm/lib/Support/Triple.cpp ++++ b/src/llvm-project/llvm/lib/Support/Triple.cpp +@@ -257,6 +257,7 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { + case GNU: return "gnu"; + case GNUABI64: return "gnuabi64"; + case GNUABIN32: return "gnuabin32"; ++ case GNUABILPX32: return "gnuabilpx32"; + case GNUEABI: return "gnueabi"; + case GNUEABIHF: return "gnueabihf"; + case GNUX32: return "gnux32"; +diff --git a/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp b/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp +index 194e8d88a..1e8aebf1b 100644 +--- a/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp ++++ b/src/llvm-project/llvm/lib/Support/UnicodeNameToCodepoint.cpp +@@ -499,8 +499,8 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { + // Filling (and overriding) the matrix for the name fragment of each node + // iteratively. CompleteName is used to collect the actual name of potential + // match, respecting case and spacing. +- std::function VisitNode; +- VisitNode = [&](const Node &N, std::size_t Row) -> void { ++ auto VisitNode = [&](const Node &N, std::size_t Row, ++ auto &VisitNode) -> void { + std::size_t J = 0; + for (; J < N.Name.size(); J++) { + if (!isAlnum(N.Name[J])) +@@ -533,7 +533,7 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { + ChildOffset += C.Size; + if (!C.isValid()) + break; +- VisitNode(C, Row); ++ VisitNode(C, Row, VisitNode); + if (!C.HasSibling) + break; + } +@@ -541,7 +541,7 @@ nearestMatchesForCodepointName(StringRef Pattern, std::size_t MaxMatchesCount) { + }; + + Node Root = createRoot(); +- VisitNode(Root, 1); ++ VisitNode(Root, 1, VisitNode); + return Matches; + } + +diff --git a/src/llvm-project/llvm/lib/Support/Unix/Path.inc b/src/llvm-project/llvm/lib/Support/Unix/Path.inc +index 6f85ee0db..2ae7c6dc4 100644 +--- a/src/llvm-project/llvm/lib/Support/Unix/Path.inc ++++ b/src/llvm-project/llvm/lib/Support/Unix/Path.inc +@@ -1476,7 +1476,7 @@ namespace fs { + std::error_code copy_file(const Twine &From, const Twine &To) { + std::string FromS = From.str(); + std::string ToS = To.str(); +-#if 0 && __has_builtin(__builtin_available) ++#if __has_builtin(__builtin_available) + if (__builtin_available(macos 10.12, *)) { + // Optimistically try to use clonefile() and handle errors, rather than + // calling stat() to see if it'll work. +diff --git a/src/llvm-project/llvm/lib/Support/Unix/Signals.inc b/src/llvm-project/llvm/lib/Support/Unix/Signals.inc +index bf145bffe..23ac012b9 100644 +--- a/src/llvm-project/llvm/lib/Support/Unix/Signals.inc ++++ b/src/llvm-project/llvm/lib/Support/Unix/Signals.inc +@@ -432,10 +432,6 @@ void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { + } + + void llvm::sys::DefaultOneShotPipeSignalHandler() { +- // UNIX03 conformance requires a non-zero exit code and an error message +- // to stderr when writing to a closed stdout fails. +- errs() << "error: write on a pipe with no reader\n"; +- + // Send a special return code that drivers can check for, from sysexits.h. + exit(EX_IOERR); + } +diff --git a/src/llvm-project/llvm/lib/Support/Windows/Threading.inc b/src/llvm-project/llvm/lib/Support/Windows/Threading.inc +index ed4b0d316..11f34817d 100644 +--- a/src/llvm-project/llvm/lib/Support/Windows/Threading.inc ++++ b/src/llvm-project/llvm/lib/Support/Windows/Threading.inc +@@ -144,11 +144,6 @@ struct ProcessorGroup { + + template + static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship, F Fn) { +-#if !defined(_WIN64) && defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 7 +- // `GetLogicalProcessorInformationEx@12` was only added to i386 mingw-w64 in v7.0.0 +- // https://github.com/mingw-w64/mingw-w64/commit/24842d45e025db0d38fa2bbd932b95a83282efa2#diff-faf1d8a1556e75a84b7cef2e89512e79R634 +- return false; +-#else + DWORD Len = 0; + BOOL R = ::GetLogicalProcessorInformationEx(Relationship, NULL, &Len); + if (R || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { +@@ -169,7 +164,6 @@ static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship, F Fn) { + } + free(Info); + return true; +-#endif + } + + static ArrayRef getProcessorGroups() { +diff --git a/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp b/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp +index 2567f3ed8..0daaa6d81 100644 +--- a/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp ++++ b/src/llvm-project/llvm/lib/Support/X86TargetParser.cpp +@@ -203,10 +203,10 @@ constexpr FeatureBitset FeaturesTigerlake = + FeatureCLWB | FeatureMOVDIRI | FeatureSHSTK | FeatureKL | FeatureWIDEKL; + constexpr FeatureBitset FeaturesSapphireRapids = + FeaturesICLServer | FeatureAMX_BF16 | FeatureAMX_INT8 | FeatureAMX_TILE | +- FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVX512VP2INTERSECT | +- FeatureAVXVNNI | FeatureCLDEMOTE | FeatureENQCMD | FeatureMOVDIR64B | +- FeatureMOVDIRI | FeaturePTWRITE | FeatureSERIALIZE | FeatureSHSTK | +- FeatureTSXLDTRK | FeatureUINTR | FeatureWAITPKG; ++ FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVXVNNI | FeatureCLDEMOTE | ++ FeatureENQCMD | FeatureMOVDIR64B | FeatureMOVDIRI | FeaturePTWRITE | ++ FeatureSERIALIZE | FeatureSHSTK | FeatureTSXLDTRK | FeatureUINTR | ++ FeatureWAITPKG; + + // Intel Atom processors. + // Bonnell has feature parity with Core2 and adds MOVBE. +@@ -367,7 +367,7 @@ constexpr ProcInfo Processors[] = { + // Tigerlake microarchitecture based processors. + { {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, FeaturesTigerlake }, + // Sapphire Rapids microarchitecture based processors. +- { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512VP2INTERSECT, FeaturesSapphireRapids }, ++ { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512BF16, FeaturesSapphireRapids }, + // Alderlake microarchitecture based processors. + { {"alderlake"}, CK_Alderlake, FEATURE_AVX2, FeaturesAlderlake }, + // Knights Landing processor. +diff --git a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +index c28216048..06e21f90e 100644 +--- a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp ++++ b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +@@ -5805,7 +5805,7 @@ SDValue AArch64TargetLowering::LowerFormalArguments( + assert(!Res && "Call operand has unhandled type"); + (void)Res; + } +- SmallVector ArgValues; ++ + unsigned ExtraArgLocs = 0; + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i - ExtraArgLocs]; +@@ -6157,17 +6157,10 @@ void AArch64TargetLowering::saveVarArgRegisters(CCState &CCInfo, + /// appropriate copies out of appropriate physical registers. + SDValue AArch64TargetLowering::LowerCallResult( + SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, +- const SmallVectorImpl &Ins, const SDLoc &DL, ++ const SmallVectorImpl &RVLocs, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals, bool isThisReturn, + SDValue ThisVal) const { +- CCAssignFn *RetCC = CCAssignFnForReturn(CallConv); +- // Assign locations to each value returned by this call. +- SmallVector RVLocs; + DenseMap CopiedRegs; +- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, +- *DAG.getContext()); +- CCInfo.AnalyzeCallResult(Ins, RetCC); +- + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign VA = RVLocs[i]; +@@ -6508,17 +6501,39 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, + GuardWithBTI = FuncInfo->branchTargetEnforcement(); + } + ++ // Analyze operands of the call, assigning locations to each operand. ++ SmallVector ArgLocs; ++ CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); ++ ++ if (IsVarArg) { ++ unsigned NumArgs = Outs.size(); ++ ++ for (unsigned i = 0; i != NumArgs; ++i) { ++ if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector()) ++ report_fatal_error("Passing SVE types to variadic functions is " ++ "currently not supported"); ++ } ++ } ++ ++ analyzeCallOperands(*this, Subtarget, CLI, CCInfo); ++ ++ CCAssignFn *RetCC = CCAssignFnForReturn(CallConv); ++ // Assign locations to each value returned by this call. ++ SmallVector RVLocs; ++ CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, ++ *DAG.getContext()); ++ RetCCInfo.AnalyzeCallResult(Ins, RetCC); ++ + // Check callee args/returns for SVE registers and set calling convention + // accordingly. + if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) { +- bool CalleeOutSVE = any_of(Outs, [](ISD::OutputArg &Out){ +- return Out.VT.isScalableVector(); +- }); +- bool CalleeInSVE = any_of(Ins, [](ISD::InputArg &In){ +- return In.VT.isScalableVector(); +- }); +- +- if (CalleeInSVE || CalleeOutSVE) ++ auto HasSVERegLoc = [](CCValAssign &Loc) { ++ if (!Loc.isRegLoc()) ++ return false; ++ return AArch64::ZPRRegClass.contains(Loc.getLocReg()) || ++ AArch64::PPRRegClass.contains(Loc.getLocReg()); ++ }; ++ if (any_of(RVLocs, HasSVERegLoc) || any_of(ArgLocs, HasSVERegLoc)) + CallConv = CallingConv::AArch64_SVE_VectorCall; + } + +@@ -6540,22 +6555,6 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); + +- // Analyze operands of the call, assigning locations to each operand. +- SmallVector ArgLocs; +- CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); +- +- if (IsVarArg) { +- unsigned NumArgs = Outs.size(); +- +- for (unsigned i = 0; i != NumArgs; ++i) { +- if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector()) +- report_fatal_error("Passing SVE types to variadic functions is " +- "currently not supported"); +- } +- } +- +- analyzeCallOperands(*this, Subtarget, CLI, CCInfo); +- + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + +@@ -6961,7 +6960,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, + + // Handle result values, copying them out of physregs into vregs that we + // return. +- return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, ++ return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, RVLocs, DL, DAG, + InVals, IsThisReturn, + IsThisReturn ? OutVals[0] : SDValue()); + } +diff --git a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h +index 1ba2e2f31..ff3bfe897 100644 +--- a/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h ++++ b/src/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.h +@@ -894,7 +894,7 @@ private: + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, +- const SmallVectorImpl &Ins, ++ const SmallVectorImpl &RVLocs, + const SDLoc &DL, SelectionDAG &DAG, + SmallVectorImpl &InVals, bool isThisReturn, + SDValue ThisVal) const; +diff --git a/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +index f7d139adc..f6b7d1ffc 100644 +--- a/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp ++++ b/src/llvm-project/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +@@ -249,6 +249,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, + case ISD::STORE: + case ISD::BUILD_VECTOR: + case ISD::BITCAST: ++ case ISD::UNDEF: + case ISD::EXTRACT_VECTOR_ELT: + case ISD::INSERT_VECTOR_ELT: + case ISD::EXTRACT_SUBVECTOR: +@@ -516,6 +517,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, + case ISD::STORE: + case ISD::BUILD_VECTOR: + case ISD::BITCAST: ++ case ISD::UNDEF: + case ISD::EXTRACT_VECTOR_ELT: + case ISD::INSERT_VECTOR_ELT: + case ISD::INSERT_SUBVECTOR: +diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp +index 3c102463b..cbfd2bc68 100644 +--- a/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp ++++ b/src/llvm-project/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp +@@ -1036,7 +1036,7 @@ InstructionCost ARMTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + // split, we may need an expensive shuffle to get two in sync. This has the + // effect of making larger than legal compares (v8i32 for example) + // expensive. +- if (LT.second.getVectorNumElements() > 2) { ++ if (LT.second.isVector() && LT.second.getVectorNumElements() > 2) { + if (LT.first > 1) + return LT.first * BaseCost + + BaseT::getScalarizationOverhead(VecCondTy, true, false); +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt +index 296160531..cb8b768d5 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt +@@ -2,10 +2,10 @@ add_llvm_component_library(LLVMLoongArchAsmParser + LoongArchAsmParser.cpp + + LINK_COMPONENTS +- LoongArchDesc +- LoongArchInfo + MC + MCParser ++ LoongArchDesc ++ LoongArchInfo + Support + + ADD_TO_COMPONENT +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +index 9793c7bc3..2d35dfd0c 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +@@ -1,4 +1,4 @@ +-// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=// ++//===-- LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions ----===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,551 +6,2278 @@ + // + //===----------------------------------------------------------------------===// + +-#include "MCTargetDesc/LoongArchInstPrinter.h" ++#include "LoongArchTargetStreamer.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" + #include "TargetInfo/LoongArchTargetInfo.h" ++#include "llvm/ADT/APFloat.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/ADT/SmallVector.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/ADT/Triple.h" ++#include "llvm/ADT/Twine.h" ++#include "llvm/BinaryFormat/ELF.h" + #include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCInstrDesc.h" + #include "llvm/MC/MCInstrInfo.h" ++#include "llvm/MC/MCObjectFileInfo.h" + #include "llvm/MC/MCParser/MCAsmLexer.h" ++#include "llvm/MC/MCParser/MCAsmParser.h" ++#include "llvm/MC/MCParser/MCAsmParserExtension.h" + #include "llvm/MC/MCParser/MCParsedAsmOperand.h" + #include "llvm/MC/MCParser/MCTargetAsmParser.h" +-#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/MC/MCSectionELF.h" + #include "llvm/MC/MCStreamer.h" + #include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCSymbol.h" ++#include "llvm/MC/MCSymbolELF.h" ++#include "llvm/MC/MCValue.h" ++#include "llvm/MC/SubtargetFeature.h" + #include "llvm/MC/TargetRegistry.h" + #include "llvm/Support/Casting.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Support/Compiler.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Support/SMLoc.h" ++#include "llvm/Support/SourceMgr.h" ++#include "llvm/Support/raw_ostream.h" ++#include ++#include ++#include ++#include ++#include ++#include + + using namespace llvm; + + #define DEBUG_TYPE "loongarch-asm-parser" + ++namespace llvm { ++ ++class MCInstrInfo; ++ ++} // end namespace llvm ++ ++namespace { ++ ++class LoongArchAssemblerOptions { ++public: ++ LoongArchAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {} ++ ++ LoongArchAssemblerOptions(const LoongArchAssemblerOptions *Opts) { ++ Features = Opts->getFeatures(); ++ } ++ ++ const FeatureBitset &getFeatures() const { return Features; } ++ void setFeatures(const FeatureBitset &Features_) { Features = Features_; } ++ ++private: ++ FeatureBitset Features; ++}; ++ ++} // end anonymous namespace ++ + namespace { ++ + class LoongArchAsmParser : public MCTargetAsmParser { +- SMLoc getLoc() const { return getParser().getTok().getLoc(); } ++ LoongArchTargetStreamer &getTargetStreamer() { ++ MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); ++ return static_cast(TS); ++ } ++ ++ LoongArchABIInfo ABI; ++ SmallVector, 2> AssemblerOptions; ++ MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a ++ // nullptr, which indicates that no function is currently ++ // selected. This usually happens after an '.end' ++ // directive. ++ bool IsPicEnabled; + +- /// Parse a register as used in CFI directives. ++ // Map of register aliases created via the .set directive. ++ StringMap RegisterSets; ++ ++#define GET_ASSEMBLER_HEADER ++#include "LoongArchGenAsmMatcher.inc" ++ ++ unsigned checkTargetMatchPredicate(MCInst &Inst) override; ++ ++ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ OperandVector &Operands, MCStreamer &Out, ++ uint64_t &ErrorInfo, ++ bool MatchingInlineAsm) override; ++ ++ /// Parse a register as used in CFI directives + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; + ++ bool mnemonicIsValid(StringRef Mnemonic); ++ + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) override; + +- bool ParseDirective(AsmToken DirectiveID) override { return true; } ++ bool ParseDirective(AsmToken DirectiveID) override; ++ ++ OperandMatchResultTy parseMemOperand(OperandVector &Operands); ++ OperandMatchResultTy parseAMemOperand(OperandVector &Operands); ++ OperandMatchResultTy ++ matchAnyRegisterNameWithoutDollar(OperandVector &Operands, ++ StringRef Identifier, SMLoc S); ++ OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, ++ const AsmToken &Token, ++ SMLoc S); ++ OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, ++ SMLoc S); ++ OperandMatchResultTy parseAnyRegister(OperandVector &Operands); ++ OperandMatchResultTy parseJumpTarget(OperandVector &Operands); ++ ++ bool searchSymbolAlias(OperandVector &Operands); ++ ++ bool parseOperand(OperandVector &, StringRef Mnemonic); ++ ++ enum MacroExpanderResultTy { ++ MER_NotAMacro, ++ MER_Success, ++ MER_Fail, ++ }; + +- bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, +- OperandVector &Operands, MCStreamer &Out, +- uint64_t &ErrorInfo, +- bool MatchingInlineAsm) override; ++ // Expands assembly pseudo instructions. ++ MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, ++ MCStreamer &Out, ++ const MCSubtargetInfo *STI); + +- unsigned checkTargetMatchPredicate(MCInst &Inst) override; ++ bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, ++ const MCSubtargetInfo *STI); + +- unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, +- unsigned Kind) override; ++ bool expandLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, ++ const MCSubtargetInfo *STI); + +- bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, +- int64_t Lower, int64_t Upper, Twine Msg); ++ bool reportParseError(Twine ErrorMsg); + +- /// Helper for processing MC instructions that have been successfully matched +- /// by MatchAndEmitInstruction. +- bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, +- MCStreamer &Out); ++ bool parseMemOffset(const MCExpr *&Res); + +-// Auto-generated instruction matching functions. +-#define GET_ASSEMBLER_HEADER +-#include "LoongArchGenAsmMatcher.inc" ++ bool isEvaluated(const MCExpr *Expr); ++ bool parseDirectiveSet(); ++ ++ bool parseSetAssignment(); ++ ++ bool parseInternalDirectiveReallowModule(); ++ ++ int matchCPURegisterName(StringRef Symbol); ++ ++ int matchFPURegisterName(StringRef Name); ++ ++ int matchFCFRRegisterName(StringRef Name); ++ int matchFCSRRegisterName(StringRef Name); ++ ++ int matchLSX128RegisterName(StringRef Name); ++ ++ int matchLASX256RegisterName(StringRef Name); ++ ++ bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, ++ const MCSubtargetInfo *STI); ++ ++ // Helper function that checks if the value of a vector index is within the ++ // boundaries of accepted values for each RegisterKind ++ // Example: VINSGR2VR.B $v0[n], $1 => 16 > n >= 0 ++ bool validateLSXIndex(int Val, int RegKind); ++ ++ void setFeatureBits(uint64_t Feature, StringRef FeatureString) { ++ if (!(getSTI().getFeatureBits()[Feature])) { ++ MCSubtargetInfo &STI = copySTI(); ++ setAvailableFeatures( ++ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); ++ AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); ++ } ++ } + +- OperandMatchResultTy parseRegister(OperandVector &Operands); +- OperandMatchResultTy parseImmediate(OperandVector &Operands); ++ void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { ++ if (getSTI().getFeatureBits()[Feature]) { ++ MCSubtargetInfo &STI = copySTI(); ++ setAvailableFeatures( ++ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); ++ AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); ++ } ++ } ++ ++ void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { ++ setFeatureBits(Feature, FeatureString); ++ AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); ++ } + +- bool parseOperand(OperandVector &Operands, StringRef Mnemonic); ++ void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { ++ clearFeatureBits(Feature, FeatureString); ++ AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); ++ } + + public: + enum LoongArchMatchResultTy { +- Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, +- Match_RequiresMsbNotLessThanLsb, +- Match_RequiresOpnd2NotR0R1, ++ Match_RequiresNoZeroRegister = FIRST_TARGET_MATCH_RESULT_TY, ++ Match_RequiresNoRaRegister, ++ Match_RequiresRange0_31, ++ Match_RequiresRange0_63, ++ Match_MsbHigherThanLsb, ++ Match_RequiresPosSizeUImm6, + #define GET_OPERAND_DIAGNOSTIC_TYPES + #include "LoongArchGenAsmMatcher.inc" + #undef GET_OPERAND_DIAGNOSTIC_TYPES + }; + +- LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, ++ LoongArchAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) +- : MCTargetAsmParser(Options, STI, MII) { +- Parser.addAliasForDirective(".half", ".2byte"); +- Parser.addAliasForDirective(".hword", ".2byte"); +- Parser.addAliasForDirective(".word", ".4byte"); +- Parser.addAliasForDirective(".dword", ".8byte"); ++ : MCTargetAsmParser(Options, sti, MII), ++ ABI(LoongArchABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), ++ sti.getCPU(), Options)) { ++ MCAsmParserExtension::Initialize(parser); ++ ++ parser.addAliasForDirective(".asciiz", ".asciz"); ++ parser.addAliasForDirective(".hword", ".2byte"); ++ parser.addAliasForDirective(".word", ".4byte"); ++ parser.addAliasForDirective(".dword", ".8byte"); + + // Initialize the set of available features. +- setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); ++ setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); ++ ++ // Remember the initial assembler options. The user can not modify these. ++ AssemblerOptions.push_back( ++ std::make_unique(getSTI().getFeatureBits())); ++ ++ // Create an assembler options environment for the user to modify. ++ AssemblerOptions.push_back( ++ std::make_unique(getSTI().getFeatureBits())); ++ ++ getTargetStreamer().updateABIInfo(*this); ++ ++ CurrentFn = nullptr; ++ ++ IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); ++ } ++ ++ bool is64Bit() const { ++ return getSTI().getFeatureBits()[LoongArch::Feature64Bit]; ++ } ++ ++ bool isFP64bit() const { ++ return getSTI().getFeatureBits()[LoongArch::FeatureFP64Bit]; ++ } ++ ++ const LoongArchABIInfo &getABI() const { return ABI; } ++ bool isABI_LPX32() const { return ABI.IsLPX32(); } ++ bool isABI_LP64() const { return ABI.IsLP64(); } ++ bool isABI_LP32() const { return ABI.IsLP32(); } ++ ++ bool hasLSX() const { ++ return getSTI().getFeatureBits()[LoongArch::FeatureLSX]; ++ } ++ ++ bool hasLASX() const { ++ return getSTI().getFeatureBits()[LoongArch::FeatureLASX]; ++ } ++ ++ bool inPicMode() { ++ return IsPicEnabled; ++ } ++ ++ bool useSoftFloat() const { ++ return getSTI().getFeatureBits()[LoongArch::FeatureSoftFloat]; ++ } ++ ++ const MCExpr *createTargetUnaryExpr(const MCExpr *E, ++ AsmToken::TokenKind OperatorToken, ++ MCContext &Ctx) override { ++ switch(OperatorToken) { ++ default: ++ llvm_unreachable("Unknown token"); ++ return nullptr; ++#if 0 ++ case AsmToken::PercentPlt: ++ return LoongArchMCExpr::create(LoongArchMCExpr::MEK_PLT, E, Ctx); ++#endif ++ } + } + }; + +-// Instances of this class represent a parsed LoongArch machine instruction. ++/// LoongArchOperand - Instances of this class represent a parsed LoongArch machine ++/// instruction. + class LoongArchOperand : public MCParsedAsmOperand { +- enum class KindTy { +- Token, +- Register, +- Immediate, ++public: ++ /// Broad categories of register classes ++ /// The exact class is finalized by the render method. ++ enum RegKind { ++ RegKind_GPR = 1, /// GPR32 and GPR64 (depending on is64Bit()) ++ RegKind_FGR = 2, /// FGR32, FGR64 (depending on isFP64bit()) ++ RegKind_FCFR = 4, /// FCFR ++ RegKind_FCSR = 8, /// FCSR ++ RegKind_LSX128 = 16, /// LSX128[BHWD] (makes no difference which) ++ RegKind_LASX256 = 32, /// LASX256[BHWD] (makes no difference which) ++ RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCFR | RegKind_FCSR | ++ RegKind_LSX128 | RegKind_LASX256 ++ }; ++ ++private: ++ enum KindTy { ++ k_Immediate, /// An immediate (possibly involving symbol references) ++ k_Memory, /// Base + Offset Memory Address ++ k_RegisterIndex, /// A register index in one or more RegKind. ++ k_Token, /// A simple token ++ k_RegList, /// A physical register list + } Kind; + +- struct RegOp { +- MCRegister RegNum; ++public: ++ LoongArchOperand(KindTy K, LoongArchAsmParser &Parser) ++ : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} ++ ++ ~LoongArchOperand() override { ++ switch (Kind) { ++ case k_Memory: ++ delete Mem.Base; ++ break; ++ case k_RegList: ++ delete RegList.List; ++ break; ++ case k_Immediate: ++ case k_RegisterIndex: ++ case k_Token: ++ break; ++ } ++ } ++ ++private: ++ /// For diagnostics, and checking the assembler temporary ++ LoongArchAsmParser &AsmParser; ++ ++ struct Token { ++ const char *Data; ++ unsigned Length; ++ }; ++ ++ struct RegIdxOp { ++ unsigned Index; /// Index into the register class ++ RegKind Kind; /// Bitfield of the kinds it could possibly be ++ struct Token Tok; /// The input token this operand originated from. ++ const MCRegisterInfo *RegInfo; + }; + + struct ImmOp { + const MCExpr *Val; + }; + +- SMLoc StartLoc, EndLoc; +- union { +- StringRef Tok; +- struct RegOp Reg; +- struct ImmOp Imm; ++ struct MemOp { ++ LoongArchOperand *Base; ++ const MCExpr *Off; + }; + +-public: +- LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} ++ struct RegListOp { ++ SmallVector *List; ++ }; + +- bool isToken() const override { return Kind == KindTy::Token; } +- bool isReg() const override { return Kind == KindTy::Register; } +- bool isImm() const override { return Kind == KindTy::Immediate; } +- bool isMem() const override { return false; } +- void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } ++ union { ++ struct Token Tok; ++ struct RegIdxOp RegIdx; ++ struct ImmOp Imm; ++ struct MemOp Mem; ++ struct RegListOp RegList; ++ }; + +- static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) { +- if (auto CE = dyn_cast(Expr)) { +- Imm = CE->getValue(); +- return true; +- } ++ SMLoc StartLoc, EndLoc; + +- return false; ++ /// Internal constructor for register kinds ++ static std::unique_ptr CreateReg(unsigned Index, StringRef Str, ++ RegKind RegKind, ++ const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, ++ LoongArchAsmParser &Parser) { ++ auto Op = std::make_unique(k_RegisterIndex, Parser); ++ Op->RegIdx.Index = Index; ++ Op->RegIdx.RegInfo = RegInfo; ++ Op->RegIdx.Kind = RegKind; ++ Op->RegIdx.Tok.Data = Str.data(); ++ Op->RegIdx.Tok.Length = Str.size(); ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; + } + +- template bool isUImm() const { +- if (!isImm()) +- return false; +- +- int64_t Imm; +- bool IsConstantImm = evaluateConstantImm(getImm(), Imm); +- return IsConstantImm && isUInt(Imm - P); ++public: ++ /// Coerce the register to GPR32 and return the real register for the current ++ /// target. ++ unsigned getGPR32Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); ++ unsigned ClassID = LoongArch::GPR32RegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + +- template bool isSImm() const { +- if (!isImm()) +- return false; +- +- int64_t Imm; +- bool IsConstantImm = evaluateConstantImm(getImm(), Imm); +- return IsConstantImm && isShiftedInt(Imm); +- } +- +- bool isUImm2() const { return isUImm<2>(); } +- bool isUImm2plus1() const { return isUImm<2, 1>(); } +- bool isUImm3() const { return isUImm<3>(); } +- bool isUImm5() const { return isUImm<5>(); } +- bool isUImm6() const { return isUImm<6>(); } +- bool isUImm8() const { return isUImm<8>(); } +- bool isUImm12() const { return isUImm<12>(); } +- bool isUImm14() const { return isUImm<14>(); } +- bool isUImm15() const { return isUImm<15>(); } +- bool isSImm12() const { return isSImm<12>(); } +- bool isSImm14lsl2() const { return isSImm<14, 2>(); } +- bool isSImm16() const { return isSImm<16>(); } +- bool isSImm16lsl2() const { return isSImm<16, 2>(); } +- bool isSImm20() const { return isSImm<20>(); } +- bool isSImm21lsl2() const { return isSImm<21, 2>(); } +- bool isSImm26lsl2() const { return isSImm<26, 2>(); } +- +- /// Gets location of the first token of this operand. +- SMLoc getStartLoc() const override { return StartLoc; } +- /// Gets location of the last token of this operand. +- SMLoc getEndLoc() const override { return EndLoc; } +- +- unsigned getReg() const override { +- assert(Kind == KindTy::Register && "Invalid type access!"); +- return Reg.RegNum.id(); ++ /// Coerce the register to GPR32 and return the real register for the current ++ /// target. ++ unsigned getGPRMM16Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); ++ unsigned ClassID = LoongArch::GPR32RegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + +- const MCExpr *getImm() const { +- assert(Kind == KindTy::Immediate && "Invalid type access!"); +- return Imm.Val; ++ /// Coerce the register to GPR64 and return the real register for the current ++ /// target. ++ unsigned getGPR64Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); ++ unsigned ClassID = LoongArch::GPR64RegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + +- StringRef getToken() const { +- assert(Kind == KindTy::Token && "Invalid type access!"); +- return Tok; ++private: ++ /// Coerce the register to FGR64 and return the real register for the current ++ /// target. ++ unsigned getFGR64Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); ++ return RegIdx.RegInfo->getRegClass(LoongArch::FGR64RegClassID) ++ .getRegister(RegIdx.Index); + } + +- void print(raw_ostream &OS) const override { +- auto RegName = [](unsigned Reg) { +- if (Reg) +- return LoongArchInstPrinter::getRegisterName(Reg); +- else +- return "noreg"; +- }; ++ /// Coerce the register to FGR32 and return the real register for the current ++ /// target. ++ unsigned getFGR32Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); ++ return RegIdx.RegInfo->getRegClass(LoongArch::FGR32RegClassID) ++ .getRegister(RegIdx.Index); ++ } + +- switch (Kind) { +- case KindTy::Immediate: +- OS << *getImm(); +- break; +- case KindTy::Register: +- OS << ""; +- break; +- case KindTy::Token: +- OS << "'" << getToken() << "'"; +- break; +- } ++ /// Coerce the register to FCFR and return the real register for the current ++ /// target. ++ unsigned getFCFRReg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCFR) && "Invalid access!"); ++ return RegIdx.RegInfo->getRegClass(LoongArch::FCFRRegClassID) ++ .getRegister(RegIdx.Index); + } + +- static std::unique_ptr createToken(StringRef Str, SMLoc S) { +- auto Op = std::make_unique(KindTy::Token); +- Op->Tok = Str; +- Op->StartLoc = S; +- Op->EndLoc = S; +- return Op; ++ /// Coerce the register to LSX128 and return the real register for the current ++ /// target. ++ unsigned getLSX128Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_LSX128) && "Invalid access!"); ++ // It doesn't matter which of the LSX128[BHWD] classes we use. They are all ++ // identical ++ unsigned ClassID = LoongArch::LSX128BRegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + +- static std::unique_ptr createReg(unsigned RegNo, SMLoc S, +- SMLoc E) { +- auto Op = std::make_unique(KindTy::Register); +- Op->Reg.RegNum = RegNo; +- Op->StartLoc = S; +- Op->EndLoc = E; +- return Op; ++ unsigned getLASX256Reg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_LASX256) && "Invalid access!"); ++ unsigned ClassID = LoongArch::LASX256BRegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + +- static std::unique_ptr createImm(const MCExpr *Val, SMLoc S, +- SMLoc E) { +- auto Op = std::make_unique(KindTy::Immediate); +- Op->Imm.Val = Val; +- Op->StartLoc = S; +- Op->EndLoc = E; +- return Op; ++ /// Coerce the register to CCR and return the real register for the ++ /// current target. ++ unsigned getFCSRReg() const { ++ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCSR) && "Invalid access!"); ++ unsigned ClassID = LoongArch::FCSRRegClassID; ++ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + ++public: + void addExpr(MCInst &Inst, const MCExpr *Expr) const { +- if (auto CE = dyn_cast(Expr)) ++ // Add as immediate when possible. Null MCExpr = 0. ++ if (!Expr) ++ Inst.addOperand(MCOperand::createImm(0)); ++ else if (const MCConstantExpr *CE = dyn_cast(Expr)) + Inst.addOperand(MCOperand::createImm(CE->getValue())); + else + Inst.addOperand(MCOperand::createExpr(Expr)); + } + +- // Used by the TableGen Code. + void addRegOperands(MCInst &Inst, unsigned N) const { +- assert(N == 1 && "Invalid number of operands!"); +- Inst.addOperand(MCOperand::createReg(getReg())); ++ llvm_unreachable("Use a custom parser instead"); + } +- void addImmOperands(MCInst &Inst, unsigned N) const { ++ ++ /// Render the operand to an MCInst as a GPR32 ++ /// Asserts if the wrong number of operands are requested, or the operand ++ /// is not a k_RegisterIndex compatible with RegKind_GPR ++ void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); +- addExpr(Inst, getImm()); ++ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); + } +-}; +-} // end namespace + +-#define GET_REGISTER_MATCHER +-#define GET_SUBTARGET_FEATURE_NAME +-#define GET_MATCHER_IMPLEMENTATION +-#define GET_MNEMONIC_SPELL_CHECKER +-#include "LoongArchGenAsmMatcher.inc" ++ void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); ++ } + +-static MCRegister convertFPR32ToFPR64(MCRegister Reg) { +- assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); +- return Reg - LoongArch::F0 + LoongArch::F0_64; +-} ++ void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPR32Reg())); ++ } + +-// Attempts to match Name as a register (either using the default name or +-// alternative ABI names), setting RegNo to the matching register. Upon +-// failure, returns true and sets RegNo to 0. +-static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { +- RegNo = MatchRegisterName(Name); +- // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial +- // match always matches the 32-bit variant, and not the 64-bit one. +- assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); +- // The default FPR register class is based on the tablegen enum ordering. +- static_assert(LoongArch::F0 < LoongArch::F0_64, +- "FPR matching must be updated"); +- if (RegNo == LoongArch::NoRegister) +- RegNo = MatchRegisterAltName(Name); ++ void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); ++ } + +- return RegNo == LoongArch::NoRegister; +-} ++ void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); ++ } + +-bool LoongArchAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, +- SMLoc &EndLoc) { +- return Error(getLoc(), "invalid register number"); +-} ++ void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); ++ } + +-OperandMatchResultTy LoongArchAsmParser::tryParseRegister(unsigned &RegNo, +- SMLoc &StartLoc, +- SMLoc &EndLoc) { +- llvm_unreachable("Unimplemented function."); +-} ++ void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); ++ } + +-OperandMatchResultTy +-LoongArchAsmParser::parseRegister(OperandVector &Operands) { +- if (getLexer().getTok().isNot(AsmToken::Dollar)) +- return MatchOperand_NoMatch; ++ void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst, ++ unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); ++ } + +- // Eat the $ prefix. +- getLexer().Lex(); +- if (getLexer().getKind() != AsmToken::Identifier) +- return MatchOperand_NoMatch; ++ /// Render the operand to an MCInst as a GPR64 ++ /// Asserts if the wrong number of operands are requested, or the operand ++ /// is not a k_RegisterIndex compatible with RegKind_GPR ++ void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getGPR64Reg())); ++ } + +- StringRef Name = getLexer().getTok().getIdentifier(); +- MCRegister RegNo; +- matchRegisterNameHelper(RegNo, Name); +- if (RegNo == LoongArch::NoRegister) +- return MatchOperand_NoMatch; ++ void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFGR64Reg())); ++ } + +- SMLoc S = getLoc(); +- SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); +- getLexer().Lex(); +- Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); ++ void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFGR64Reg())); ++ } + +- return MatchOperand_Success; +-} ++ void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFGR32Reg())); ++ } + +-OperandMatchResultTy +-LoongArchAsmParser::parseImmediate(OperandVector &Operands) { +- SMLoc S = getLoc(); +- SMLoc E; +- const MCExpr *Res; ++ void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFGR32Reg())); ++ } + +- if (getParser().parseExpression(Res, E)) +- return MatchOperand_ParseFail; ++ void addFCFRAsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFCFRReg())); ++ } + +- Operands.push_back(LoongArchOperand::createImm(Res, S, E)); +- return MatchOperand_Success; +-} ++ void addLSX128AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getLSX128Reg())); ++ } + +-/// Looks at a token type and creates the relevant operand from this +-/// information, adding to Operands. Return true upon an error. +-bool LoongArchAsmParser::parseOperand(OperandVector &Operands, +- StringRef Mnemonic) { +- if (parseRegister(Operands) == MatchOperand_Success || +- parseImmediate(Operands) == MatchOperand_Success) +- return false; ++ void addLASX256AsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getLASX256Reg())); ++ } + +- // Finally we have exhausted all options and must declare defeat. +- Error(getLoc(), "unknown operand"); +- return true; +-} ++ void addFCSRAsmRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::createReg(getFCSRReg())); ++ } + +-bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, +- StringRef Name, SMLoc NameLoc, +- OperandVector &Operands) { +- // First operand in MCInst is instruction mnemonic. +- Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); ++ template ++ void addConstantUImmOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ uint64_t Imm = getConstantImm() - Offset; ++ Imm &= (1ULL << Bits) - 1; ++ Imm += Offset; ++ Imm += AdjustOffset; ++ Inst.addOperand(MCOperand::createImm(Imm)); ++ } + +- // If there are no more operands, then finish. +- if (parseOptionalToken(AsmToken::EndOfStatement)) +- return false; ++ template ++ void addSImmOperands(MCInst &Inst, unsigned N) const { ++ if (isImm() && !isConstantImm()) { ++ addExpr(Inst, getImm()); ++ return; ++ } ++ addConstantSImmOperands(Inst, N); ++ } + +- // Parse first operand. +- if (parseOperand(Operands, Name)) +- return true; ++ template ++ void addUImmOperands(MCInst &Inst, unsigned N) const { ++ if (isImm() && !isConstantImm()) { ++ addExpr(Inst, getImm()); ++ return; ++ } ++ addConstantUImmOperands(Inst, N); ++ } + +- // Parse until end of statement, consuming commas between operands. +- while (parseOptionalToken(AsmToken::Comma)) +- if (parseOperand(Operands, Name)) +- return true; ++ template ++ void addConstantSImmOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ int64_t Imm = getConstantImm() - Offset; ++ Imm = SignExtend64(Imm); ++ Imm += Offset; ++ Imm += AdjustOffset; ++ Inst.addOperand(MCOperand::createImm(Imm)); ++ } + +- // Parse end of statement and return successfully. +- if (parseOptionalToken(AsmToken::EndOfStatement)) +- return false; ++ void addImmOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ const MCExpr *Expr = getImm(); ++ addExpr(Inst, Expr); ++ } + +- SMLoc Loc = getLexer().getLoc(); +- getParser().eatToEndOfStatement(); +- return Error(Loc, "unexpected token"); +-} ++ void addMemOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 2 && "Invalid number of operands!"); + +-bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, +- OperandVector &Operands, +- MCStreamer &Out) { +- Inst.setLoc(IDLoc); +- Out.emitInstruction(Inst, getSTI()); +- return false; +-} ++ Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit() ++ ? getMemBase()->getGPR64Reg() ++ : getMemBase()->getGPR32Reg())); + +-unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { +- switch (Inst.getOpcode()) { +- default: +- break; +- case LoongArch::CSRXCHG: { +- unsigned Rj = Inst.getOperand(2).getReg(); +- if (Rj == LoongArch::R0 || Rj == LoongArch::R1) +- return Match_RequiresOpnd2NotR0R1; +- return Match_Success; ++ const MCExpr *Expr = getMemOff(); ++ addExpr(Inst, Expr); + } +- case LoongArch::BSTRINS_W: +- case LoongArch::BSTRINS_D: +- case LoongArch::BSTRPICK_W: +- case LoongArch::BSTRPICK_D: { +- unsigned Opc = Inst.getOpcode(); +- const signed Msb = +- (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) +- ? Inst.getOperand(3).getImm() +- : Inst.getOperand(2).getImm(); +- const signed Lsb = +- (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) +- ? Inst.getOperand(4).getImm() +- : Inst.getOperand(3).getImm(); +- if (Msb < Lsb) +- return Match_RequiresMsbNotLessThanLsb; +- return Match_Success; ++ ++ void addRegListOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ ++ for (auto RegNo : getRegList()) ++ Inst.addOperand(MCOperand::createReg(RegNo)); + } ++ ++ bool isReg() const override { ++ // As a special case until we sort out the definition of div/divu, accept ++ // $0/$zero here so that MCK_ZERO works correctly. ++ return isGPRAsmReg() && RegIdx.Index == 0; + } + +- return Match_Success; +-} ++ bool isRegIdx() const { return Kind == k_RegisterIndex; } ++ bool isImm() const override { return Kind == k_Immediate; } + +-unsigned +-LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, +- unsigned Kind) { +- LoongArchOperand &Op = static_cast(AsmOp); +- if (!Op.isReg()) +- return Match_InvalidOperand; ++ bool isConstantImm() const { ++ int64_t Res; ++ return isImm() && getImm()->evaluateAsAbsolute(Res); ++ } + +- MCRegister Reg = Op.getReg(); +- // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the +- // register from FPR32 to FPR64 if necessary. +- if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && +- Kind == MCK_FPR64) { +- Op.setReg(convertFPR32ToFPR64(Reg)); +- return Match_Success; ++ bool isConstantImmz() const { ++ return isConstantImm() && getConstantImm() == 0; + } + +- return Match_InvalidOperand; +-} ++ template bool isConstantUImm() const { ++ return isConstantImm() && isUInt(getConstantImm() - Offset); ++ } + +-bool LoongArchAsmParser::generateImmOutOfRangeError( +- OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, +- Twine Msg = "immediate must be an integer in the range") { +- SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); +- return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); +-} ++ template bool isSImm() const { ++ return isConstantImm() ? isInt(getConstantImm()) : isImm(); ++ } + +-bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, +- OperandVector &Operands, +- MCStreamer &Out, +- uint64_t &ErrorInfo, +- bool MatchingInlineAsm) { +- MCInst Inst; +- FeatureBitset MissingFeatures; ++ template bool isUImm() const { ++ return isConstantImm() ? isUInt(getConstantImm()) : isImm(); ++ } + +- auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, +- MatchingInlineAsm); +- switch (Result) { +- default: +- break; +- case Match_Success: +- return processInstruction(Inst, IDLoc, Operands, Out); +- case Match_MissingFeature: { +- assert(MissingFeatures.any() && "Unknown missing features!"); +- bool FirstFeature = true; +- std::string Msg = "instruction requires the following:"; +- for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { +- if (MissingFeatures[i]) { +- Msg += FirstFeature ? " " : ", "; +- Msg += getSubtargetFeatureName(i); +- FirstFeature = false; +- } +- } +- return Error(IDLoc, Msg); ++ template bool isAnyImm() const { ++ return isConstantImm() ? (isInt(getConstantImm()) || ++ isUInt(getConstantImm())) ++ : isImm(); + } +- case Match_MnemonicFail: { +- FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); +- std::string Suggestion = LoongArchMnemonicSpellCheck( +- ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); +- return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); ++ ++ template bool isConstantSImm() const { ++ return isConstantImm() && isInt(getConstantImm() - Offset); ++ } ++ ++ template bool isConstantUImmRange() const { ++ return isConstantImm() && getConstantImm() >= Bottom && ++ getConstantImm() <= Top; ++ } ++ ++ bool isToken() const override { ++ // Note: It's not possible to pretend that other operand kinds are tokens. ++ // The matcher emitter checks tokens first. ++ return Kind == k_Token; ++ } ++ ++ bool isMem() const override { return Kind == k_Memory; } ++ ++ bool isConstantMemOff() const { ++ return isMem() && isa(getMemOff()); ++ } ++ ++ bool isZeroMemOff() const { ++ return isMem() && isa(getMemOff()) && ++ getConstantMemOff() == 0; ++ } ++ ++ // Allow relocation operators. ++ // FIXME: This predicate and others need to look through binary expressions ++ // and determine whether a Value is a constant or not. ++ template ++ bool isMemWithSimmOffset() const { ++ if (!isMem()) ++ return false; ++ if (!getMemBase()->isGPRAsmReg()) ++ return false; ++ if (isa(getMemOff()) || ++ (isConstantMemOff() && ++ isShiftedInt(getConstantMemOff()))) ++ return true; ++ MCValue Res; ++ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); ++ return IsReloc && isShiftedInt(Res.getConstant()); ++ } ++ ++ bool isMemWithPtrSizeOffset() const { ++ if (!isMem()) ++ return false; ++ if (!getMemBase()->isGPRAsmReg()) ++ return false; ++ const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32; ++ if (isa(getMemOff()) || ++ (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff()))) ++ return true; ++ MCValue Res; ++ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); ++ return IsReloc && isIntN(PtrBits, Res.getConstant()); ++ } ++ ++ bool isMemWithGRPMM16Base() const { ++ return isMem() && getMemBase()->isMM16AsmReg(); ++ } ++ ++ template bool isMemWithUimmOffsetSP() const { ++ return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) ++ && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == LoongArch::SP); ++ } ++ ++ template bool isMemWithUimmWordAlignedOffsetSP() const { ++ return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) ++ && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() ++ && (getMemBase()->getGPR32Reg() == LoongArch::SP); ++ } ++ ++ template ++ bool isScaledUImm() const { ++ return isConstantImm() && ++ isShiftedUInt(getConstantImm()); ++ } ++ ++ template ++ bool isScaledSImm() const { ++ if (isConstantImm() && ++ isShiftedInt(getConstantImm())) ++ return true; ++ // Operand can also be a symbol or symbol plus ++ // offset in case of relocations. ++ if (Kind != k_Immediate) ++ return false; ++ MCValue Res; ++ bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr); ++ return Success && isShiftedInt(Res.getConstant()); ++ } ++ ++ bool isRegList16() const { ++ if (!isRegList()) ++ return false; ++ ++ int Size = RegList.List->size(); ++ if (Size < 2 || Size > 5) ++ return false; ++ ++ unsigned R0 = RegList.List->front(); ++ unsigned R1 = RegList.List->back(); ++ if (!((R0 == LoongArch::S0 && R1 == LoongArch::RA) || ++ (R0 == LoongArch::S0_64 && R1 == LoongArch::RA_64))) ++ return false; ++ ++ int PrevReg = *RegList.List->begin(); ++ for (int i = 1; i < Size - 1; i++) { ++ int Reg = (*(RegList.List))[i]; ++ if ( Reg != PrevReg + 1) ++ return false; ++ PrevReg = Reg; ++ } ++ ++ return true; ++ } ++ ++ bool isInvNum() const { return Kind == k_Immediate; } ++ ++ bool isLSAImm() const { ++ if (!isConstantImm()) ++ return false; ++ int64_t Val = getConstantImm(); ++ return 1 <= Val && Val <= 4; ++ } ++ ++ bool isRegList() const { return Kind == k_RegList; } ++ ++ StringRef getToken() const { ++ assert(Kind == k_Token && "Invalid access!"); ++ return StringRef(Tok.Data, Tok.Length); ++ } ++ ++ unsigned getReg() const override { ++ // As a special case until we sort out the definition of div/divu, accept ++ // $0/$zero here so that MCK_ZERO works correctly. ++ if (Kind == k_RegisterIndex && RegIdx.Index == 0 && ++ RegIdx.Kind & RegKind_GPR) ++ return getGPR32Reg(); // FIXME: GPR64 too ++ ++ llvm_unreachable("Invalid access!"); ++ return 0; ++ } ++ ++ const MCExpr *getImm() const { ++ assert((Kind == k_Immediate) && "Invalid access!"); ++ return Imm.Val; ++ } ++ ++ int64_t getConstantImm() const { ++ const MCExpr *Val = getImm(); ++ int64_t Value = 0; ++ (void)Val->evaluateAsAbsolute(Value); ++ return Value; ++ } ++ ++ LoongArchOperand *getMemBase() const { ++ assert((Kind == k_Memory) && "Invalid access!"); ++ return Mem.Base; ++ } ++ ++ const MCExpr *getMemOff() const { ++ assert((Kind == k_Memory) && "Invalid access!"); ++ return Mem.Off; ++ } ++ ++ int64_t getConstantMemOff() const { ++ return static_cast(getMemOff())->getValue(); ++ } ++ ++ const SmallVectorImpl &getRegList() const { ++ assert((Kind == k_RegList) && "Invalid access!"); ++ return *(RegList.List); ++ } ++ ++ static std::unique_ptr CreateToken(StringRef Str, SMLoc S, ++ LoongArchAsmParser &Parser) { ++ auto Op = std::make_unique(k_Token, Parser); ++ Op->Tok.Data = Str.data(); ++ Op->Tok.Length = Str.size(); ++ Op->StartLoc = S; ++ Op->EndLoc = S; ++ return Op; ++ } ++ ++ /// Create a numeric register (e.g. $1). The exact register remains ++ /// unresolved until an instruction successfully matches ++ static std::unique_ptr ++ createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); ++ return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser); ++ } ++ ++ /// Create a register that is definitely a GPR. ++ /// This is typically only used for named registers such as $gp. ++ static std::unique_ptr ++ createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser); ++ } ++ ++ /// Create a register that is definitely a FGR. ++ /// This is typically only used for named registers such as $f0. ++ static std::unique_ptr ++ createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser); ++ } ++ ++ /// Create a register that is definitely an FCFR. ++ /// This is typically only used for named registers such as $fcc0. ++ static std::unique_ptr ++ createFCFRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_FCFR, RegInfo, S, E, Parser); ++ } ++ ++ /// Create a register that is definitely an FCSR. ++ /// This is typically only used for named registers such as $fcsr0. ++ static std::unique_ptr ++ createFCSRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_FCSR, RegInfo, S, E, Parser); ++ } ++ ++ /// Create a register that is definitely an LSX128. ++ /// This is typically only used for named registers such as $v0. ++ static std::unique_ptr ++ createLSX128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_LSX128, RegInfo, S, E, Parser); ++ } ++ ++ static std::unique_ptr ++ createLASX256Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, ++ SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ return CreateReg(Index, Str, RegKind_LASX256, RegInfo, S, E, Parser); ++ } ++ ++ static std::unique_ptr ++ CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, LoongArchAsmParser &Parser) { ++ auto Op = std::make_unique(k_Immediate, Parser); ++ Op->Imm.Val = Val; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ static std::unique_ptr ++ CreateMem(std::unique_ptr Base, const MCExpr *Off, SMLoc S, ++ SMLoc E, LoongArchAsmParser &Parser) { ++ auto Op = std::make_unique(k_Memory, Parser); ++ Op->Mem.Base = Base.release(); ++ Op->Mem.Off = Off; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ static std::unique_ptr ++ CreateRegList(SmallVectorImpl &Regs, SMLoc StartLoc, SMLoc EndLoc, ++ LoongArchAsmParser &Parser) { ++ assert(Regs.size() > 0 && "Empty list not allowed"); ++ ++ auto Op = std::make_unique(k_RegList, Parser); ++ Op->RegList.List = new SmallVector(Regs.begin(), Regs.end()); ++ Op->StartLoc = StartLoc; ++ Op->EndLoc = EndLoc; ++ return Op; ++ } ++ ++ bool isGPRZeroAsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0; ++ } ++ ++ bool isGPRNonZeroAsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 && ++ RegIdx.Index <= 31; ++ } ++ ++ bool isGPRAsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; ++ } ++ ++ bool isMM16AsmReg() const { ++ if (!(isRegIdx() && RegIdx.Kind)) ++ return false; ++ return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) ++ || RegIdx.Index == 16 || RegIdx.Index == 17); ++ ++ } ++ bool isMM16AsmRegZero() const { ++ if (!(isRegIdx() && RegIdx.Kind)) ++ return false; ++ return (RegIdx.Index == 0 || ++ (RegIdx.Index >= 2 && RegIdx.Index <= 7) || ++ RegIdx.Index == 17); ++ } ++ ++ bool isMM16AsmRegMoveP() const { ++ if (!(isRegIdx() && RegIdx.Kind)) ++ return false; ++ return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || ++ (RegIdx.Index >= 16 && RegIdx.Index <= 20)); ++ } ++ ++ bool isMM16AsmRegMovePPairFirst() const { ++ if (!(isRegIdx() && RegIdx.Kind)) ++ return false; ++ return RegIdx.Index >= 4 && RegIdx.Index <= 6; ++ } ++ ++ bool isMM16AsmRegMovePPairSecond() const { ++ if (!(isRegIdx() && RegIdx.Kind)) ++ return false; ++ return (RegIdx.Index == 21 || RegIdx.Index == 22 || ++ (RegIdx.Index >= 5 && RegIdx.Index <= 7)); ++ } ++ ++ bool isFGRAsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; ++ } ++ ++ bool isStrictlyFGRAsmReg() const { ++ return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31; ++ } ++ ++ bool isFCSRAsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_FCSR && RegIdx.Index <= 3; ++ } ++ ++ bool isFCFRAsmReg() const { ++ if (!(isRegIdx() && RegIdx.Kind & RegKind_FCFR)) ++ return false; ++ return RegIdx.Index <= 7; ++ } ++ ++ bool isLSX128AsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_LSX128 && RegIdx.Index <= 31; ++ } ++ ++ bool isLASX256AsmReg() const { ++ return isRegIdx() && RegIdx.Kind & RegKind_LASX256 && RegIdx.Index <= 31; ++ } ++ ++ /// getStartLoc - Get the location of the first token of this operand. ++ SMLoc getStartLoc() const override { return StartLoc; } ++ /// getEndLoc - Get the location of the last token of this operand. ++ SMLoc getEndLoc() const override { return EndLoc; } ++ ++ void print(raw_ostream &OS) const override { ++ switch (Kind) { ++ case k_Immediate: ++ OS << "Imm<"; ++ OS << *Imm.Val; ++ OS << ">"; ++ break; ++ case k_Memory: ++ OS << "Mem<"; ++ Mem.Base->print(OS); ++ OS << ", "; ++ OS << *Mem.Off; ++ OS << ">"; ++ break; ++ case k_RegisterIndex: ++ OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", " ++ << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">"; ++ break; ++ case k_Token: ++ OS << getToken(); ++ break; ++ case k_RegList: ++ OS << "RegList< "; ++ for (auto Reg : (*RegList.List)) ++ OS << Reg << " "; ++ OS << ">"; ++ break; ++ } ++ } ++ ++ bool isValidForTie(const LoongArchOperand &Other) const { ++ if (Kind != Other.Kind) ++ return false; ++ ++ switch (Kind) { ++ default: ++ llvm_unreachable("Unexpected kind"); ++ return false; ++ case k_RegisterIndex: { ++ StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length); ++ StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length); ++ return Token == OtherToken; ++ } ++ } ++ } ++}; // class LoongArchOperand ++ ++} // end anonymous namespace ++ ++namespace llvm { ++ ++extern const MCInstrDesc LoongArchInsts[]; ++ ++} // end namespace llvm ++ ++static const MCInstrDesc &getInstDesc(unsigned Opcode) { ++ return LoongArchInsts[Opcode]; ++} ++ ++static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) { ++ if (const MCSymbolRefExpr *SRExpr = dyn_cast(Expr)) { ++ return &SRExpr->getSymbol(); ++ } ++ ++ if (const MCBinaryExpr *BExpr = dyn_cast(Expr)) { ++ const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS()); ++ const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS()); ++ ++ if (LHSSym) ++ return LHSSym; ++ ++ if (RHSSym) ++ return RHSSym; ++ ++ return nullptr; ++ } ++ ++ if (const MCUnaryExpr *UExpr = dyn_cast(Expr)) ++ return getSingleMCSymbol(UExpr->getSubExpr()); ++ ++ return nullptr; ++} ++ ++static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { ++ if (isa(Expr)) ++ return 1; ++ ++ if (const MCBinaryExpr *BExpr = dyn_cast(Expr)) ++ return countMCSymbolRefExpr(BExpr->getLHS()) + ++ countMCSymbolRefExpr(BExpr->getRHS()); ++ ++ if (const MCUnaryExpr *UExpr = dyn_cast(Expr)) ++ return countMCSymbolRefExpr(UExpr->getSubExpr()); ++ ++ return 0; ++} ++ ++bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, ++ MCStreamer &Out, ++ const MCSubtargetInfo *STI) { ++ const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); ++ ++ Inst.setLoc(IDLoc); ++ ++ // Check branch instructions. ++ if (MCID.isBranch() || MCID.isCall()) { ++ const unsigned Opcode = Inst.getOpcode(); ++ MCOperand Offset; ++ bool check = true; ++ unsigned OffsetOpndIdx, OffsetOpndWidth; ++ switch (Opcode) { ++ default: ++ check = false; ++ break; ++ case LoongArch::BEQ: ++ case LoongArch::BNE: ++ case LoongArch::BLT: ++ case LoongArch::BGE: ++ case LoongArch::BLTU: ++ case LoongArch::BGEU: ++ OffsetOpndIdx = 2; ++ OffsetOpndWidth = 16; ++ break; ++ case LoongArch::BEQZ: ++ case LoongArch::BNEZ: ++ case LoongArch::BCEQZ: ++ case LoongArch::BCNEZ: ++ OffsetOpndIdx = 1; ++ OffsetOpndWidth = 21; ++ break; ++ case LoongArch::B: ++ case LoongArch::BL: ++ OffsetOpndIdx = 0; ++ OffsetOpndWidth = 26; ++ break; ++ } ++ if (check) { ++ assert(MCID.getNumOperands() == OffsetOpndIdx + 1 && ++ "unexpected number of operands"); ++ Offset = Inst.getOperand(OffsetOpndIdx); ++ // Non-Imm situation will be dealed with later on when applying fixups. ++ if (Offset.isImm()) { ++ if (!isIntN(OffsetOpndWidth + 2, Offset.getImm())) ++ return Error(IDLoc, "branch target out of range"); ++ if (offsetToAlignment(Offset.getImm(), Align(1LL << 2))) ++ return Error(IDLoc, "branch to misaligned address"); ++ } ++ } ++ } ++ ++ bool IsPCRelativeLoad = (MCID.TSFlags & LoongArchII::IsPCRelativeLoad) != 0; ++ if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { ++ // Check the offset of memory operand, if it is a symbol ++ // reference or immediate we may have to expand instructions. ++ for (unsigned i = 0; i < MCID.getNumOperands(); i++) { ++ const MCOperandInfo &OpInfo = MCID.OpInfo[i]; ++ if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || ++ (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { ++ MCOperand &Op = Inst.getOperand(i); ++ if (Op.isImm()) { ++ int64_t MemOffset = Op.getImm(); ++ if (MemOffset < -32768 || MemOffset > 32767) { ++ return getParser().hasPendingError(); ++ } ++ } else if (Op.isExpr()) { ++ const MCExpr *Expr = Op.getExpr(); ++ if (Expr->getKind() == MCExpr::SymbolRef) { ++ const MCSymbolRefExpr *SR = ++ static_cast(Expr); ++ if (SR->getKind() == MCSymbolRefExpr::VK_None) { ++ return getParser().hasPendingError(); ++ } ++ } else if (!isEvaluated(Expr)) { ++ return getParser().hasPendingError(); ++ } ++ } ++ } ++ } // for ++ } // if load/store ++ ++ MacroExpanderResultTy ExpandResult = ++ tryExpandInstruction(Inst, IDLoc, Out, STI); ++ switch (ExpandResult) { ++ case MER_NotAMacro: ++ Out.emitInstruction(Inst, *STI); ++ break; ++ case MER_Success: ++ break; ++ case MER_Fail: ++ return true; + } ++ ++ return false; ++} ++ ++LoongArchAsmParser::MacroExpanderResultTy ++LoongArchAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, ++ const MCSubtargetInfo *STI) { ++ switch (Inst.getOpcode()) { ++ default: ++ return MER_NotAMacro; ++ case LoongArch::LoadImm32: // li.w $rd, $imm32 ++ case LoongArch::LoadImm64: // li.d $rd, $imm64 ++ return expandLoadImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; ++ case LoongArch::LoadAddrLocal: // la.local $rd, symbol ++ case LoongArch::LoadAddrGlobal: // la.global $rd, symbol ++ case LoongArch::LoadAddrGlobal_Alias: // la $rd, symbol ++ case LoongArch::LoadAddrTLS_LE: // la.tls.le $rd, symbol ++ case LoongArch::LoadAddrTLS_IE: // la.tls.ie $rd, symbol ++ case LoongArch::LoadAddrTLS_LD: // la.tls.ld $rd, symbol ++ case LoongArch::LoadAddrTLS_GD: // la.tls.gd $rd, symbol ++ return expandLoadAddress(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; ++ } ++} ++ ++/// Can the value be represented by a unsigned N-bit value and a shift left? ++template static bool isShiftedUIntAtAnyPosition(uint64_t x) { ++ unsigned BitNum = findFirstSet(x); ++ ++ return (x == x >> BitNum << BitNum) && isUInt(x >> BitNum); ++} ++ ++bool LoongArchAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, ++ MCStreamer &Out, ++ const MCSubtargetInfo *STI) { ++ const int64_t Imm = Inst.getOperand(1).getImm(); ++ const unsigned DstReg = Inst.getOperand(0).getReg(); ++ LoongArchTargetStreamer &TOut = getTargetStreamer(); ++ bool Is64Bit = Inst.getOpcode() == LoongArch::LoadImm64; ++ unsigned SrcReg = Is64Bit ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ LoongArchAnalyzeImmediate::InstSeq Seq = ++ LoongArchAnalyzeImmediate::generateInstSeq( ++ Is64Bit ? Imm : SignExtend64<32>(Imm), Is64Bit); ++ ++ for (auto &Inst : Seq) { ++ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) ++ TOut.emitRI(Inst.Opc, DstReg, Inst.Imm, IDLoc, STI); ++ else ++ TOut.emitRRI(Inst.Opc, DstReg, SrcReg, Inst.Imm, IDLoc, STI); ++ SrcReg = DstReg; ++ } ++ ++ return false; ++} ++ ++bool LoongArchAsmParser::expandLoadAddress(MCInst &Inst, SMLoc IDLoc, ++ MCStreamer &Out, ++ const MCSubtargetInfo *STI) { ++ LoongArchTargetStreamer &TOut = getTargetStreamer(); ++ const MCExpr *SymExpr = Inst.getOperand(1).getExpr(); ++ const LoongArchMCExpr *HiExpr = nullptr; ++ const LoongArchMCExpr *LoExpr = nullptr; ++ const LoongArchMCExpr *HigherExpr = nullptr; ++ const LoongArchMCExpr *HighestExpr = nullptr; ++ const MCExpr *GotExpr = MCSymbolRefExpr::create( ++ "_GLOBAL_OFFSET_TABLE_", MCSymbolRefExpr::VK_None, getContext()); ++ unsigned DstReg = Inst.getOperand(0).getReg(); ++ ++ MCValue Res; ++ if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { ++ Error(IDLoc, "expected relocatable expression"); ++ return true; ++ } ++ if (Res.getSymB() != nullptr) { ++ Error(IDLoc, "expected relocatable expression with only one symbol"); ++ return true; ++ } ++ ++ switch (Inst.getOpcode()) { ++ case LoongArch::LoadAddrLocal: ++ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_PCREL_HI, SymExpr, ++ getContext()); ++ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_PCREL_LO, SymExpr, ++ getContext()); ++ ++ TOut.emitRX(LoongArch::PCADDU12I_ri, DstReg, MCOperand::createExpr(HiExpr), ++ IDLoc, STI); ++ TOut.emitRRX(LoongArch::ADDI_D_rri, DstReg, DstReg, ++ MCOperand::createExpr(LoExpr), IDLoc, STI); ++ return false; ++ case LoongArch::LoadAddrGlobal: ++ case LoongArch::LoadAddrGlobal_Alias: ++ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_GOT_HI, SymExpr, ++ getContext()); ++ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_GOT_LO, SymExpr, ++ getContext()); ++ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, ++ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ TOut.emitRRXX(LoongArch::LD_D_rrii, DstReg, DstReg, ++ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ return false; ++ case LoongArch::LoadAddrTLS_LE: ++ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HI, SymExpr, ++ getContext()); ++ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_LO, SymExpr, ++ getContext()); ++ HigherExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HIGHER, ++ SymExpr, getContext()); ++ HighestExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSLE_HIGHEST, ++ SymExpr, getContext()); ++ TOut.emitRX(LoongArch::LU12I_W_ri, DstReg, MCOperand::createExpr(HiExpr), ++ IDLoc, STI); ++ TOut.emitRRX(LoongArch::ORI_rri, DstReg, DstReg, ++ MCOperand::createExpr(LoExpr), IDLoc, STI); ++ TOut.emitRX(LoongArch::LU32I_D_ri, DstReg, ++ MCOperand::createExpr(HigherExpr), IDLoc, STI); ++ TOut.emitRRX(LoongArch::LU52I_D_rri, DstReg, DstReg, ++ MCOperand::createExpr(HighestExpr), IDLoc, STI); ++ return false; ++ case LoongArch::LoadAddrTLS_IE: ++ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSIE_HI, SymExpr, ++ getContext()); ++ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSIE_LO, SymExpr, ++ getContext()); ++ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, ++ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ TOut.emitRRXX(LoongArch::LD_D_rrii, DstReg, DstReg, ++ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ return false; ++ case LoongArch::LoadAddrTLS_LD: ++ case LoongArch::LoadAddrTLS_GD: ++ HiExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSGD_HI, SymExpr, ++ getContext()); ++ LoExpr = LoongArchMCExpr::create(LoongArchMCExpr::MEK_TLSGD_LO, SymExpr, ++ getContext()); ++ TOut.emitRXX(LoongArch::PCADDU12I_rii, DstReg, ++ MCOperand::createExpr(HiExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ TOut.emitRRXX(LoongArch::ADDI_D_rrii, DstReg, DstReg, ++ MCOperand::createExpr(LoExpr), MCOperand::createExpr(GotExpr), ++ IDLoc, STI); ++ return false; ++ default: ++ llvm_unreachable(""); ++ } ++} ++ ++unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { ++ switch (Inst.getOpcode()) { ++ case LoongArch::BSTRINS_W: ++ case LoongArch::BSTRPICK_W: { ++ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && ++ "Operands must be immediates for bstrins.w/bstrpick.w!"); ++ const signed Msbw = Inst.getOperand(2).getImm(); ++ const signed Lsbw = Inst.getOperand(3).getImm(); ++ if (Msbw < Lsbw) ++ return Match_MsbHigherThanLsb; ++ if ((Lsbw < 0) || (Msbw > 31)) ++ return Match_RequiresRange0_31; ++ return Match_Success; ++ } ++ case LoongArch::BSTRINS_D: ++ case LoongArch::BSTRPICK_D: { ++ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && ++ "Operands must be immediates for bstrins.d/bstrpick.d!"); ++ const signed Msbd = Inst.getOperand(2).getImm(); ++ const signed Lsbd = Inst.getOperand(3).getImm(); ++ if (Msbd < Lsbd) ++ return Match_MsbHigherThanLsb; ++ if ((Lsbd < 0) || (Msbd > 63)) ++ return Match_RequiresRange0_63; ++ return Match_Success; ++ } ++ case LoongArch::CSRXCHG32: ++ case LoongArch::CSRXCHG: ++ if (Inst.getOperand(2).getReg() == LoongArch::ZERO || ++ Inst.getOperand(2).getReg() == LoongArch::ZERO_64) ++ return Match_RequiresNoZeroRegister; ++ if (Inst.getOperand(2).getReg() == LoongArch::RA || ++ Inst.getOperand(2).getReg() == LoongArch::RA_64) ++ return Match_RequiresNoRaRegister; ++ return Match_Success; ++ } ++ ++ return Match_Success; ++} ++ ++static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, ++ uint64_t ErrorInfo) { ++ if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { ++ SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); ++ if (ErrorLoc == SMLoc()) ++ return Loc; ++ return ErrorLoc; ++ } ++ return Loc; ++} ++ ++bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ OperandVector &Operands, ++ MCStreamer &Out, ++ uint64_t &ErrorInfo, ++ bool MatchingInlineAsm) { ++ MCInst Inst; ++ unsigned MatchResult = ++ MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); ++ switch (MatchResult) { ++ case Match_Success: ++ if (processInstruction(Inst, IDLoc, Out, STI)) ++ return true; ++ return false; ++ case Match_MissingFeature: ++ Error(IDLoc, "instruction requires a CPU feature not currently enabled"); ++ return true; + case Match_InvalidOperand: { + SMLoc ErrorLoc = IDLoc; + if (ErrorInfo != ~0ULL) { + if (ErrorInfo >= Operands.size()) +- return Error(ErrorLoc, "too few operands for instruction"); ++ return Error(IDLoc, "too few operands for instruction"); + +- ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); ++ ErrorLoc = Operands[ErrorInfo]->getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + } ++ + return Error(ErrorLoc, "invalid operand for instruction"); + } ++ case Match_MnemonicFail: ++ return Error(IDLoc, "invalid instruction"); ++ case Match_RequiresNoZeroRegister: ++ return Error(IDLoc, "invalid operand ($zero) for instruction"); ++ case Match_RequiresNoRaRegister: ++ return Error(IDLoc, "invalid operand ($r1) for instruction"); ++ case Match_InvalidImm0_3: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 3]."); ++ case Match_InvalidImm0_7: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 7]."); ++ case Match_InvalidImm0_31: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 31]."); ++ case Match_InvalidImm0_63: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 63]."); ++ case Match_InvalidImm0_4095: ++ case Match_UImm12_Relaxed: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 4095]."); ++ case Match_InvalidImm0_32767: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "immediate must be an integer in range [0, 32767]."); ++ case Match_UImm16_Relaxed: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 16-bit unsigned immediate"); ++ case Match_UImm20_0: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 20-bit unsigned immediate"); ++ case Match_UImm26_0: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 26-bit unsigned immediate"); ++ case Match_UImm32_Coerced: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 32-bit immediate"); ++ case Match_InvalidSImm2: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 2-bit signed immediate"); ++ case Match_InvalidSImm3: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 3-bit signed immediate"); ++ case Match_InvalidSImm5: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 5-bit signed immediate"); ++ case Match_InvalidSImm8: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 8-bit signed immediate"); ++ case Match_InvalidSImm12: ++ case Match_SImm12_Relaxed: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 12-bit signed immediate"); ++ case Match_InvalidSImm14: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 14-bit signed immediate"); ++ case Match_InvalidSImm15: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 15-bit signed immediate"); ++ case Match_InvalidSImm16: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 16-bit signed immediate"); ++ case Match_InvalidSImm20: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 20-bit signed immediate"); ++ case Match_InvalidSImm21: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 21-bit signed immediate"); ++ case Match_InvalidSImm26: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 26-bit signed immediate"); ++ case Match_SImm32: ++ case Match_SImm32_Relaxed: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected 32-bit signed immediate"); ++ case Match_MemSImm14: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected memory with 14-bit signed offset"); ++ case Match_MemSImmPtr: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected memory with 32-bit signed offset"); ++ case Match_UImm2_1: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected immediate in range 1 .. 4"); ++ case Match_MemSImm14Lsl2: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected memory with 16-bit signed offset and multiple of 4"); ++ case Match_RequiresRange0_31: { ++ SMLoc ErrorStart = Operands[3]->getStartLoc(); ++ SMLoc ErrorEnd = Operands[4]->getEndLoc(); ++ return Error(ErrorStart, "from lsbw to msbw are not in the range 0 .. 31", ++ SMRange(ErrorStart, ErrorEnd)); ++ } ++ case Match_RequiresPosSizeUImm6: { ++ SMLoc ErrorStart = Operands[3]->getStartLoc(); ++ SMLoc ErrorEnd = Operands[4]->getEndLoc(); ++ return Error(ErrorStart, "size plus position are not in the range 1 .. 63", ++ SMRange(ErrorStart, ErrorEnd)); ++ } ++ case Match_RequiresRange0_63: { ++ SMLoc ErrorStart = Operands[3]->getStartLoc(); ++ SMLoc ErrorEnd = Operands[4]->getEndLoc(); ++ return Error(ErrorStart, "from lsbd to msbd are not in the range 0 .. 63", ++ SMRange(ErrorStart, ErrorEnd)); ++ } ++ case Match_MsbHigherThanLsb: { ++ SMLoc ErrorStart = Operands[3]->getStartLoc(); ++ SMLoc ErrorEnd = Operands[4]->getEndLoc(); ++ return Error(ErrorStart, "msb are not higher than lsb", SMRange(ErrorStart, ErrorEnd)); ++ } ++ case Match_MemZeroOff: ++ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), ++ "expected memory with constant 0 offset"); + } + +- // Handle the case when the error message is of specific type +- // other than the generic Match_InvalidOperand, and the +- // corresponding operand is missing. +- if (Result > FIRST_TARGET_MATCH_RESULT_TY) { +- SMLoc ErrorLoc = IDLoc; +- if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) +- return Error(ErrorLoc, "too few operands for instruction"); ++ llvm_unreachable("Implement any new match types added!"); ++} ++ ++/* ++ * Note: The implementation of this function must be sync with the definition ++ * of GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td ++ */ ++int LoongArchAsmParser::matchCPURegisterName(StringRef Name) { ++ int CC; ++ ++ CC = StringSwitch(Name) ++ .Cases("zero", "r0", 0) ++ .Cases("a0", "v0", "r4", 1) ++ .Cases("a1", "v1", "r5", 2) ++ .Cases("a2", "r6", 3) ++ .Cases("a3", "r7", 4) ++ .Cases("a4", "r8", 5) ++ .Cases("a5", "r9", 6) ++ .Cases("a6", "r10", 7) ++ .Cases("a7", "r11", 8) ++ .Cases("t0", "r12", 9) ++ .Cases("t1", "r13", 10) ++ .Cases("t2", "r14", 11) ++ .Cases("t3", "r15", 12) ++ .Cases("t4", "r16", 13) ++ .Cases("t5", "r17", 14) ++ .Cases("t6", "r18", 15) ++ .Cases("t7", "r19", 16) ++ .Cases("t8", "r20", 17) ++ .Cases("s0", "r23", 18) ++ .Cases("s1", "r24", 19) ++ .Cases("s2", "r25", 20) ++ .Cases("s3", "r26", 21) ++ .Cases("s4", "r27", 22) ++ .Cases("s5", "r28", 23) ++ .Cases("s6", "r29", 24) ++ .Cases("s7", "r30", 25) ++ .Cases("s8", "r31", 26) ++ .Cases("ra", "r1", 27) ++ .Cases("tp", "r2", 28) ++ .Cases("sp", "r3", 29) ++ .Case("r21", 30) ++ .Cases("fp", "r22", 31) ++ .Default(-1); ++ ++ return CC; ++} ++ ++int LoongArchAsmParser::matchFPURegisterName(StringRef Name) { ++ if (Name[0] == 'f') { ++ int CC; ++ ++ CC = StringSwitch(Name) ++ .Cases("f0", "fa0", "fv0", 0) ++ .Cases("f1", "fa1", "fv1", 1) ++ .Cases("f2", "fa2", 2) ++ .Cases("f3", "fa3", 3) ++ .Cases("f4", "fa4", 4) ++ .Cases("f5", "fa5", 5) ++ .Cases("f6", "fa6", 6) ++ .Cases("f7", "fa7", 7) ++ .Cases("f8", "ft0", 8) ++ .Cases("f9", "ft1", 9) ++ .Cases("f10", "ft2", 10) ++ .Cases("f11", "ft3", 11) ++ .Cases("f12", "ft4", 12) ++ .Cases("f13", "ft5", 13) ++ .Cases("f14", "ft6", 14) ++ .Cases("f15", "ft7", 15) ++ .Cases("f16", "ft8", 16) ++ .Cases("f17", "ft9", 17) ++ .Cases("f18", "ft10", 18) ++ .Cases("f19", "ft11", 19) ++ .Cases("f20", "ft12", 20) ++ .Cases("f21", "ft13", 21) ++ .Cases("f22", "ft14", 22) ++ .Cases("f23", "ft15", 23) ++ .Cases("f24", "fs0", 24) ++ .Cases("f25", "fs1", 25) ++ .Cases("f26", "fs2", 26) ++ .Cases("f27", "fs3", 27) ++ .Cases("f28", "fs4", 28) ++ .Cases("f29", "fs5", 29) ++ .Cases("f30", "fs6", 30) ++ .Cases("f31", "fs7", 31) ++ .Default(-1); ++ ++ return CC; + } ++ return -1; ++} + +- switch (Result) { +- default: +- break; +- case Match_RequiresMsbNotLessThanLsb: { +- SMLoc ErrorStart = Operands[3]->getStartLoc(); +- return Error(ErrorStart, "msb is less than lsb", +- SMRange(ErrorStart, Operands[4]->getEndLoc())); +- } +- case Match_RequiresOpnd2NotR0R1: +- return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); +- case Match_InvalidUImm2: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 2) - 1); +- case Match_InvalidUImm2plus1: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, +- /*Upper=*/(1 << 2)); +- case Match_InvalidUImm3: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 3) - 1); +- case Match_InvalidUImm5: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 5) - 1); +- case Match_InvalidUImm6: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 6) - 1); +- case Match_InvalidUImm12: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 12) - 1); +- case Match_InvalidUImm15: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, +- /*Upper=*/(1 << 15) - 1); +- case Match_InvalidSImm12: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), +- /*Upper=*/(1 << 11) - 1); +- case Match_InvalidSImm14lsl2: +- return generateImmOutOfRangeError( +- Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, +- "immediate must be a multiple of 4 in the range"); +- case Match_InvalidSImm16: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), +- /*Upper=*/(1 << 15) - 1); +- case Match_InvalidSImm16lsl2: +- return generateImmOutOfRangeError( +- Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, +- "immediate must be a multiple of 4 in the range"); +- case Match_InvalidSImm20: +- return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), +- /*Upper=*/(1 << 19) - 1); +- case Match_InvalidSImm21lsl2: +- return generateImmOutOfRangeError( +- Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, +- "immediate must be a multiple of 4 in the range"); +- case Match_InvalidSImm26lsl2: +- return generateImmOutOfRangeError( +- Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, +- "immediate must be a multiple of 4 in the range"); ++int LoongArchAsmParser::matchFCFRRegisterName(StringRef Name) { ++ if (Name.startswith("fcc")) { ++ StringRef NumString = Name.substr(3); ++ unsigned IntVal; ++ if (NumString.getAsInteger(10, IntVal)) ++ return -1; // This is not an integer. ++ if (IntVal > 7) // There are only 8 fcc registers. ++ return -1; ++ return IntVal; ++ } ++ return -1; ++} ++ ++int LoongArchAsmParser::matchFCSRRegisterName(StringRef Name) { ++ if (Name.startswith("fcsr")) { ++ StringRef NumString = Name.substr(4); ++ unsigned IntVal; ++ if (NumString.getAsInteger(10, IntVal)) ++ return -1; // This is not an integer. ++ if (IntVal > 3) // There are only 4 fcsr registers. ++ return -1; ++ return IntVal; ++ } ++ return -1; ++} ++ ++int LoongArchAsmParser::matchLSX128RegisterName(StringRef Name) { ++ unsigned IntVal; ++ ++ if (Name.front() != 'v' || Name.drop_front(2).getAsInteger(10, IntVal)) ++ return -1; ++ ++ if (IntVal > 31) ++ return -1; ++ ++ return IntVal; ++} ++ ++int LoongArchAsmParser::matchLASX256RegisterName(StringRef Name) { ++ unsigned IntVal; ++ ++ if (Name.front() != 'x' || Name.drop_front(2).getAsInteger(10, IntVal)) ++ return -1; ++ ++ if (IntVal > 31) ++ return -1; ++ ++ return IntVal; ++} ++ ++bool LoongArchAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "parseOperand\n"); ++ ++ // Check if the current operand has a custom associated parser, if so, try to ++ // custom parse the operand, or fallback to the general approach. ++ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); ++ if (ResTy == MatchOperand_Success) ++ return false; ++ // If there wasn't a custom match, try the generic matcher below. Otherwise, ++ // there was a match, but an error occurred, in which case, just return that ++ // the operand parsing failed. ++ if (ResTy == MatchOperand_ParseFail) ++ return true; ++ ++ LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); ++ ++ switch (getLexer().getKind()) { ++ case AsmToken::Dollar: { ++ // Parse the register. ++ SMLoc S = Parser.getTok().getLoc(); ++ ++ // Almost all registers have been parsed by custom parsers. There is only ++ // one exception to this. $zero (and it's alias $0) will reach this point ++ // for div, divu, and similar instructions because it is not an operand ++ // to the instruction definition but an explicit register. Special case ++ // this situation for now. ++ if (parseAnyRegister(Operands) != MatchOperand_NoMatch) ++ return false; ++ ++ // Maybe it is a symbol reference. ++ StringRef Identifier; ++ if (Parser.parseIdentifier(Identifier)) ++ return true; ++ ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); ++ // Otherwise create a symbol reference. ++ const MCExpr *Res = ++ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); ++ ++ Operands.push_back(LoongArchOperand::CreateImm(Res, S, E, *this)); ++ return false; ++ } ++ default: { ++ LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); ++ ++ const MCExpr *Expr; ++ SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. ++ if (getParser().parseExpression(Expr)) ++ return true; ++ ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ ++ Operands.push_back(LoongArchOperand::CreateImm(Expr, S, E, *this)); ++ return false; + } +- llvm_unreachable("Unknown match type detected!"); ++ } // switch(getLexer().getKind()) ++ return true; ++} ++ ++bool LoongArchAsmParser::isEvaluated(const MCExpr *Expr) { ++ switch (Expr->getKind()) { ++ case MCExpr::Constant: ++ return true; ++ case MCExpr::SymbolRef: ++ return (cast(Expr)->getKind() != MCSymbolRefExpr::VK_None); ++ case MCExpr::Binary: { ++ const MCBinaryExpr *BE = cast(Expr); ++ if (!isEvaluated(BE->getLHS())) ++ return false; ++ return isEvaluated(BE->getRHS()); ++ } ++ case MCExpr::Unary: ++ return isEvaluated(cast(Expr)->getSubExpr()); ++ case MCExpr::Target: ++ return true; ++ } ++ return false; ++} ++ ++bool LoongArchAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, ++ SMLoc &EndLoc) { ++ return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success; ++} ++ ++OperandMatchResultTy LoongArchAsmParser::tryParseRegister(unsigned &RegNo, ++ SMLoc &StartLoc, ++ SMLoc &EndLoc) { ++ SmallVector, 1> Operands; ++ OperandMatchResultTy ResTy = parseAnyRegister(Operands); ++ if (ResTy == MatchOperand_Success) { ++ assert(Operands.size() == 1); ++ LoongArchOperand &Operand = static_cast(*Operands.front()); ++ StartLoc = Operand.getStartLoc(); ++ EndLoc = Operand.getEndLoc(); ++ ++ // AFAIK, we only support numeric registers and named GPR's in CFI ++ // directives. ++ // Don't worry about eating tokens before failing. Using an unrecognised ++ // register is a parse error. ++ if (Operand.isGPRAsmReg()) { ++ // Resolve to GPR32 or GPR64 appropriately. ++ RegNo = is64Bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); ++ } ++ ++ return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch ++ : MatchOperand_Success; ++ } ++ ++ assert(Operands.size() == 0); ++ return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch : MatchOperand_Success; ++} ++ ++bool LoongArchAsmParser::parseMemOffset(const MCExpr *&Res) { ++ return getParser().parseExpression(Res); ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::parseMemOperand(OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "parseMemOperand\n"); ++ const MCExpr *IdVal = nullptr; ++ SMLoc S; ++ OperandMatchResultTy Res = MatchOperand_NoMatch; ++ // First operand is the base. ++ S = Parser.getTok().getLoc(); ++ ++ Res = parseAnyRegister(Operands); ++ if (Res != MatchOperand_Success) ++ return Res; ++ ++ if (Parser.getTok().isNot(AsmToken::Comma)) { ++ Error(Parser.getTok().getLoc(), "',' expected"); ++ return MatchOperand_ParseFail; ++ } ++ ++ Parser.Lex(); // Eat the ',' token. ++ ++ if (parseMemOffset(IdVal)) ++ return MatchOperand_ParseFail; ++ ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ ++ // Replace the register operand with the memory operand. ++ std::unique_ptr op( ++ static_cast(Operands.back().release())); ++ // Remove the register from the operands. ++ // "op" will be managed by k_Memory. ++ Operands.pop_back(); ++ ++ // when symbol not defined, error report. ++ if (dyn_cast(IdVal)) { ++ return MatchOperand_ParseFail; ++ } ++ ++ // Add the memory operand. ++ if (dyn_cast(IdVal)) { ++ int64_t Imm; ++ if (IdVal->evaluateAsAbsolute(Imm)) ++ IdVal = MCConstantExpr::create(Imm, getContext()); ++ else ++ return MatchOperand_ParseFail; ++ } ++ ++ Operands.push_back(LoongArchOperand::CreateMem(std::move(op), IdVal, S, E, *this)); ++ return MatchOperand_Success; ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::parseAMemOperand(OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "parseAMemOperand\n"); ++ const MCExpr *IdVal = nullptr; ++ SMLoc S; ++ OperandMatchResultTy Res = MatchOperand_NoMatch; ++ // First operand is the base. ++ S = Parser.getTok().getLoc(); ++ ++ Res = parseAnyRegister(Operands); ++ if (Res != MatchOperand_Success) ++ return Res; ++ ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ ++ // AM* instructions allow an optional '0' memory offset. ++ if (Parser.getTok().is(AsmToken::Comma)) { ++ Parser.Lex(); // Eat the ',' token. ++ ++ if (parseMemOffset(IdVal)) ++ return MatchOperand_ParseFail; ++ ++ // when symbol not defined, error report. ++ if (dyn_cast(IdVal)) ++ return MatchOperand_ParseFail; ++ ++ if (dyn_cast(IdVal)) { ++ int64_t Imm; ++ if (IdVal->evaluateAsAbsolute(Imm)) { ++ assert(Imm == 0 && "imm must be 0"); ++ IdVal = MCConstantExpr::create(Imm, getContext()); ++ } else { ++ return MatchOperand_ParseFail; ++ } ++ } ++ } else { ++ // Offset defaults to 0. ++ IdVal = MCConstantExpr::create(0, getContext()); ++ } ++ ++ // Replace the register operand with the memory operand. ++ std::unique_ptr op( ++ static_cast(Operands.back().release())); ++ // Remove the register from the operands. ++ // "op" will be managed by k_Memory. ++ Operands.pop_back(); ++ // Add the memory operand. ++ Operands.push_back( ++ LoongArchOperand::CreateMem(std::move(op), IdVal, S, E, *this)); ++ return MatchOperand_Success; ++} ++ ++bool LoongArchAsmParser::searchSymbolAlias(OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); ++ if (!Sym) ++ return false; ++ ++ SMLoc S = Parser.getTok().getLoc(); ++ if (Sym->isVariable()) { ++ const MCExpr *Expr = Sym->getVariableValue(); ++ if (Expr->getKind() == MCExpr::SymbolRef) { ++ const MCSymbolRefExpr *Ref = static_cast(Expr); ++ StringRef DefSymbol = Ref->getSymbol().getName(); ++ if (DefSymbol.startswith("$")) { ++ OperandMatchResultTy ResTy = ++ matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); ++ if (ResTy == MatchOperand_Success) { ++ Parser.Lex(); ++ return true; ++ } ++ if (ResTy == MatchOperand_ParseFail) ++ llvm_unreachable("Should never ParseFail"); ++ } ++ } ++ } else if (Sym->isUnset()) { ++ // If symbol is unset, it might be created in the `parseSetAssignment` ++ // routine as an alias for a numeric register name. ++ // Lookup in the aliases list. ++ auto Entry = RegisterSets.find(Sym->getName()); ++ if (Entry != RegisterSets.end()) { ++ OperandMatchResultTy ResTy = ++ matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S); ++ if (ResTy == MatchOperand_Success) { ++ Parser.Lex(); ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, ++ StringRef Identifier, ++ SMLoc S) { ++ int Index = matchCPURegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createGPRReg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ Index = matchFPURegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createFGRReg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ Index = matchFCFRRegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createFCFRReg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ Index = matchFCSRRegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createFCSRReg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ Index = matchLSX128RegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createLSX128Reg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ Index = matchLASX256RegisterName(Identifier); ++ if (Index != -1) { ++ Operands.push_back(LoongArchOperand::createLASX256Reg( ++ Index, Identifier, getContext().getRegisterInfo(), S, ++ getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ return MatchOperand_NoMatch; ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, ++ const AsmToken &Token, SMLoc S) { ++ if (Token.is(AsmToken::Identifier)) { ++ LLVM_DEBUG(dbgs() << ".. identifier\n"); ++ StringRef Identifier = Token.getIdentifier(); ++ OperandMatchResultTy ResTy = ++ matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); ++ return ResTy; ++ } else if (Token.is(AsmToken::Integer)) { ++ LLVM_DEBUG(dbgs() << ".. integer\n"); ++ int64_t RegNum = Token.getIntVal(); ++ if (RegNum < 0 || RegNum > 31) { ++ // Show the error, but treat invalid register ++ // number as a normal one to continue parsing ++ // and catch other possible errors. ++ Error(getLexer().getLoc(), "invalid register number"); ++ } ++ Operands.push_back(LoongArchOperand::createNumericReg( ++ RegNum, Token.getString(), getContext().getRegisterInfo(), S, ++ Token.getLoc(), *this)); ++ return MatchOperand_Success; ++ } ++ ++ LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); ++ ++ return MatchOperand_NoMatch; ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { ++ auto Token = getLexer().peekTok(false); ++ return matchAnyRegisterWithoutDollar(Operands, Token, S); ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::parseAnyRegister(OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); ++ ++ auto Token = Parser.getTok(); ++ ++ SMLoc S = Token.getLoc(); ++ ++ if (Token.isNot(AsmToken::Dollar)) { ++ LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); ++ if (Token.is(AsmToken::Identifier)) { ++ if (searchSymbolAlias(Operands)) ++ return MatchOperand_Success; ++ } ++ LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); ++ return MatchOperand_NoMatch; ++ } ++ LLVM_DEBUG(dbgs() << ".. $\n"); ++ ++ OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); ++ if (ResTy == MatchOperand_Success) { ++ Parser.Lex(); // $ ++ Parser.Lex(); // identifier ++ } ++ return ResTy; ++} ++ ++OperandMatchResultTy ++LoongArchAsmParser::parseJumpTarget(OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); ++ ++ SMLoc S = getLexer().getLoc(); ++ ++ // Registers are a valid target and have priority over symbols. ++ OperandMatchResultTy ResTy = parseAnyRegister(Operands); ++ if (ResTy != MatchOperand_NoMatch) ++ return ResTy; ++ ++ // Integers and expressions are acceptable ++ const MCExpr *Expr = nullptr; ++ if (Parser.parseExpression(Expr)) { ++ // We have no way of knowing if a symbol was consumed so we must ParseFail ++ return MatchOperand_ParseFail; ++ } ++ Operands.push_back( ++ LoongArchOperand::CreateImm(Expr, S, getLexer().getLoc(), *this)); ++ return MatchOperand_Success; ++} ++ ++static std::string LoongArchMnemonicSpellCheck(StringRef S, ++ const FeatureBitset &FBS, ++ unsigned VariantID = 0); ++ ++bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, ++ StringRef Name, SMLoc NameLoc, ++ OperandVector &Operands) { ++ MCAsmParser &Parser = getParser(); ++ LLVM_DEBUG(dbgs() << "ParseInstruction\n"); ++ ++ // We have reached first instruction, module directive are now forbidden. ++ getTargetStreamer().forbidModuleDirective(); ++ ++ // Check if we have valid mnemonic ++ if (!mnemonicIsValid(Name)) { ++ FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); ++ std::string Suggestion = LoongArchMnemonicSpellCheck(Name, FBS); ++ return Error(NameLoc, "unknown instruction" + Suggestion); ++ } ++ ++ // First operand in MCInst is instruction mnemonic. ++ Operands.push_back(LoongArchOperand::CreateToken(Name, NameLoc, *this)); ++ ++ // Read the remaining operands. ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ // Read the first operand. ++ if (parseOperand(Operands, Name)) { ++ SMLoc Loc = getLexer().getLoc(); ++ return Error(Loc, "unexpected token in argument list"); ++ } ++ ++ while (getLexer().is(AsmToken::Comma)) { ++ Parser.Lex(); // Eat the comma. ++ // Parse and remember the operand. ++ if (parseOperand(Operands, Name)) { ++ SMLoc Loc = getLexer().getLoc(); ++ return Error(Loc, "unexpected token in argument list"); ++ } ++ } ++ } ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ SMLoc Loc = getLexer().getLoc(); ++ return Error(Loc, "unexpected token in argument list"); ++ } ++ Parser.Lex(); // Consume the EndOfStatement. ++ return false; ++} ++ ++// FIXME: Given that these have the same name, these should both be ++// consistent on affecting the Parser. ++bool LoongArchAsmParser::reportParseError(Twine ErrorMsg) { ++ SMLoc Loc = getLexer().getLoc(); ++ return Error(Loc, ErrorMsg); ++} ++ ++bool LoongArchAsmParser::parseSetAssignment() { ++ StringRef Name; ++ const MCExpr *Value; ++ MCAsmParser &Parser = getParser(); ++ ++ if (Parser.parseIdentifier(Name)) ++ return reportParseError("expected identifier after .set"); ++ ++ if (getLexer().isNot(AsmToken::Comma)) ++ return reportParseError("unexpected token, expected comma"); ++ Lex(); // Eat comma ++ ++ if (!Parser.parseExpression(Value)) { ++ // Parse assignment of an expression including ++ // symbolic registers: ++ // .set $tmp, $BB0-$BB1 ++ // .set r2, $f2 ++ MCSymbol *Sym = getContext().getOrCreateSymbol(Name); ++ Sym->setVariableValue(Value); ++ } else { ++ return reportParseError("expected valid expression after comma"); ++ } ++ ++ return false; ++} ++ ++bool LoongArchAsmParser::parseDirectiveSet() { ++ const AsmToken &Tok = getParser().getTok(); ++ StringRef IdVal = Tok.getString(); ++ SMLoc Loc = Tok.getLoc(); ++ ++ if (IdVal == "bopt") { ++ Warning(Loc, "'bopt' feature is unsupported"); ++ getParser().Lex(); ++ return false; ++ } ++ if (IdVal == "nobopt") { ++ // We're already running in nobopt mode, so nothing to do. ++ getParser().Lex(); ++ return false; ++ } ++ ++ // It is just an identifier, look for an assignment. ++ return parseSetAssignment(); ++} ++ ++bool LoongArchAsmParser::ParseDirective(AsmToken DirectiveID) { ++ // This returns false if this function recognizes the directive ++ // regardless of whether it is successfully handles or reports an ++ // error. Otherwise it returns true to give the generic parser a ++ // chance at recognizing it. ++ ++ MCAsmParser &Parser = getParser(); ++ StringRef IDVal = DirectiveID.getString(); ++ ++ if (IDVal == ".end") { ++ while (getLexer().isNot(AsmToken::Eof)) ++ Parser.Lex(); ++ return false; ++ } ++ ++ if (IDVal == ".set") { ++ parseDirectiveSet(); ++ return false; ++ } ++ ++ if (IDVal == ".llvm_internal_loongarch_reallow_module_directive") { ++ parseInternalDirectiveReallowModule(); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool LoongArchAsmParser::parseInternalDirectiveReallowModule() { ++ // If this is not the end of the statement, report an error. ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ reportParseError("unexpected token, expected end of statement"); ++ return false; ++ } ++ ++ getTargetStreamer().reallowModuleDirective(); ++ ++ getParser().Lex(); // Eat EndOfStatement token. ++ return false; + } + + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { + RegisterMCAsmParser X(getTheLoongArch32Target()); +- RegisterMCAsmParser Y(getTheLoongArch64Target()); ++ RegisterMCAsmParser A(getTheLoongArch64Target()); ++} ++ ++#define GET_REGISTER_MATCHER ++#define GET_MATCHER_IMPLEMENTATION ++#define GET_MNEMONIC_SPELL_CHECKER ++#include "LoongArchGenAsmMatcher.inc" ++ ++bool LoongArchAsmParser::mnemonicIsValid(StringRef Mnemonic) { ++ // Find the appropriate table for this asm variant. ++ const MatchEntry *Start, *End; ++ Start = std::begin(MatchTable0); ++ End = std::end(MatchTable0); ++ ++ // Search the table. ++ auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode()); ++ return MnemonicRange.first != MnemonicRange.second; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt +index 4d8e81aea..8540b97ff 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/CMakeLists.txt +@@ -1,14 +1,15 @@ +-add_llvm_component_group(LoongArch) ++add_llvm_component_group(LoongArch HAS_JIT) + + set(LLVM_TARGET_DEFINITIONS LoongArch.td) + + tablegen(LLVM LoongArchGenAsmMatcher.inc -gen-asm-matcher) + tablegen(LLVM LoongArchGenAsmWriter.inc -gen-asm-writer) ++tablegen(LLVM LoongArchGenCallingConv.inc -gen-callingconv) + tablegen(LLVM LoongArchGenDAGISel.inc -gen-dag-isel) + tablegen(LLVM LoongArchGenDisassemblerTables.inc -gen-disassembler) + tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info) +-tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering) + tablegen(LLVM LoongArchGenMCCodeEmitter.inc -gen-emitter) ++tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering) + tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info) + tablegen(LLVM LoongArchGenSubtargetInfo.inc -gen-subtarget) + +@@ -16,14 +17,20 @@ add_public_tablegen_target(LoongArchCommonTableGen) + + add_llvm_target(LoongArchCodeGen + LoongArchAsmPrinter.cpp +- LoongArchFrameLowering.cpp ++ LoongArchCCState.cpp ++ LoongArchExpandPseudo.cpp + LoongArchInstrInfo.cpp + LoongArchISelDAGToDAG.cpp + LoongArchISelLowering.cpp ++ LoongArchFrameLowering.cpp + LoongArchMCInstLower.cpp ++ LoongArchMachineFunction.cpp ++ LoongArchModuleISelDAGToDAG.cpp + LoongArchRegisterInfo.cpp + LoongArchSubtarget.cpp + LoongArchTargetMachine.cpp ++ LoongArchTargetObjectFile.cpp ++ LoongArchTargetTransformInfo.cpp + + LINK_COMPONENTS + Analysis +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt +index 1cce676cf..864be6313 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt +@@ -2,10 +2,8 @@ add_llvm_component_library(LLVMLoongArchDisassembler + LoongArchDisassembler.cpp + + LINK_COMPONENTS +- LoongArchDesc +- LoongArchInfo +- MC + MCDisassembler ++ LoongArchInfo + Support + + ADD_TO_COMPONENT +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp +index beb757c78..6468a0fc8 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===// ++//===- LoongArchDisassembler.cpp - Disassembler for LoongArch -----------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,140 +6,935 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file implements the LoongArchDisassembler class. ++// This file is part of the LoongArch Disassembler. + // + //===----------------------------------------------------------------------===// + +-#include "MCTargetDesc/LoongArchBaseInfo.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" +-#include "TargetInfo/LoongArchTargetInfo.h" ++#include "LoongArch.h" ++#include "llvm/ADT/ArrayRef.h" + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCDecoderOps.h" + #include "llvm/MC/MCDisassembler/MCDisassembler.h" + #include "llvm/MC/MCInst.h" +-#include "llvm/MC/MCInstrInfo.h" + #include "llvm/MC/MCRegisterInfo.h" + #include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/Support/Compiler.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MathExtras.h" + #include "llvm/MC/TargetRegistry.h" +-#include "llvm/Support/Endian.h" ++#include "llvm/Support/raw_ostream.h" ++#include ++#include + + using namespace llvm; + + #define DEBUG_TYPE "loongarch-disassembler" + +-typedef MCDisassembler::DecodeStatus DecodeStatus; ++using DecodeStatus = MCDisassembler::DecodeStatus; + + namespace { ++ + class LoongArchDisassembler : public MCDisassembler { ++ + public: + LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + ++ bool isFP64() const { return STI.getFeatureBits()[LoongArch::FeatureFP64Bit]; } ++ ++ bool is64Bit() const { return STI.getFeatureBits()[LoongArch::Feature64Bit]; } ++ + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &CStream) const override; + }; +-} // end namespace + +-static MCDisassembler *createLoongArchDisassembler(const Target &T, +- const MCSubtargetInfo &STI, +- MCContext &Ctx) { ++} // end anonymous namespace ++ ++// Forward declare these because the autogenerated code will reference them. ++// Definitions are further down. ++static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeFCFRRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLSX128BRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLSX128HRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLSX128WRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLSX128DRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLASX256BRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLASX256HRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLASX256WRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLASX256DRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeBranchTarget(MCInst &Inst, ++ unsigned Offset, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeJumpTarget(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeMem(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeAMem(MCInst &Inst, unsigned Insn, uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeMemSimm14(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder); ++ ++static DecodeStatus DecodeLSX128Mem(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLSX128Mem13(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLSX128Mem10(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLASX256Mem13(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLASX256Mem10(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLSX128memlsl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLSX128memstl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLASX256memlsl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLASX256memstl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeLASX256Mem(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder); ++ ++static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, ++ uint64_t Address, ++ const void *Decoder); ++ ++template ++static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, ++ uint64_t Address, ++ const void *Decoder); ++ ++template ++static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value, ++ uint64_t Address, ++ const void *Decoder) { ++ return DecodeUImmWithOffsetAndScale(Inst, Value, Address, ++ Decoder); ++} ++ ++template ++static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, ++ uint64_t Address, ++ const void *Decoder); ++ ++/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't ++/// handle. ++template ++static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, ++ const void *Decoder); ++ ++namespace llvm { ++ ++Target &getTheLoongArch32Target(); ++Target &getTheLoongArch64Target(); ++ ++} // end namespace llvm ++ ++static MCDisassembler *createLoongArchDisassembler( ++ const Target &T, ++ const MCSubtargetInfo &STI, ++ MCContext &Ctx) { + return new LoongArchDisassembler(STI, Ctx); + } + + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() { +- // Register the disassembler for each target. ++ // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(), + createLoongArchDisassembler); + TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(), + createLoongArchDisassembler); + } + +-static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, +- uint64_t Address, +- const MCDisassembler *Decoder) { +- if (RegNo >= 32) ++#include "LoongArchGenDisassemblerTables.inc" ++ ++static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { ++ const LoongArchDisassembler *Dis = static_cast(D); ++ const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); ++ if (RC == LoongArch::GPR64RegClassID || RC == LoongArch::GPR32RegClassID) { ++ // sync with the GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td ++ // that just like LoongArchAsmParser.cpp and LoongArchISelLowering.cpp ++ unsigned char indexes[] = { 0, 27, 28, 29, 1, 2, 3, 4, ++ 5, 6, 7, 8, 9, 10, 11, 12, ++ 13, 14, 15, 16, 17, 30, 31, 18, ++ 19, 20, 21, 22, 23, 24, 25, 26 ++ }; ++ assert(RegNo < sizeof(indexes)); ++ return *(RegInfo->getRegClass(RC).begin() + indexes[RegNo]); ++ } ++ return *(RegInfo->getRegClass(RC).begin() + RegNo); ++} ++ ++template ++static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, ++ const void *Decoder) { ++ using DecodeFN = DecodeStatus (*)(MCInst &, unsigned, uint64_t, const void *); ++ ++ // The size of the n field depends on the element size ++ // The register class also depends on this. ++ InsnType tmp = fieldFromInstruction(insn, 17, 5); ++ unsigned NSize = 0; ++ DecodeFN RegDecoder = nullptr; ++ if ((tmp & 0x18) == 0x00) { ++ NSize = 4; ++ RegDecoder = DecodeLSX128BRegisterClass; ++ } else if ((tmp & 0x1c) == 0x10) { ++ NSize = 3; ++ RegDecoder = DecodeLSX128HRegisterClass; ++ } else if ((tmp & 0x1e) == 0x18) { ++ NSize = 2; ++ RegDecoder = DecodeLSX128WRegisterClass; ++ } else if ((tmp & 0x1f) == 0x1c) { ++ NSize = 1; ++ RegDecoder = DecodeLSX128DRegisterClass; ++ } else ++ llvm_unreachable("Invalid encoding"); ++ ++ assert(NSize != 0 && RegDecoder != nullptr); ++ ++ // $vd ++ tmp = fieldFromInstruction(insn, 6, 5); ++ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) ++ return MCDisassembler::Fail; ++ // $vd_in ++ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) ++ return MCDisassembler::Fail; ++ // $n ++ tmp = fieldFromInstruction(insn, 16, NSize); ++ MI.addOperand(MCOperand::createImm(tmp)); ++ // $vs ++ tmp = fieldFromInstruction(insn, 11, 5); ++ if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) ++ return MCDisassembler::Fail; ++ // $n2 ++ MI.addOperand(MCOperand::createImm(0)); ++ ++ return MCDisassembler::Success; ++} ++ ++/// Read four bytes from the ArrayRef and return 32 bit word. ++static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, ++ uint64_t &Size, uint32_t &Insn) { ++ // We want to read exactly 4 Bytes of data. ++ if (Bytes.size() < 4) { ++ Size = 0; + return MCDisassembler::Fail; +- Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo)); ++ } ++ ++ Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | ++ (Bytes[3] << 24); ++ + return MCDisassembler::Success; + } + +-static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, ++DecodeStatus LoongArchDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, ++ ArrayRef Bytes, ++ uint64_t Address, ++ raw_ostream &CStream) const { ++ uint32_t Insn; ++ DecodeStatus Result; ++ Size = 0; ++ ++ // Attempt to read the instruction so that we can attempt to decode it. If ++ // the buffer is not 4 bytes long, let the higher level logic figure out ++ // what to do with a size of zero and MCDisassembler::Fail. ++ Result = readInstruction32(Bytes, Address, Size, Insn); ++ if (Result == MCDisassembler::Fail) ++ return MCDisassembler::Fail; ++ ++ // The only instruction size for standard encoded LoongArch. ++ Size = 4; ++ ++ if (is64Bit()) { ++ LLVM_DEBUG(dbgs() << "Trying LoongArch (GPR64) table (32-bit opcodes):\n"); ++ Result = decodeInstruction(DecoderTableLoongArch32, Instr, Insn, ++ Address, this, STI); ++ if (Result != MCDisassembler::Fail) ++ return Result; ++ } ++ ++ LLVM_DEBUG(dbgs() << "Trying LoongArch32 (GPR32) table (32-bit opcodes):\n"); ++ Result = decodeInstruction(DecoderTableLoongArch3232, Instr, Insn, ++ Address, this, STI); ++ if (Result != MCDisassembler::Fail) ++ return Result; ++ ++ return MCDisassembler::Fail; ++} ++ ++static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, ++ unsigned RegNo, + uint64_t Address, +- const MCDisassembler *Decoder) { +- if (RegNo >= 32) ++ const void *Decoder) { ++ if (RegNo > 31) + return MCDisassembler::Fail; +- Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo)); ++ ++ unsigned Reg = getReg(Decoder, LoongArch::GPR64RegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; + } + +-static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, ++static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, ++ unsigned RegNo, + uint64_t Address, +- const MCDisassembler *Decoder) { +- if (RegNo >= 32) ++ const void *Decoder) { ++ if (RegNo > 31) + return MCDisassembler::Fail; +- Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo)); ++ unsigned Reg = getReg(Decoder, LoongArch::GPR32RegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; + } + +-static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo, ++static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, ++ unsigned RegNo, + uint64_t Address, +- const MCDisassembler *Decoder) { +- if (RegNo >= 8) ++ const void *Decoder) { ++ if (static_cast(Decoder)->is64Bit()) ++ return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); ++ ++ return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); ++} ++ ++static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) + return MCDisassembler::Fail; +- Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo)); ++ unsigned Reg = getReg(Decoder, LoongArch::FGR64RegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; + } + +-static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo, ++static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ ++ unsigned Reg = getReg(Decoder, LoongArch::FGR32RegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, ++ unsigned RegNo, + uint64_t Address, +- const MCDisassembler *Decoder) { +- if (RegNo >= 4) ++ const void *Decoder) { ++ if (RegNo > 31) + return MCDisassembler::Fail; +- Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo)); ++ ++ unsigned Reg = getReg(Decoder, LoongArch::FCSRRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; + } + +-template +-static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, +- int64_t Address, +- const MCDisassembler *Decoder) { +- assert(isUInt(Imm) && "Invalid immediate"); +- Inst.addOperand(MCOperand::createImm(Imm + P)); ++static DecodeStatus DecodeFCFRRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 7) ++ return MCDisassembler::Fail; ++ ++ unsigned Reg = getReg(Decoder, LoongArch::FCFRRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ + return MCDisassembler::Success; + } + +-template +-static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, +- int64_t Address, +- const MCDisassembler *Decoder) { +- assert(isUInt(Imm) && "Invalid immediate"); +- // Sign-extend the number in the bottom bits of Imm, then shift left +- // bits. +- Inst.addOperand(MCOperand::createImm(SignExtend64(Imm) << S)); ++static DecodeStatus DecodeMem(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder) { ++ int Offset = SignExtend32<12>((Insn >> 10) & 0xfff); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ ++ Reg = getReg(Decoder, LoongArch::GPR32RegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ if (Inst.getOpcode() == LoongArch::SC_W || ++ Inst.getOpcode() == LoongArch::SC_D) ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ + return MCDisassembler::Success; + } + +-#include "LoongArchGenDisassemblerTables.inc" ++static DecodeStatus DecodeAMem(MCInst &Inst, unsigned Insn, uint64_t Address, ++ const void *Decoder) { ++ unsigned Rd = fieldFromInstruction(Insn, 0, 5); ++ unsigned Rj = fieldFromInstruction(Insn, 5, 5); ++ unsigned Rk = fieldFromInstruction(Insn, 10, 5); + +-DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size, +- ArrayRef Bytes, +- uint64_t Address, +- raw_ostream &CS) const { +- uint32_t Insn; +- DecodeStatus Result; ++ Rd = getReg(Decoder, LoongArch::GPR32RegClassID, Rd); ++ Rj = getReg(Decoder, LoongArch::GPR32RegClassID, Rj); ++ Rk = getReg(Decoder, LoongArch::GPR32RegClassID, Rk); + +- // We want to read exactly 4 bytes of data because all LoongArch instructions +- // are fixed 32 bits. +- if (Bytes.size() < 4) { +- Size = 0; ++ // Note the operands sequence is "rd,rk,rj". ++ Inst.addOperand(MCOperand::createReg(Rd)); ++ Inst.addOperand(MCOperand::createReg(Rk)); ++ Inst.addOperand(MCOperand::createReg(Rj)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeMemSimm14(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder) { ++ int Offset = SignExtend32<12>((Insn >> 10) & 0x3fff); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ ++ Reg = getReg(Decoder, LoongArch::GPR32RegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ if (Inst.getOpcode() == LoongArch::SC_W || ++ Inst.getOpcode() == LoongArch::SC_D) ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128Mem(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128Mem13(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<13>(fieldFromInstruction(Insn, 5, 13)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128Mem10(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 5, 10)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256Mem13(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<13>(fieldFromInstruction(Insn, 5, 13)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256Mem10(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 5, 10)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128memstl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<8>(fieldFromInstruction(Insn, 10, 8)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ unsigned idx; ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ switch (Inst.getOpcode()) { ++ default: ++ assert(false && "Unexpected instruction"); + return MCDisassembler::Fail; ++ break; ++ case LoongArch::VSTELM_B: ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ idx = fieldFromInstruction(Insn, 18, 4); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::VSTELM_H: ++ Inst.addOperand(MCOperand::createImm(Offset * 2)); ++ idx = fieldFromInstruction(Insn, 18, 3); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::VSTELM_W: ++ Inst.addOperand(MCOperand::createImm(Offset * 4)); ++ idx = fieldFromInstruction(Insn, 18, 2); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::VSTELM_D: ++ Inst.addOperand(MCOperand::createImm(Offset * 8)); ++ idx = fieldFromInstruction(Insn, 18, 1); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; + } + +- Insn = support::endian::read32le(Bytes.data()); +- // Calling the auto-generated decoder function. +- Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); +- Size = 4; ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128memlsl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ ++ int Offset; ++ unsigned Reg, Base; ++ switch (Inst.getOpcode()) { ++ default: ++ assert(false && "Unexpected instruction"); ++ return MCDisassembler::Fail; ++ break; ++ case LoongArch::VLDREPL_B: ++ ++ Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ break; ++ case LoongArch::VLDREPL_H: ++ ++ Offset = SignExtend32<11>(fieldFromInstruction(Insn, 10, 11)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128HRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 2)); ++ break; ++ case LoongArch::VLDREPL_W: ++ ++ Offset = SignExtend32<10>(fieldFromInstruction(Insn, 10, 10)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 4)); ++ break; ++ case LoongArch::VLDREPL_D: ++ ++ Offset = SignExtend32<9>(fieldFromInstruction(Insn, 10, 9)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 8)); ++ break; ++ } ++ ++ return MCDisassembler::Success; ++} ++static DecodeStatus DecodeLASX256Mem(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256memstl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { ++ int Offset = SignExtend32<8>(fieldFromInstruction(Insn, 10, 8)); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ unsigned idx; ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ switch (Inst.getOpcode()) { ++ default: ++ assert(false && "Unexpected instruction"); ++ return MCDisassembler::Fail; ++ break; ++ case LoongArch::XVSTELM_B: ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ idx = fieldFromInstruction(Insn, 18, 5); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::XVSTELM_H: ++ Inst.addOperand(MCOperand::createImm(Offset * 2)); ++ idx = fieldFromInstruction(Insn, 18, 4); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::XVSTELM_W: ++ Inst.addOperand(MCOperand::createImm(Offset * 4)); ++ idx = fieldFromInstruction(Insn, 18, 3); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ case LoongArch::XVSTELM_D: ++ Inst.addOperand(MCOperand::createImm(Offset * 8)); ++ idx = fieldFromInstruction(Insn, 18, 2); ++ Inst.addOperand(MCOperand::createImm(idx)); ++ break; ++ } ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256memlsl(MCInst &Inst, unsigned Insn, ++ uint64_t Address, const void *Decoder) { + +- return Result; ++ int Offset; ++ unsigned Reg, Base; ++ switch (Inst.getOpcode()) { ++ default: ++ assert(false && "Unexpected instruction"); ++ return MCDisassembler::Fail; ++ break; ++ case LoongArch::XVLDREPL_B: ++ ++ Offset = SignExtend32<12>(fieldFromInstruction(Insn, 10, 12)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ break; ++ case LoongArch::XVLDREPL_H: ++ ++ Offset = SignExtend32<11>(fieldFromInstruction(Insn, 10, 11)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256HRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 2)); ++ break; ++ case LoongArch::XVLDREPL_W: ++ ++ Offset = SignExtend32<10>(fieldFromInstruction(Insn, 10, 10)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 4)); ++ break; ++ case LoongArch::XVLDREPL_D: ++ ++ Offset = SignExtend32<9>(fieldFromInstruction(Insn, 10, 9)); ++ Reg = fieldFromInstruction(Insn, 0, 5); ++ Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset * 8)); ++ break; ++ } ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeFMem(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder) { ++ int Offset = SignExtend32<12>((Insn >> 10) & 0xffff); ++ unsigned Reg = fieldFromInstruction(Insn, 0, 5); ++ unsigned Base = fieldFromInstruction(Insn, 5, 5); ++ Reg = getReg(Decoder, LoongArch::FGR64RegClassID, Reg); ++ Base = getReg(Decoder, LoongArch::GPR32RegClassID, Base); ++ ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ Inst.addOperand(MCOperand::createReg(Base)); ++ Inst.addOperand(MCOperand::createImm(Offset)); ++ ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128BRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LSX128BRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128HRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LSX128HRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128WRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LSX128WRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLSX128DRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LSX128DRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256BRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LASX256BRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256HRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LASX256HRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256WRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LASX256WRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeLASX256DRegisterClass(MCInst &Inst, unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = getReg(Decoder, LoongArch::LASX256DRegClassID, RegNo); ++ Inst.addOperand(MCOperand::createReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeBranchTarget(MCInst &Inst, ++ unsigned Offset, ++ uint64_t Address, ++ const void *Decoder) { ++ int32_t BranchOffset; ++ // Similar to LoongArchAsmParser::processInstruction, decode the branch target ++ // for different instructions. ++ switch (Inst.getOpcode()) { ++ default: ++ llvm_unreachable(""); ++ case LoongArch::BEQ: ++ case LoongArch::BNE: ++ case LoongArch::BLT: ++ case LoongArch::BGE: ++ case LoongArch::BLTU: ++ case LoongArch::BGEU: ++ BranchOffset = (SignExtend32<16>(Offset) * 4); ++ break; ++ case LoongArch::BEQZ: ++ case LoongArch::BNEZ: ++ case LoongArch::BCEQZ: ++ case LoongArch::BCNEZ: ++ BranchOffset = (SignExtend32<21>(Offset) * 4); ++ break; ++ case LoongArch::B: ++ case LoongArch::BL: ++ BranchOffset = (SignExtend32<26>(Offset) * 4); ++ break; ++ } ++ Inst.addOperand(MCOperand::createImm(BranchOffset)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeJumpTarget(MCInst &Inst, ++ unsigned Insn, ++ uint64_t Address, ++ const void *Decoder) { ++ unsigned hi10 = fieldFromInstruction(Insn, 0, 10); ++ unsigned lo16 = fieldFromInstruction(Insn, 10, 16); ++ int32_t JumpOffset = SignExtend32<28>((hi10 << 16 | lo16) << 2); ++ Inst.addOperand(MCOperand::createImm(JumpOffset)); ++ return MCDisassembler::Success; ++} ++ ++template ++static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, ++ uint64_t Address, ++ const void *Decoder) { ++ Value &= ((1 << Bits) - 1); ++ Value *= Scale; ++ Inst.addOperand(MCOperand::createImm(Value + Offset)); ++ return MCDisassembler::Success; ++} ++ ++template ++static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, ++ uint64_t Address, ++ const void *Decoder) { ++ int32_t Imm = SignExtend32(Value) * ScaleBy; ++ Inst.addOperand(MCOperand::createImm(Imm + Offset)); ++ return MCDisassembler::Success; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h +index e6c9c24dd..73fd4a628 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.h +@@ -1,4 +1,4 @@ +-//===-- LoongArch.h - Top-level interface for LoongArch ---------*- C++ -*-===// ++//===-- LoongArch.h - Top-level interface for LoongArch representation ----*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,33 +6,32 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file contains the entry points for global functions defined in the LLVM +-// LoongArch back-end. ++// This file contains the entry points for global functions defined in ++// the LLVM LoongArch back-end. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H + +-#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" + #include "llvm/Target/TargetMachine.h" + + namespace llvm { +-class LoongArchTargetMachine; +-class AsmPrinter; +-class FunctionPass; +-class MCInst; +-class MCOperand; +-class MachineInstr; +-class MachineOperand; ++ class LoongArchTargetMachine; ++ class ModulePass; ++ class FunctionPass; ++ class LoongArchSubtarget; ++ class LoongArchTargetMachine; ++ class InstructionSelector; ++ class PassRegistry; + +-bool lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, +- AsmPrinter &AP); +-bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, +- MCOperand &MCOp, +- const AsmPrinter &AP); ++ FunctionPass *createLoongArchModuleISelDagPass(); ++ FunctionPass *createLoongArchOptimizePICCallPass(); ++ FunctionPass *createLoongArchBranchExpansion(); ++ FunctionPass *createLoongArchExpandPseudoPass(); + +-FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM); +-} // end namespace llvm ++ void initializeLoongArchBranchExpansionPass(PassRegistry &); ++} // end namespace llvm; + +-#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td +index bf465c27e..703c1ba50 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch.td +@@ -1,139 +1,107 @@ +-//===-- LoongArch.td - Describe the LoongArch Target -------*- tablegen -*-===// ++//===-- LoongArch.td - Describe the LoongArch Target Machine ---------*- tablegen -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. + // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + // + //===----------------------------------------------------------------------===// ++// This is the top level entry point for the LoongArch target. ++//===----------------------------------------------------------------------===// ++ ++//===----------------------------------------------------------------------===// ++// Target-independent interfaces ++//===----------------------------------------------------------------------===// + + include "llvm/Target/Target.td" + ++// The overall idea of the PredicateControl class is to chop the Predicates list ++// into subsets that are usually overridden independently. This allows ++// subclasses to partially override the predicates of their superclasses without ++// having to re-add all the existing predicates. ++class PredicateControl { ++ // Predicates for the encoding scheme in use such as HasStdEnc ++ list EncodingPredicates = []; ++ // Predicates for the GPR size such as is64Bit ++ list GPRPredicates = []; ++ // Predicates for the FGR size and layout such as IsFP64bit ++ list FGRPredicates = []; ++ // Predicates for the instruction group membership such as ISA's. ++ list InsnPredicates = []; ++ // Predicate for the ISA extension that an instruction belongs to. ++ list ExtPredicate = []; ++ // Predicate for marking the instruction as usable in hard-float mode only. ++ list HardFloatPredicate = []; ++ // Predicates for anything else ++ list AdditionalPredicates = []; ++ list Predicates = !listconcat(EncodingPredicates, ++ GPRPredicates, ++ FGRPredicates, ++ InsnPredicates, ++ HardFloatPredicate, ++ ExtPredicate, ++ AdditionalPredicates); ++} ++ ++// Like Requires<> but for the AdditionalPredicates list ++class AdditionalRequires preds> { ++ list AdditionalPredicates = preds; ++} ++ + //===----------------------------------------------------------------------===// +-// LoongArch subtarget features and instruction predicates. ++// LoongArch Subtarget features // + //===----------------------------------------------------------------------===// + +-// LoongArch is divided into two versions, the 32-bit version (LA32) and the +-// 64-bit version (LA64). +-def Feature64Bit +- : SubtargetFeature<"64bit", "HasLA64", "true", +- "LA64 Basic Integer and Privilege Instruction Set">; +-def IsLA64 +- : Predicate<"Subtarget->is64Bit()">, +- AssemblerPredicate<(all_of Feature64Bit), +- "LA64 Basic Integer and Privilege Instruction Set">; +-def IsLA32 +- : Predicate<"!Subtarget->is64Bit()">, +- AssemblerPredicate<(all_of(not Feature64Bit)), +- "LA32 Basic Integer and Privilege Instruction Set">; +- +-defvar LA32 = DefaultMode; +-def LA64 : HwMode<"+64bit">; +- +-// Single Precision floating point +-def FeatureBasicF +- : SubtargetFeature<"f", "HasBasicF", "true", +- "'F' (Single-Precision Floating-Point)">; +-def HasBasicF +- : Predicate<"Subtarget->hasBasicF()">, +- AssemblerPredicate<(all_of FeatureBasicF), +- "'F' (Single-Precision Floating-Point)">; +- +-// Double Precision floating point +-def FeatureBasicD +- : SubtargetFeature<"d", "HasBasicD", "true", +- "'D' (Double-Precision Floating-Point)", +- [FeatureBasicF]>; +-def HasBasicD +- : Predicate<"Subtarget->hasBasicD()">, +- AssemblerPredicate<(all_of FeatureBasicD), +- "'D' (Double-Precision Floating-Point)">; +- +-// Loongson SIMD eXtension (LSX) +-def FeatureExtLSX +- : SubtargetFeature<"lsx", "HasExtLSX", "true", +- "'LSX' (Loongson SIMD Extension)", [FeatureBasicD]>; +-def HasExtLSX +- : Predicate<"Subtarget->hasExtLSX()">, +- AssemblerPredicate<(all_of FeatureExtLSX), +- "'LSX' (Loongson SIMD Extension)">; +- +-// Loongson Advanced SIMD eXtension (LASX) +-def FeatureExtLASX +- : SubtargetFeature<"lasx", "HasExtLASX", "true", +- "'LASX' (Loongson Advanced SIMD Extension)", +- [FeatureExtLSX]>; +-def HasExtLASX +- : Predicate<"Subtarget->hasExtLASX()">, +- AssemblerPredicate<(all_of FeatureExtLASX), +- "'LASX' (Loongson Advanced SIMD Extension)">; +- +-// Loongson VirtualiZation (LVZ) +-def FeatureExtLVZ +- : SubtargetFeature<"lvz", "HasExtLVZ", "true", +- "'LVZ' (Loongson Virtualization Extension)">; +-def HasExtLVZ +- : Predicate<"Subtarget->hasExtLVZ()">, +- AssemblerPredicate<(all_of FeatureExtLVZ), +- "'LVZ' (Loongson Virtualization Extension)">; +- +-// Loongson Binary Translation (LBT) +-def FeatureExtLBT +- : SubtargetFeature<"lbt", "HasExtLBT", "true", +- "'LBT' (Loongson Binary Translation Extension)">; +-def HasExtLBT +- : Predicate<"Subtarget->hasExtLBT()">, +- AssemblerPredicate<(all_of FeatureExtLBT), +- "'LBT' (Loongson Binary Translation Extension)">; +- ++def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", ++ "Support 64-bit FP registers">; ++def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", ++ "true", "Only supports single precision float">; ++def FeatureSoftFloat : SubtargetFeature<"soft-float", "IsSoftFloat", "true", ++ "Does not support floating point instructions">; ++def Feature64Bit : SubtargetFeature<"64bit", "HasLA64", "true", ++ "Support LA64 ISA", ++ [FeatureFP64Bit]>; ++def FeatureLSX : SubtargetFeature<"lsx", "HasLSX", "true", "Support LSX">; ++ ++def FeatureLASX : SubtargetFeature<"lasx", "HasLASX", "true", "Support LASX", [FeatureLSX]>; ++ ++def FeatureUnalignedAccess ++ : SubtargetFeature<"unaligned-access", "UnalignedAccess", "true", ++ "Allow all unaligned memory access">; + //===----------------------------------------------------------------------===// +-// Registers, instruction descriptions ... ++// Register File, Calling Conv, Instruction Descriptions + //===----------------------------------------------------------------------===// + + include "LoongArchRegisterInfo.td" +-include "LoongArchCallingConv.td" + include "LoongArchInstrInfo.td" ++include "LoongArchCallingConv.td" ++ ++def LoongArchInstrInfo : InstrInfo; + + //===----------------------------------------------------------------------===// + // LoongArch processors supported. + //===----------------------------------------------------------------------===// + +-def : ProcessorModel<"generic-la32", NoSchedModel, []>; +-def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit]>; ++def : ProcessorModel<"la264", NoSchedModel, [Feature64Bit]>; + +-def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit, +- FeatureExtLASX, +- FeatureExtLVZ, +- FeatureExtLBT]>; ++def : ProcessorModel<"la364", NoSchedModel, [Feature64Bit]>; + +-//===----------------------------------------------------------------------===// +-// Define the LoongArch target. +-//===----------------------------------------------------------------------===// +- +-def LoongArchInstrInfo : InstrInfo { +- // guess mayLoad, mayStore, and hasSideEffects +- // This option is a temporary migration help. It will go away. +- let guessInstructionProperties = 1; +-} ++def : ProcessorModel<"la464", NoSchedModel, ++ [Feature64Bit, FeatureUnalignedAccess]>; + + def LoongArchAsmParser : AsmParser { +- let ShouldEmitMatchRegisterAltName = 1; +- let AllowDuplicateRegisterNames = 1; ++ let ShouldEmitMatchRegisterName = 0; + } + + def LoongArchAsmParserVariant : AsmParserVariant { + int Variant = 0; ++ + // Recognize hard coded registers. + string RegisterPrefix = "$"; + } + +-def LoongArchAsmWriter : AsmWriter { +- int PassSubtarget = 1; +-} +- + def LoongArch : Target { + let InstructionSet = LoongArchInstrInfo; + let AssemblyParsers = [LoongArchAsmParser]; + let AssemblyParserVariants = [LoongArchAsmParserVariant]; +- let AssemblyWriters = [LoongArchAsmWriter]; + let AllowRegisterRenaming = 1; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td +new file mode 100644 +index 000000000..f53471995 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArch32InstrInfo.td +@@ -0,0 +1,717 @@ ++//===- LoongArch32InstrInfo.td - Target Description for LoongArch Target -*- tablegen -*-=// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file describes LoongArch32 instructions. ++// ++//===----------------------------------------------------------------------===// ++ ++//===---------------------------------------------------------------------===/ ++// Instruction Definitions. ++//===---------------------------------------------------------------------===/ ++ ++let DecoderNamespace = "LoongArch32" in { ++ /// ++ /// R2 ++ /// ++ def CLO_W : Count1<"clo.w", GPR32Opnd, ctlz>, R2I<0b00100>; ++ def CLZ_W : Int_Reg2<"clz.w", GPR32Opnd, ctlz>, R2I<0b00101>; ++ def CTO_W : Count1<"cto.w", GPR32Opnd, cttz>, R2I<0b00110>; ++ def CTZ_W : Int_Reg2<"ctz.w", GPR32Opnd, cttz>, R2I<0b00111>; ++ ++ def REVB_2H : Int_Reg2<"revb.2h", GPR32Opnd>, R2I<0b01100>;//see below bswap pattern ++ ++ def BITREV_4B : Int_Reg2<"bitrev.4b", GPR32Opnd>, R2I<0b10010>; ++ def BITREV_W : Int_Reg2<"bitrev.w", GPR32Opnd, bitreverse>, R2I<0b10100>; ++ ++ let isCodeGenOnly = 1 in { ++ def EXT_W_H32 : SignExtInReg<"ext.w.h", GPR32Opnd, i16>, R2I<0b10110>; ++ def EXT_W_B32 : SignExtInReg<"ext.w.b", GPR32Opnd, i8>, R2I<0b10111>; ++ ++ } ++ ++ def CPUCFG : Int_Reg2<"cpucfg", GPR32Opnd, int_loongarch_cpucfg>, R2I<0b11011>; ++ def RDTIMEL_W32 : Int_Reg2_Rdtime<"rdtimel.w", GPR32Opnd>, R2I<0b11000>; ++ def RDTIMEH_W32 : Int_Reg2_Rdtime<"rdtimeh.w", GPR32Opnd>, R2I<0b11001>; ++ ++ /// ++ /// R3 ++ /// ++ def ADD_W : Int_Reg3<"add.w", GPR32Opnd, add>, R3I<0b0100000>; ++ def SUB_W : Int_Reg3<"sub.w", GPR32Opnd, sub>, R3I<0b0100010>; ++ ++ let isCodeGenOnly = 1 in { ++ def SLT32 : SetCC_R<"slt", GPR32Opnd, setlt>, R3I<0b0100100>; ++ def SLTU32 : SetCC_R<"sltu", GPR32Opnd, setult>, R3I<0b0100101>; ++ def MASKEQZ32 : Int_Reg3<"maskeqz", GPR32Opnd>, R3I<0b0100110>;//see below patterns ++ def MASKNEZ32 : Int_Reg3<"masknez", GPR32Opnd>, R3I<0b0100111>;//see below patterns ++ ++ def NOR32 : Nor<"nor", GPR32Opnd>, R3I<0b0101000>; ++ def AND32 : Int_Reg3<"and", GPR32Opnd, and>, R3I<0b0101001>; ++ def OR32 : Int_Reg3<"or", GPR32Opnd, or>, R3I<0b0101010>; ++ def XOR32 : Int_Reg3<"xor", GPR32Opnd, xor>, R3I<0b0101011>; ++ def ANDN32 : Int_Reg3<"andn", GPR32Opnd>, R3I<0b0101101>; ++ def ORN32 : Int_Reg3<"orn", GPR32Opnd>, R3I<0b0101100>; ++ } ++ ++ def SLL_W : Shift_Var<"sll.w", GPR32Opnd, shl>, R3I<0b0101110>; ++ def SRL_W : Shift_Var<"srl.w", GPR32Opnd, srl>, R3I<0b0101111>; ++ def SRA_W : Shift_Var<"sra.w", GPR32Opnd, sra>, R3I<0b0110000>; ++ def ROTR_W: Shift_Var<"rotr.w", GPR32Opnd, rotr>, R3I<0b0110110>; ++ ++ def MUL_W : Int_Reg3<"mul.w", GPR32Opnd, mul>, R3I<0b0111000>; ++ def MULH_W : Int_Reg3<"mulh.w", GPR32Opnd, mulhs>, R3I<0b0111001>; ++ def MULH_WU : Int_Reg3<"mulh.wu", GPR32Opnd, mulhu>, R3I<0b0111010>; ++ ++let usesCustomInserter = 1 in { ++ def DIV_W : Int_Reg3<"div.w", GPR32Opnd, sdiv>, R3I<0b1000000>; ++ def MOD_W : Int_Reg3<"mod.w", GPR32Opnd, srem>, R3I<0b1000001>; ++ def DIV_WU : Int_Reg3<"div.wu", GPR32Opnd, udiv>, R3I<0b1000010>; ++ def MOD_WU : Int_Reg3<"mod.wu", GPR32Opnd, urem>, R3I<0b1000011>; ++} ++ ++ def CRC_W_B_W : Int_Reg3<"crc.w.b.w", GPR32Opnd, int_loongarch_crc_w_b_w>, R3I<0b1001000>; ++ def CRC_W_H_W : Int_Reg3<"crc.w.h.w", GPR32Opnd, int_loongarch_crc_w_h_w>, R3I<0b1001001>; ++ def CRC_W_W_W : Int_Reg3<"crc.w.w.w", GPR32Opnd, int_loongarch_crc_w_w_w>, R3I<0b1001010>; ++ def CRCC_W_B_W : Int_Reg3<"crcc.w.b.w", GPR32Opnd, int_loongarch_crcc_w_b_w>, R3I<0b1001100>; ++ def CRCC_W_H_W : Int_Reg3<"crcc.w.h.w", GPR32Opnd, int_loongarch_crcc_w_h_w>, R3I<0b1001101>; ++ def CRCC_W_W_W : Int_Reg3<"crcc.w.w.w", GPR32Opnd, int_loongarch_crcc_w_w_w>, R3I<0b1001110>; ++ /// ++ /// SLLI ++ /// ++ def SLLI_W : Shift_Imm32<"slli.w", GPR32Opnd, shl>, R2_IMM5<0b00>; ++ def SRLI_W : Shift_Imm32<"srli.w", GPR32Opnd, srl>, R2_IMM5<0b01>; ++ def SRAI_W : Shift_Imm32<"srai.w", GPR32Opnd, sra>, R2_IMM5<0b10>; ++ def ROTRI_W : Shift_Imm32<"rotri.w", GPR32Opnd, rotr>, R2_IMM5<0b11>; ++ /// ++ /// Misc ++ /// ++ def ALSL_W : Reg3_Sa<"alsl.w", GPR32Opnd, uimm2_plus1>, R3_SA2<0b00010> { ++ let Pattern = [(set GPR32Opnd:$rd, ++ (add GPR32Opnd:$rk, (shl GPR32Opnd:$rj, immZExt2Alsl:$sa)))]; ++ } ++ def BYTEPICK_W : Reg3_Sa<"bytepick.w", GPR32Opnd, uimm2>, R3_SA2<0b00100>;//pattern:[] ++ ++ def BREAK : Code15<"break", int_loongarch_break>, CODE15<0b1010100>; ++ def SYSCALL : Code15<"syscall", int_loongarch_syscall>, CODE15<0b1010110>; ++ def TRAP : TrapBase; ++ ++ def BSTRINS_W : InsBase_32<"bstrins.w", GPR32Opnd, uimm5, LoongArchBstrins>, ++ INSERT_BIT32<0>; ++ def BSTRPICK_W : PickBase_32<"bstrpick.w", GPR32Opnd, uimm5, LoongArchBstrpick>, ++ INSERT_BIT32<1>; ++ ++ /// ++ /// R2_IMM12 ++ /// ++ let isCodeGenOnly = 1 in { ++ def SLTI32 : SetCC_I<"slti", GPR32Opnd, simm12_32>, R2_IMM12<0b000>; //PatFrag ++ def SLTUI32 : SetCC_I<"sltui", GPR32Opnd, simm12_32>, R2_IMM12<0b001>; //PatFrag ++ } ++ def ADDI_W : Int_Reg2_Imm12<"addi.w", GPR32Opnd, simm12_32, add>, R2_IMM12<0b010>; ++ ++ let isCodeGenOnly = 1 in { ++ def ANDI32 : Int_Reg2_Imm12<"andi", GPR32Opnd, uimm12_32, and>, R2_IMM12<0b101>; ++ def ORI32 : Int_Reg2_Imm12<"ori", GPR32Opnd, uimm12_32, or>, R2_IMM12<0b110>; ++ def XORI32 : Int_Reg2_Imm12<"xori", GPR32Opnd, uimm12_32, xor>, R2_IMM12<0b111>; ++ } ++ ++ /// ++ /// Privilege Instructions ++ /// ++ def CSRRD32 : CSR<"csrrd", GPR32Opnd, uimm14_32, int_loongarch_csrrd_w>, R1_CSR<0b0000000000100>; ++ def CSRWR32 : CSRW<"csrwr", GPR32Opnd, uimm14_32, int_loongarch_csrwr_w>, R1_CSR<0b0000100000100>; ++ def CSRXCHG32 : CSRX<"csrxchg", GPR32Opnd, uimm14_32, int_loongarch_csrxchg_w>, R2_CSR<0b00000100>; ++ def IOCSRRD_B32 : Int_Reg2<"iocsrrd.b", GPR32Opnd, int_loongarch_iocsrrd_b>, R2P<0b000>; ++ def IOCSRRD_H32 : Int_Reg2<"iocsrrd.h", GPR32Opnd, int_loongarch_iocsrrd_h>, R2P<0b001>; ++ def IOCSRRD_W32 : Int_Reg2<"iocsrrd.w", GPR32Opnd, int_loongarch_iocsrrd_w>, R2P<0b010>; ++ def IOCSRWR_B32 : Int_Reg2_Iocsrwr<"iocsrwr.b", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_b>, R2P<0b100>; ++ def IOCSRWR_H32 : Int_Reg2_Iocsrwr<"iocsrwr.h", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_h>, R2P<0b101>; ++ def IOCSRWR_W32 : Int_Reg2_Iocsrwr<"iocsrwr.w", GPR32Opnd, GPR32Opnd, int_loongarch_iocsrwr_w>, R2P<0b110>; ++ def CACOP32 : CAC<"cacop", GPR32Opnd, simm12_32, int_loongarch_cacop_w>, R1_CACHE; ++ def LDDIR32 : LEVEL<"lddir", GPR32Opnd>, R2_LEVEL<0b00000110010000>; ++ def LDPTE32 : SEQ<"ldpte", GPR32Opnd>, R1_SEQ<0b00000110010001>; ++ ++ //def WAIT : Wait<"wait">; ++ // ++ //def IOCSRRD_D : R2P<0b011>, Int_Reg2<"iocsrrd.d", GPR32Opnd>; ++ //def IOCSRWR_D : R2P<0b111>, Int_Reg2<"iocsrwr.d", GPR32Opnd>; ++ // ++ //def TLBINV : IMM32<0b001000>, OP32<"tlbinv">; ++ //def TLBFLUSH : IMM32<0b001001>, OP32<"tlbflush">; ++ //def TLBP : IMM32<0b001010>, OP32<"tlbp">; ++ //def TLBR : IMM32<0b001011>, OP32<"tlbr">; ++ //def TLBWI : IMM32<0b001100>, OP32<"tlbwi">; ++ //def TLBWR : IMM32<0b001101>, OP32<"tlbwr">; ++ ++ /// ++ /// R1_IMM20 ++ /// ++ let isCodeGenOnly = 1 in { ++ def LU12I_W32 : SI20<"lu12i.w", GPR32Opnd, simm20_32>, R1_SI20<0b0001010>; ++ def PCADDI32 : SI20<"pcaddi", GPR32Opnd, simm20_32>, R1_SI20<0b0001100>; ++ def PCALAU12I32 : SI20<"pcalau12i", GPR32Opnd, simm20_32>, R1_SI20<0b0001101>; ++ def PCADDU12I32 : SI20<"pcaddu12i", GPR32Opnd, simm20_32>, R1_SI20<0b0001110>; ++ } ++ ++ let isCodeGenOnly = 1 in { ++ def BEQZ32 : Beqz<"beqz", brtarget, seteq, GPR32Opnd>, R1_IMM21BEQZ<0b010000>; ++ def BNEZ32 : Beqz<"bnez", brtarget, setne, GPR32Opnd>, R1_IMM21BEQZ<0b010001>; ++ ++ def JIRL32 : FJirl<"jirl", calltarget, GPR32Opnd>, R2_IMM16JIRL; ++ ++ def B32 : JumpFB, IMM26B<0b010100>; ++ ++ def BEQ32 : Beq<"beq", brtarget, seteq, GPR32Opnd>, R2_IMM16BEQ<0b010110>; ++ def BNE32 : Beq<"bne", brtarget, setne, GPR32Opnd>, R2_IMM16BEQ<0b010111>; ++ def BLT32 : Beq<"blt", brtarget, setlt, GPR32Opnd>, R2_IMM16BEQ<0b011000>; ++ def BGE32 : Beq<"bge", brtarget, setge, GPR32Opnd>, R2_IMM16BEQ<0b011001>; ++ def BLTU32 : Beq<"bltu", brtarget, setult, GPR32Opnd>, R2_IMM16BEQ<0b011010>; ++ def BGEU32 : Beq<"bgeu", brtarget, setuge, GPR32Opnd>, R2_IMM16BEQ<0b011011>; ++ } ++ ++ /// ++ /// Mem access ++ /// ++ def LL_W : LLBase<"ll.w", GPR32Opnd, mem_simm14_lsl2>, LL_SC<0b000>; ++ def SC_W : SCBase<"sc.w", GPR32Opnd, mem_simm14_lsl2>, LL_SC<0b001>; ++ ++ def PRELD_Raw32 : Preld_Raw<"preld", GPR32Opnd>, PRELD_FM; ++ ++ let isCodeGenOnly = 1 in { ++ def LD_B32 : Ld<"ld.b", GPR32Opnd, mem_simmptr, sextloadi8>, LOAD_STORE<0b0000>; ++ def LD_H32 : Ld<"ld.h", GPR32Opnd, mem_simmptr, sextloadi16, addrDefault>, LOAD_STORE<0b0001>; ++ def LD_W32 : Ld<"ld.w", GPR32Opnd, mem, load, addrDefault>, LOAD_STORE<0b0010>; ++ def ST_B32 : St<"st.b", GPR32Opnd, mem, truncstorei8>, LOAD_STORE<0b0100>; ++ def ST_H32 : St<"st.h", GPR32Opnd, mem, truncstorei16>, LOAD_STORE<0b0101>; ++ def ST_W32 : St<"st.w", GPR32Opnd, mem, store>, LOAD_STORE<0b0110>; ++ def LD_BU32 : Ld<"ld.bu", GPR32Opnd, mem_simmptr, zextloadi8, addrDefault>, LOAD_STORE<0b1000>; ++ def LD_HU32 : Ld<"ld.hu", GPR32Opnd, mem_simmptr, zextloadi16>, LOAD_STORE<0b1001>; ++ ++ def PRELD32 : Preld<"preld", mem, GPR32Opnd>, PRELD_FM; ++ ++ def LDPTR_W32 : LdPtr<"ldptr.w", GPR32Opnd>, LL_SC<0b100>; ++ def STPTR_W32 : StPtr<"stptr.w", GPR32Opnd>, LL_SC<0b101>; ++ } ++ ++ def IBAR : Bar<"ibar", int_loongarch_ibar>, BAR_FM<1>; ++ def DBAR : Bar<"dbar", int_loongarch_dbar>, BAR_FM<0>; ++ ++ def LONG_BRANCH_ADDIW : LoongArchPseudo<(outs GPR32Opnd:$dst), ++ (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; ++ ++ def LONG_BRANCH_ADDIW2Op : LoongArchPseudo<(outs GPR32Opnd:$dst), ++ (ins GPR32Opnd:$src, brtarget:$tgt), []>; ++ ++ def PseudoReturn : PseudoReturnBase; ++ ++ let isCodeGenOnly = 1 in { ++ def LDX_W32 : LDX_FT_LA<"ldx.w", GPR32Opnd, load>, ++ R3MI<0b00010000>; ++ def LDX_HU32 : LDX_FT_LA<"ldx.hu", GPR32Opnd, extloadi16>, ++ R3MI<0b01001000>; ++ def LDX_BU32 : LDX_FT_LA<"ldx.bu", GPR32Opnd, extloadi8>, ++ R3MI<0b01000000>; ++ def STX_W32 : STX_FT_LA<"stx.w", GPR32Opnd, store>, ++ R3MI<0b00110000>; ++ def LDX_H32 : LDX_FT_LA<"ldx.h", GPR32Opnd, sextloadi16>, ++ R3MI<0b00001000>; ++ def LDX_B32 : LDX_FT_LA<"ldx.b", GPR32Opnd, sextloadi8>, ++ R3MI<0b00000000>; ++ def STX_B32 : STX_FT_LA<"stx.b", GPR32Opnd, truncstorei8>, ++ R3MI<0b00100000>; ++ def STX_H32 : STX_FT_LA<"stx.h", GPR32Opnd, truncstorei16>, ++ R3MI<0b00101000>; ++ } ++} ++ ++def LEA_ADDI_W: EffectiveAddress<"addi.w", GPR32Opnd>, LEA_ADDI_FM<0b010>; ++ ++def : LoongArchPat<(LoongArchAddress (i32 tglobaladdr:$in)), ++ (ADDI_W (PCADDU12I32 tglobaladdr:$in) ,0)>,GPR_32; ++def : LoongArchPat<(LoongArchAddress (i32 tblockaddress:$in)), ++ (ADDI_W (PCADDU12I32 tblockaddress:$in),0)>, GPR_32; ++def : LoongArchPat<(LoongArchAddress (i32 tjumptable:$in)), ++ (ADDI_W (PCADDU12I32 tjumptable:$in),0)>, GPR_32; ++def : LoongArchPat<(LoongArchAddress (i32 texternalsym:$in)), ++ (ADDI_W (PCADDU12I32 texternalsym:$in),0)>, GPR_32; ++ ++//===----------------------------------------------------------------------===// ++// Arbitrary patterns that map to one or more instructions ++//===----------------------------------------------------------------------===// ++ ++let isCodeGenOnly = 1 in { ++ def REVB_2W_32 : Int_Reg2<"revb.2w", GPR32Opnd>, R2I<0b01110>; ++ def REVH_2W_32 : Int_Reg2<"revh.2w", GPR32Opnd>, R2I<0b10000>; ++} ++ ++// bswap pattern ++def : LoongArchPat<(bswap GPR32:$rj), (ROTRI_W (REVB_2H GPR32:$rj), 16)>; ++//def : LoongArchPat<(bswap GPR32:$rj), (REVB_2W_32 GPR32:$rj)>; ++//def : LoongArchPat<(bswap GPR32:$rj), (REVH_2W_32 (REVB_2H GPR32:$rj))>; ++ ++// i32 selects ++multiclass SelectInt_Pats { ++ ++// reg, immz ++def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, RC:$f), ++ (OROp (MASKNEZOp RC:$t, RC:$cond), (MASKEQZOp RC:$f, RC:$cond))>; ++def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), RC:$t, RC:$f), ++ (OROp (MASKEQZOp RC:$t, RC:$cond), (MASKNEZOp RC:$f, RC:$cond))>; ++ ++//def : LoongArchPat<(select (Opg (seteq RC:$cond, imm_type:$imm)), RC:$t, RC:$f), ++// (OROp (MASKNEZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), ++// (MASKEQZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; ++//def : LoongArchPat<(select (Opg (setne RC:$cond, imm_type:$imm)), RC:$t, RC:$f), ++// (OROp (MASKEQZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), ++// (MASKNEZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; ++ ++// reg, immSExt12Plus1 ++//def : LoongArchPat<(select (Opg (setgt RC:$cond, immSExt12Plus1:$imm)), RC:$t, RC:$f), ++// (OROp (MASKNEZOp RC:$t, (SLTiOp RC:$cond, (Plus1 imm:$imm))), ++// (MASKEQZOp RC:$f, (SLTiOp RC:$cond, (Plus1 imm:$imm))))>; ++//def : LoongArchPat<(select (Opg (setugt RC:$cond, immSExt16Plus1:$imm)), RC:$t, RC:$f), ++// (OROp (MASKNEZOp RC:$t, (SLTiuOp RC:$cond, (Plus1 imm:$imm))), ++// (MASKEQZOp RC:$f, (SLTiuOp RC:$cond, (Plus1 imm:$imm))))>; ++ ++def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, immz), ++ (MASKNEZOp RC:$t, RC:$cond)>; ++def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), RC:$t, immz), ++ (MASKEQZOp RC:$t, RC:$cond)>; ++def : LoongArchPat<(select (Opg (seteq RC:$cond, immz)), immz, RC:$f), ++ (MASKEQZOp RC:$f, RC:$cond)>; ++def : LoongArchPat<(select (Opg (setne RC:$cond, immz)), immz, RC:$f), ++ (MASKNEZOp RC:$f, RC:$cond)>; ++} ++ ++defm : SelectInt_Pats; ++ ++def : LoongArchPat<(select i32:$cond, i32:$t, i32:$f), ++ (OR32 (MASKEQZ32 i32:$t, i32:$cond), ++ (MASKNEZ32 i32:$f, i32:$cond))>; ++def : LoongArchPat<(select i32:$cond, i32:$t, immz), ++ (MASKEQZ32 i32:$t, i32:$cond)>; ++def : LoongArchPat<(select i32:$cond, immz, i32:$f), ++ (MASKNEZ32 i32:$f, i32:$cond)>; ++ ++// truncate ++def : LoongArchPat<(i32 (trunc (assertzext_lt_i32 GPR64:$src))), ++ (EXTRACT_SUBREG GPR64:$src, sub_32)>, GPR_64; ++def : LoongArchPat<(i32 (trunc GPR64:$src)), ++ (SLLI_W (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, GPR_64; ++ ++// Patterns used for matching away redundant sign extensions. ++// LA32 arithmetic instructions sign extend their result implicitly. ++def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ADD_W GPR32:$src, GPR32:$src2), sub_32)>; ++def : LoongArchPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SUB_W GPR32:$src, GPR32:$src2), sub_32)>; ++def : LoongArchPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (MUL_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(store (i32 0), addr:$dst), (ST_W32 ZERO, addr:$dst)>; ++ ++def : InstAlias<"break", (BREAK 0), 1>; ++def : InstAlias<"break $imm", (BREAK uimm15:$imm), 1>; ++def : LoongArchInstAlias<"move $dst, $src", ++ (OR32 GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, GPR_32; ++ ++def immSExt12Plus1 : PatLeaf<(imm), [{ ++ return isInt<13>(N->getSExtValue()) && isInt<12>(N->getSExtValue() + 1); ++}]>; ++ ++def Plus1 : SDNodeXFormgetSExtValue() + 1); }]>; ++ ++multiclass BrcondPats { ++ ++def : LoongArchPat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), ++ (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), ++ (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), ++ (BEQOp1 (SLTOp RC:$lhs, RC:$rhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), ++ (BEQOp1 (SLTUOp RC:$lhs, RC:$rhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setge RC:$lhs, immSExt12:$rhs)), bb:$dst), ++ (BEQOp1 (SLTIOp RC:$lhs, immSExt12:$rhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setuge RC:$lhs, immSExt12:$rhs)), bb:$dst), ++ (BEQOp1 (SLTUIOp RC:$lhs, immSExt12:$rhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setgt RC:$lhs, immSExt12Plus1:$rhs)), bb:$dst), ++ (BEQOp1 (SLTIOp RC:$lhs, (Plus1 imm:$rhs)), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setugt RC:$lhs, immSExt12Plus1:$rhs)), bb:$dst), ++ (BEQOp1 (SLTUIOp RC:$lhs, (Plus1 imm:$rhs)), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), ++ (BEQOp1 (SLTOp RC:$rhs, RC:$lhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), ++ (BEQOp1 (SLTUOp RC:$rhs, RC:$lhs), ZEROReg, bb:$dst)>; ++def : LoongArchPat<(brcond RC:$cond, bb:$dst), ++ (BNEOp RC:$cond, ZEROReg, bb:$dst)>; ++} ++ ++defm : BrcondPats, GPR_64; ++ ++let usesCustomInserter = 1 in { ++ def ATOMIC_LOAD_ADD_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_ADD_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_ADD_I32 : Atomic2Ops; ++ def ATOMIC_LOAD_SUB_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_SUB_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_SUB_I32 : Atomic2Ops; ++ def ATOMIC_LOAD_AND_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_AND_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_AND_I32 : Atomic2Ops; ++ def ATOMIC_LOAD_OR_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_OR_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_OR_I32 : Atomic2Ops; ++ def ATOMIC_LOAD_XOR_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_XOR_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_XOR_I32 : Atomic2Ops; ++ def ATOMIC_LOAD_NAND_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_NAND_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_NAND_I32 : Atomic2Ops; ++ ++ def ATOMIC_SWAP_I8 : Atomic2Ops; ++ def ATOMIC_SWAP_I16 : Atomic2Ops; ++ def ATOMIC_SWAP_I32 : Atomic2Ops; ++ ++ def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap; ++ def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap; ++ def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap; ++ ++ def ATOMIC_LOAD_MAX_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_MAX_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_MAX_I32 : Atomic2Ops; ++ ++ def ATOMIC_LOAD_MIN_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_MIN_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_MIN_I32 : Atomic2Ops; ++ ++ def ATOMIC_LOAD_UMAX_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_UMAX_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_UMAX_I32 : Atomic2Ops; ++ ++ def ATOMIC_LOAD_UMIN_I8 : Atomic2Ops; ++ def ATOMIC_LOAD_UMIN_I16 : Atomic2Ops; ++ def ATOMIC_LOAD_UMIN_I32 : Atomic2Ops; ++} ++ ++def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_ADD_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_ADD_I32_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_SUB_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_SUB_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_SUB_I32_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_AND_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_AND_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_AND_I32_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_OR_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_OR_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_OR_I32_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_XOR_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_XOR_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_XOR_I32_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_NAND_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_NAND_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_NAND_I32_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_SWAP_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_SWAP_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_SWAP_I32_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA; ++def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA; ++def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA; ++ ++def ATOMIC_LOAD_MAX_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_MAX_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_MAX_I32_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_MIN_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_MIN_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_MIN_I32_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_UMAX_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_UMAX_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_UMAX_I32_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_UMIN_I8_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_UMIN_I16_POSTRA : Atomic2OpsSubwordPostRA; ++def ATOMIC_LOAD_UMIN_I32_POSTRA : Atomic2OpsPostRA; ++ ++def : LoongArchPat<(atomic_load_8 addr:$a), (LD_B32 addr:$a)>; ++def : LoongArchPat<(atomic_load_16 addr:$a), (LD_H32 addr:$a)>; ++def : LoongArchPat<(atomic_load_32 addrimm14lsl2:$a), (LDPTR_W32 addrimm14lsl2:$a)>; ++def : LoongArchPat<(atomic_load_32 addr:$a), (LD_W32 addr:$a)>; ++ ++def : LoongArchPat<(atomic_store_8 addr:$a, GPR32:$v), ++ (ST_B32 GPR32:$v, addr:$a)>; ++def : LoongArchPat<(atomic_store_16 addr:$a, GPR32:$v), ++ (ST_H32 GPR32:$v, addr:$a)>; ++def : LoongArchPat<(atomic_store_32 addrimm14lsl2:$a, GPR32:$v), ++ (STPTR_W32 GPR32:$v, addrimm14lsl2:$a)>; ++def : LoongArchPat<(atomic_store_32 addr:$a, GPR32:$v), ++ (ST_W32 GPR32:$v, addr:$a)>; ++ ++def : LoongArchPat<(LoongArchDBAR (i32 immz)), ++ (DBAR 0)>; ++ ++def : LoongArchPat<(i32 (extloadi1 addr:$src)), (LD_BU32 addr:$src)>; ++def : LoongArchPat<(i32 (extloadi8 addr:$src)), (LD_BU32 addr:$src)>; ++def : LoongArchPat<(i32 (extloadi16 addr:$src)), (LD_HU32 addr:$src)>; ++ ++def : LoongArchPat<(store (i32 0), addr:$dst), (ST_W32 ZERO, addr:$dst)>; ++ ++// Patterns for loads/stores with a reg+imm operand. ++let AddedComplexity = 40 in { ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : StoreRegImmPat; ++ def : StoreRegImmPat; ++ def : StoreRegImmPat; ++ ++ def : LoadRegImm14Lsl2Pat; ++ def : StoreRegImm14Lsl2Pat; ++} ++ ++let isCall=1, isCTI=1, Defs = [RA] in { ++ ++ class JumpLinkRegPseudo: ++ LoongArchPseudo<(outs), (ins RO:$rj), [(LoongArchJmpLink RO:$rj)]>, ++ PseudoInstExpansion<(JIRLRInst RetReg, ResRO:$rj)> { ++ let hasPostISelHook = 1; ++ } ++ ++ class JumpLinkReg: ++ InstForm<(outs RO:$rd), (ins RO:$rj), !strconcat(opstr, "\t$rd, $rj, 0"), ++ [], FrmR, opstr> { ++ let hasPostISelHook = 1; ++ } ++ ++} ++ ++def JIRLR : JumpLinkReg<"jirl", GPR32Opnd>, R2_IMM16JIRL { ++ let offs16 = 0; ++} ++def JIRLRPseudo : JumpLinkRegPseudo; ++ ++class BrindRegPseudo: ++ LoongArchPseudo<(outs), (ins RO:$rj), [(brind RO:$rj)]>, ++ PseudoInstExpansion<(JIRLRInst RetReg, ResRO:$rj)> { ++ let isTerminator=1; ++ let isBarrier=1; ++ let isBranch = 1; ++ let isIndirectBranch = 1; ++ bit isCTI = 1; ++} ++ ++def JIRLRBRIND : BrindRegPseudo; ++ ++def : LoongArchPat<(addc GPR32:$src, immSExt12:$imm), ++ (ADDI_W GPR32:$src, imm:$imm)>; ++ ++defm : SeteqPats; ++defm : SetlePats; ++defm : SetgtPats; ++defm : SetgePats; ++defm : SetgeImmPats; ++ ++def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (immZExt12:$imm12))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (XORI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (immZExt12:$imm12)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (add (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ADD_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (add (i32 (trunc (i64 (assertsext GPR64:$rj)))), (immSExt12:$imm12))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ADDI_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (immSExt12:$imm12)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (sra (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRA_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (srl (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (mul (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (MUL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (XOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 GPR32:$rk))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (XOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), GPR32:$rk), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), (uimm12_32:$imm12))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ORI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (uimm12_32:$imm12)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 GPR32:$rk))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (OR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), GPR32:$rk), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (select i32:$cond, (i32 (trunc (i64 (assertsext GPR64:$t)))), (i32 (trunc (i64 (assertsext GPR64:$f))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (OR32 (MASKEQZ32 (EXTRACT_SUBREG GPR64:$t, sub_32), i32:$cond), ++ (MASKNEZ32 (EXTRACT_SUBREG GPR64:$f, sub_32), i32:$cond)), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (shl (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SLL_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (srem (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (MOD_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(atomic_store_32 addr:$a, (i32 (trunc (i64 (assertsext GPR64:$rj))))), ++ (ST_W32 (EXTRACT_SUBREG GPR64:$rj, sub_32), addr:$a)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (sub (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SUB_W (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (udiv (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (DIV_WU (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(i64 (sext (i32 (urem (i32 (trunc (i64 (assertsext GPR64:$rj)))), (i32 (trunc (i64 (assertsext GPR64:$rk)))))))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (MOD_WU (EXTRACT_SUBREG GPR64:$rj, sub_32), (EXTRACT_SUBREG GPR64:$rk, sub_32)), sub_32)>, GPR_64; ++ ++def : LoongArchPat<(brcond (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$rj)))), 0)), bb:$offs21), ++ (BEQZ32 (EXTRACT_SUBREG GPR64:$rj, sub_32), brtarget:$offs21)>; ++ ++def : LoongArchPat<(setne (i32 (trunc (i64 (assertsext GPR64:$rj)))), 0), ++ (SLTU32 ZERO, (EXTRACT_SUBREG GPR64:$rj, sub_32))>; ++ ++def : LoongArchPat<(select i32:$cond, (i32 (trunc (i64 (assertsext GPR64:$t)))), (i32 (trunc (i64 (assertsext GPR64:$f))))), ++ (OR32 (MASKEQZ32 (EXTRACT_SUBREG GPR64:$t, sub_32), i32:$cond), ++ (MASKNEZ32 (EXTRACT_SUBREG GPR64:$f, sub_32), i32:$cond))>; ++ ++def : LoongArchPat<(select (i32 (setne (i32 (trunc (i64 (assertsext GPR64:$cond)))), immz)), immz, i32:$f), ++ (MASKNEZ32 i32:$f, (EXTRACT_SUBREG GPR64:$cond, sub_32))>; ++ ++def : LoongArchPat<(select (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$cond)))), immz)), immz, i32:$f), ++ (MASKEQZ32 i32:$f, (EXTRACT_SUBREG GPR64:$cond, sub_32))>; ++ ++ def : LoongArchPat<(store (i32 (trunc (i64 (assertsext GPR64:$v)))), addr:$a), ++ (ST_W32 (EXTRACT_SUBREG GPR64:$v, sub_32), addr:$a)>; ++ ++ ++def : LoongArchPat<(i32 (xor GPR32:$rj, (i32 -1))), ++ (NOR32 ZERO, GPR32:$rj)>; ++ ++def : LoongArchPat<(and GPR32:$rj, (i32 (xor GPR32:$rk, (i32 -1)))), ++ (ANDN32 GPR32:$rj, GPR32:$rk)>; ++ ++def : LoongArchPat< ++ (i64 ++ (sext ++ (i32 (and (i32 (trunc (i64 (assertsext GPR64:$rj)))), ++ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rk)))), ++ (i32 -1)))) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (ANDN32 (EXTRACT_SUBREG GPR64:$rj, sub_32), ++ (EXTRACT_SUBREG GPR64:$rk, sub_32)), ++ sub_32 ++ )>; ++ ++def : LoongArchPat< ++ (i64 ++ (sext ++ (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), ++ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rk)))), ++ (i32 -1)))) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (ORN32 (EXTRACT_SUBREG GPR64:$rj, sub_32), ++ (EXTRACT_SUBREG GPR64:$rk, sub_32)), ++ sub_32 ++ )>; ++ ++def : LoongArchPat<(i64 ++ (sext ++ (i32 (xor (i32 (or (i32 (trunc (i64 (assertsext GPR64:$rj)))), ++ (i32 (trunc (i64 (assertsext GPR64:$rk)))))), ++ (i32 -1)) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (NOR32 (EXTRACT_SUBREG GPR64:$rj, sub_32), ++ (EXTRACT_SUBREG GPR64:$rk, sub_32)), ++ sub_32 ++ )>; ++ ++def : LoongArchPat<(i64 ++ (sext ++ (i32 (xor (i32 (trunc (i64 (or (i64 (assertsext GPR64:$rj)), ++ (i64 (assertsext GPR64:$rk)))))), ++ (i32 -1)) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (NOR32 (EXTRACT_SUBREG GPR64:$rk, sub_32), ++ (EXTRACT_SUBREG GPR64:$rj, sub_32)), ++ sub_32 ++ )>; ++ ++def : LoongArchPat<(i64 ++ (sext ++ (i32 (xor (i32 (trunc (i64 (assertsext GPR64:$rj)))), ++ (i32 -1)) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (NOR32 ZERO, (EXTRACT_SUBREG GPR64:$rj, sub_32)), ++ sub_32 ++ )>; ++ ++def : LoongArchPat<(i64 ++ (zext ++ (i32 (seteq (i32 (trunc (i64 (assertsext GPR64:$rj)))), ++ (i32 0)) ++ ) ++ ) ++ ), ++ (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), ++ (SLTUI32 (EXTRACT_SUBREG GPR64:$rj, sub_32), (i32 1)), ++ sub_32 ++ )>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +index 1467d1757..afa38dbf2 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +@@ -1,4 +1,4 @@ +-//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- C++ -*--=// ++//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer --------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -12,40 +12,622 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchAsmPrinter.h" ++#include "MCTargetDesc/LoongArchInstPrinter.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" + #include "LoongArch.h" ++#include "LoongArchMCInstLower.h" ++#include "LoongArchMachineFunction.h" ++#include "LoongArchSubtarget.h" + #include "LoongArchTargetMachine.h" +-#include "TargetInfo/LoongArchTargetInfo.h" +-#include "llvm/CodeGen/AsmPrinter.h" ++#include "LoongArchTargetStreamer.h" ++#include "llvm/ADT/SmallString.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/Triple.h" ++#include "llvm/ADT/Twine.h" ++#include "llvm/BinaryFormat/ELF.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" ++#include "llvm/CodeGen/MachineConstantPool.h" ++#include "llvm/CodeGen/MachineFrameInfo.h" ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineJumpTableInfo.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++#include "llvm/IR/Attributes.h" ++#include "llvm/IR/BasicBlock.h" ++#include "llvm/IR/DataLayout.h" ++#include "llvm/IR/Function.h" ++#include "llvm/IR/InlineAsm.h" ++#include "llvm/IR/Instructions.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCInstBuilder.h" ++#include "llvm/MC/MCObjectFileInfo.h" ++#include "llvm/MC/MCSectionELF.h" ++#include "llvm/MC/MCSymbol.h" ++#include "llvm/MC/MCSymbolELF.h" + #include "llvm/MC/TargetRegistry.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/raw_ostream.h" ++#include "llvm/Target/TargetMachine.h" ++#include ++#include ++#include ++#include ++#include ++#include + + using namespace llvm; + + #define DEBUG_TYPE "loongarch-asm-printer" + +-// Simple pseudo-instructions have their lowering (with expansion to real +-// instructions) auto-generated. ++LoongArchTargetStreamer &LoongArchAsmPrinter::getTargetStreamer() const { ++ return static_cast(*OutStreamer->getTargetStreamer()); ++} ++ ++bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { ++ Subtarget = &MF.getSubtarget(); ++ ++ LoongArchFI = MF.getInfo(); ++ MCP = MF.getConstantPool(); ++ ++ AsmPrinter::runOnMachineFunction(MF); ++ ++ emitXRayTable(); ++ ++ return true; ++} ++ ++bool LoongArchAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { ++ MCOp = MCInstLowering.LowerOperand(MO); ++ return MCOp.isValid(); ++} ++ + #include "LoongArchGenMCPseudoLowering.inc" + ++// Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to ++// JIRL as appropriate for the target. ++void LoongArchAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, ++ const MachineInstr *MI) { ++ bool HasLinkReg = false; ++ MCInst TmpInst0; ++ TmpInst0.setOpcode(LoongArch::JIRL); ++ HasLinkReg = true; ++ ++ MCOperand MCOp; ++ ++ if (HasLinkReg) { ++ unsigned ZeroReg = Subtarget->is64Bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); ++ } ++ ++ lowerOperand(MI->getOperand(0), MCOp); ++ TmpInst0.addOperand(MCOp); ++ ++ TmpInst0.addOperand(MCOperand::createImm(0)); ++ ++ EmitToStreamer(OutStreamer, TmpInst0); ++} ++ ++void LoongArchAsmPrinter::emitPseudoTailBranch(MCStreamer &OutStreamer, ++ const MachineInstr *MI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(LoongArch::B); ++ ++ MCOperand MCOp; ++ ++ lowerOperand(MI->getOperand(0), MCOp); ++ TmpInst.addOperand(MCOp); ++ ++ EmitToStreamer(OutStreamer, TmpInst); ++} ++ + void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) { +- LoongArch_MC::verifyInstructionPredicates( +- MI->getOpcode(), getSubtargetInfo().getFeatureBits()); ++ LoongArchTargetStreamer &TS = getTargetStreamer(); ++ unsigned Opc = MI->getOpcode(); ++ TS.forbidModuleDirective(); + +- // Do any auto-generated pseudo lowerings. +- if (emitPseudoExpansionLowering(*OutStreamer, MI)) ++ if (MI->isDebugValue()) { ++ SmallString<128> Str; ++ raw_svector_ostream OS(Str); ++ ++ PrintDebugValueComment(MI, OS); ++ return; ++ } ++ if (MI->isDebugLabel()) + return; ++ // If we just ended a constant pool, mark it as such. ++ OutStreamer->emitDataRegion(MCDR_DataRegionEnd); ++ InConstantPool = false; + +- MCInst TmpInst; +- if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this)) +- EmitToStreamer(*OutStreamer, TmpInst); ++ switch (Opc) { ++ case LoongArch::PATCHABLE_FUNCTION_ENTER: ++ LowerPATCHABLE_FUNCTION_ENTER(*MI); ++ return; ++ case LoongArch::PATCHABLE_FUNCTION_EXIT: ++ LowerPATCHABLE_FUNCTION_EXIT(*MI); ++ return; ++ case LoongArch::PATCHABLE_TAIL_CALL: ++ LowerPATCHABLE_TAIL_CALL(*MI); ++ return; ++ } ++ MachineBasicBlock::const_instr_iterator I = MI->getIterator(); ++ MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); ++ ++ do { ++ // Do any auto-generated pseudo lowerings. ++ if (emitPseudoExpansionLowering(*OutStreamer, &*I)) ++ continue; ++ if (I->getOpcode() == LoongArch::PseudoReturn || ++ I->getOpcode() == LoongArch::PseudoReturn64){ ++ emitPseudoIndirectBranch(*OutStreamer, &*I); ++ continue; ++ } ++ if (I->getOpcode() == LoongArch::PseudoTailReturn){ ++ emitPseudoTailBranch(*OutStreamer, &*I); ++ continue; ++ } ++ ++ // Some instructions are marked as pseudo right now which ++ // would make the test fail for the wrong reason but ++ // that will be fixed soon. We need this here because we are ++ // removing another test for this situation downstream in the ++ // callchain. ++ // ++ if (I->isPseudo() ++ && !isLongBranchPseudo(I->getOpcode())) ++ llvm_unreachable("Pseudo opcode found in EmitInstruction()"); ++ ++ MCInst TmpInst0; ++ MCInstLowering.Lower(&*I, TmpInst0); ++ EmitToStreamer(*OutStreamer, TmpInst0); ++ } while ((++I != E) && I->isInsideBundle()); + } + +-bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { +- AsmPrinter::runOnMachineFunction(MF); +- return true; ++//===----------------------------------------------------------------------===// ++// ++// LoongArch Asm Directives ++// ++// ++//===----------------------------------------------------------------------===// ++ ++//===----------------------------------------------------------------------===// ++// Set directives ++//===----------------------------------------------------------------------===// ++ ++/// Emit Set directives. ++const char *LoongArchAsmPrinter::getCurrentABIString() const { ++ switch (static_cast(TM).getABI().GetEnumValue()) { ++ case LoongArchABIInfo::ABI::LP32: return "abilp32"; ++ case LoongArchABIInfo::ABI::LPX32: return "abilpx32"; ++ case LoongArchABIInfo::ABI::LP64: return "abilp64"; ++ default: llvm_unreachable("Unknown LoongArch ABI"); ++ } ++} ++ ++void LoongArchAsmPrinter::emitFunctionEntryLabel() { ++ ++ OutStreamer->emitLabel(CurrentFnSym); ++ ++} ++ ++/// EmitFunctionBodyStart - Targets can override this to emit stuff before ++/// the first basic block in the function. ++void LoongArchAsmPrinter::emitFunctionBodyStart() { ++ ++ MCInstLowering.Initialize(&MF->getContext()); ++} ++ ++/// EmitFunctionBodyEnd - Targets can override this to emit stuff after ++/// the last basic block in the function. ++void LoongArchAsmPrinter::emitFunctionBodyEnd() { ++ ++ // Make sure to terminate any constant pools that were at the end ++ // of the function. ++ if (!InConstantPool) ++ return; ++ InConstantPool = false; ++ OutStreamer->emitDataRegion(MCDR_DataRegionEnd); ++} ++ ++void LoongArchAsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) { ++ AsmPrinter::emitBasicBlockEnd(MBB); ++} ++ ++/// isBlockOnlyReachableByFallthough - Return true if the basic block has ++/// exactly one predecessor and the control transfer mechanism between ++/// the predecessor and this block is a fall-through. ++bool LoongArchAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* ++ MBB) const { ++ // The predecessor has to be immediately before this block. ++ const MachineBasicBlock *Pred = *MBB->pred_begin(); ++ ++ // If the predecessor is a switch statement, assume a jump table ++ // implementation, so it is not a fall through. ++ if (const BasicBlock *bb = Pred->getBasicBlock()) ++ if (isa(bb->getTerminator())) ++ return false; ++ ++ // Check default implementation ++ return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); ++} ++ ++// Print out an operand for an inline asm expression. ++bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, ++ unsigned OpNum, const char *ExtraCode, raw_ostream &O) { ++ // Does this asm operand have a single letter operand modifier? ++ if (ExtraCode && ExtraCode[0]) { ++ if (ExtraCode[1] != 0) return true; // Unknown modifier. ++ ++ const MachineOperand &MO = MI->getOperand(OpNum); ++ switch (ExtraCode[0]) { ++ default: ++ // See if this is a generic print operand ++ return AsmPrinter::PrintAsmOperand(MI,OpNum,ExtraCode,O); ++ case 'X': // hex const int ++ if ((MO.getType()) != MachineOperand::MO_Immediate) ++ return true; ++ O << "0x" << Twine::utohexstr(MO.getImm()); ++ return false; ++ case 'x': // hex const int (low 16 bits) ++ if ((MO.getType()) != MachineOperand::MO_Immediate) ++ return true; ++ O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); ++ return false; ++ case 'd': // decimal const int ++ if ((MO.getType()) != MachineOperand::MO_Immediate) ++ return true; ++ O << MO.getImm(); ++ return false; ++ case 'm': // decimal const int minus 1 ++ if ((MO.getType()) != MachineOperand::MO_Immediate) ++ return true; ++ O << MO.getImm() - 1; ++ return false; ++ case 'y': // exact log2 ++ if ((MO.getType()) != MachineOperand::MO_Immediate) ++ return true; ++ if (!isPowerOf2_64(MO.getImm())) ++ return true; ++ O << Log2_64(MO.getImm()); ++ return false; ++ case 'z': ++ // $r0 if zero, regular printing otherwise ++ if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) { ++ O << "$r0"; ++ return false; ++ } ++ // If not, call printOperand as normal. ++ break; ++ case 'D': // Second part of a double word register operand ++ case 'L': // Low order register of a double word register operand ++ case 'M': // High order register of a double word register operand ++ { ++ if (OpNum == 0) ++ return true; ++ const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); ++ if (!FlagsOP.isImm()) ++ return true; ++ unsigned Flags = FlagsOP.getImm(); ++ unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); ++ // Number of registers represented by this operand. We are looking ++ // for 2 for 32 bit mode and 1 for 64 bit mode. ++ if (NumVals != 2) { ++ if (Subtarget->is64Bit() && NumVals == 1 && MO.isReg()) { ++ unsigned Reg = MO.getReg(); ++ O << '$' << LoongArchInstPrinter::getRegisterName(Reg); ++ return false; ++ } ++ return true; ++ } ++ ++ unsigned RegOp = OpNum; ++ if (!Subtarget->is64Bit()){ ++ // Endianness reverses which register holds the high or low value ++ // between M and L. ++ switch(ExtraCode[0]) { ++ case 'M': ++ RegOp = OpNum + 1; ++ break; ++ case 'L': ++ RegOp = OpNum; ++ break; ++ case 'D': // Always the second part ++ RegOp = OpNum + 1; ++ } ++ if (RegOp >= MI->getNumOperands()) ++ return true; ++ const MachineOperand &MO = MI->getOperand(RegOp); ++ if (!MO.isReg()) ++ return true; ++ unsigned Reg = MO.getReg(); ++ O << '$' << LoongArchInstPrinter::getRegisterName(Reg); ++ return false; ++ } ++ break; ++ } ++ case 'w': ++ // Print LSX registers for the 'f' constraint ++ // In LLVM, the 'w' modifier doesn't need to do anything. ++ // We can just call printOperand as normal. ++ break; ++ case 'u': ++ // Print LASX registers for the 'f' constraint ++ // In LLVM, the 'u' modifier doesn't need to do anything. ++ // We can just call printOperand as normal. ++ break; ++ } ++ } ++ ++ printOperand(MI, OpNum, O); ++ return false; ++} ++ ++bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, ++ unsigned OpNum, ++ const char *ExtraCode, ++ raw_ostream &O) { ++ assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); ++ const MachineOperand &BaseMO = MI->getOperand(OpNum); ++ const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); ++ assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); ++ assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); ++ int Offset = OffsetMO.getImm(); ++ ++ // Currently we are expecting either no ExtraCode or 'D','M','L'. ++ if (ExtraCode) { ++ switch (ExtraCode[0]) { ++ case 'D': ++ case 'M': ++ Offset += 4; ++ break; ++ case 'L': ++ break; ++ default: ++ return true; // Unknown modifier. ++ } ++ } ++ ++ O << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg()) << ", " << Offset; ++ ++ return false; ++} ++ ++void LoongArchAsmPrinter::printOperand(const MachineInstr *MI, int opNum, ++ raw_ostream &O) { ++ const MachineOperand &MO = MI->getOperand(opNum); ++ ++ switch (MO.getType()) { ++ case MachineOperand::MO_Register: ++ O << '$' ++ << StringRef(LoongArchInstPrinter::getRegisterName(MO.getReg())).lower(); ++ break; ++ ++ case MachineOperand::MO_Immediate: ++ O << MO.getImm(); ++ break; ++ ++ case MachineOperand::MO_MachineBasicBlock: ++ MO.getMBB()->getSymbol()->print(O, MAI); ++ return; ++ ++ case MachineOperand::MO_GlobalAddress: ++ getSymbol(MO.getGlobal())->print(O, MAI); ++ break; ++ ++ case MachineOperand::MO_BlockAddress: { ++ MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); ++ O << BA->getName(); ++ break; ++ } ++ ++ case MachineOperand::MO_ConstantPoolIndex: ++ O << getDataLayout().getPrivateGlobalPrefix() << "CPI" ++ << getFunctionNumber() << "_" << MO.getIndex(); ++ if (MO.getOffset()) ++ O << "+" << MO.getOffset(); ++ break; ++ ++ default: ++ llvm_unreachable(""); ++ } ++} ++ ++void LoongArchAsmPrinter:: ++printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { ++ // Load/Store memory operands -- imm($reg) ++ // If PIC target the target is loaded as the ++ // pattern lw $25,%call16($28) ++ ++ printOperand(MI, opNum+1, O); ++ O << "("; ++ printOperand(MI, opNum, O); ++ O << ")"; ++} ++ ++void LoongArchAsmPrinter:: ++printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { ++ // when using stack locations for not load/store instructions ++ // print the same way as all normal 3 operand instructions. ++ printOperand(MI, opNum, O); ++ O << ", "; ++ printOperand(MI, opNum+1, O); ++} ++ ++void LoongArchAsmPrinter:: ++printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { ++ for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { ++ if (i != opNum) O << ", "; ++ printOperand(MI, i, O); ++ } ++} ++ ++void LoongArchAsmPrinter::emitStartOfAsmFile(Module &M) { ++ LoongArchTargetStreamer &TS = getTargetStreamer(); ++ ++ // LoongArchTargetStreamer has an initialization order problem when emitting an ++ // object file directly (see LoongArchTargetELFStreamer for full details). Work ++ // around it by re-initializing the PIC state here. ++ TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent()); ++ ++ // Compute LoongArch architecture attributes based on the default subtarget ++ // that we'd have constructed. Module level directives aren't LTO ++ // clean anyhow. ++ // FIXME: For ifunc related functions we could iterate over and look ++ // for a feature string that doesn't match the default one. ++ const Triple &TT = TM.getTargetTriple(); ++ StringRef CPU = LoongArch_MC::selectLoongArchCPU(TT, TM.getTargetCPU()); ++ StringRef FS = TM.getTargetFeatureString(); ++ const LoongArchTargetMachine &MTM = static_cast(TM); ++ const LoongArchSubtarget STI(TT, CPU, FS, MTM, None); ++ ++ TS.updateABIInfo(STI); ++} ++ ++void LoongArchAsmPrinter::emitInlineAsmStart() const { ++ ++ OutStreamer->addBlankLine(); ++} ++ ++void LoongArchAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, ++ const MCSubtargetInfo *EndInfo) const { ++ OutStreamer->addBlankLine(); ++} ++ ++void LoongArchAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, ++ unsigned Reg) { ++ MCInst I; ++ I.setOpcode(Opcode); ++ I.addOperand(MCOperand::createReg(Reg)); ++ OutStreamer->emitInstruction(I, STI); ++} ++ ++void LoongArchAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, ++ unsigned Opcode, unsigned Reg1, ++ unsigned Reg2) { ++ MCInst I; ++ // ++ // Because of the current td files for LoongArch32, the operands for MTC1 ++ // appear backwards from their normal assembly order. It's not a trivial ++ // change to fix this in the td file so we adjust for it here. ++ // ++ if (Opcode == LoongArch::MOVGR2FR_W) { ++ unsigned Temp = Reg1; ++ Reg1 = Reg2; ++ Reg2 = Temp; ++ } ++ I.setOpcode(Opcode); ++ I.addOperand(MCOperand::createReg(Reg1)); ++ I.addOperand(MCOperand::createReg(Reg2)); ++ OutStreamer->emitInstruction(I, STI); ++} ++ ++void LoongArchAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, ++ unsigned Opcode, unsigned Reg1, ++ unsigned Reg2, unsigned Reg3) { ++ MCInst I; ++ I.setOpcode(Opcode); ++ I.addOperand(MCOperand::createReg(Reg1)); ++ I.addOperand(MCOperand::createReg(Reg2)); ++ I.addOperand(MCOperand::createReg(Reg3)); ++ OutStreamer->emitInstruction(I, STI); ++} ++ ++void LoongArchAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, ++ unsigned MovOpc, unsigned Reg1, ++ unsigned Reg2, unsigned FPReg1, ++ unsigned FPReg2, bool LE) { ++ if (!LE) { ++ unsigned temp = Reg1; ++ Reg1 = Reg2; ++ Reg2 = temp; ++ } ++ EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); ++ EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); ++} ++ ++void LoongArchAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { ++ const uint8_t NoopsInSledCount = 11; ++ // For loongarch64 we want to emit the following pattern: ++ // ++ // .Lxray_sled_N: ++ // ALIGN ++ // B .tmpN ++ // 11 NOP instructions (44 bytes) ++ // .tmpN ++ // ++ // We need the 44 bytes (11 instructions) because at runtime, we'd ++ // be patching over the full 48 bytes (12 instructions) with the following ++ // pattern: ++ // ++ // addi.d sp,sp, -16 ;create stack frame ++ // st.d ra, sp, 8 ;save return address ++ // lu12i.w t0,%%abs_hi20(__xray_FunctionEntry/Exit) ++ // ori t0,t0,%%abs_lo12(__xray_FunctionEntry/Exit) ++ // lu32i.d t0,%%abs64_lo20(__xray_FunctionEntry/Exit) ++ // lu52i.d t0,t0,%%abs64_hi12(__xray_FunctionEntry/Exit) ++ // lu12i.w t1,%%abs_hi20(function_id) ++ // ori t1,t1,%%abs_lo12(function_id) ;pass function id ++ // jirl ra, t0, 0 ;call Tracing hook ++ // ld.d ra, sp, 8 ;restore return address ++ // addi.d sp, sp, 16 ;delete stack frame ++ ++ OutStreamer->emitCodeAlignment(4, &getSubtargetInfo()); ++ auto CurSled = OutContext.createTempSymbol("xray_sled_", true); ++ OutStreamer->emitLabel(CurSled); ++ auto Target = OutContext.createTempSymbol(); ++ ++ // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual ++ // start of function ++ const MCExpr *TargetExpr = MCSymbolRefExpr::create( ++ Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); ++ EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::BEQ) ++ .addReg(LoongArch::ZERO) ++ .addReg(LoongArch::ZERO) ++ .addExpr(TargetExpr)); ++ ++ for (int8_t I = 0; I < NoopsInSledCount; I++) ++ EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::ANDI) ++ .addReg(LoongArch::ZERO) ++ .addReg(LoongArch::ZERO) ++ .addImm(0)); ++ ++ OutStreamer->emitLabel(Target); ++ recordSled(CurSled, MI, Kind, 2); ++} ++ ++void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { ++ EmitSled(MI, SledKind::FUNCTION_ENTER); ++} ++ ++void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { ++ EmitSled(MI, SledKind::FUNCTION_EXIT); ++} ++ ++void LoongArchAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { ++ EmitSled(MI, SledKind::TAIL_CALL); ++} ++ ++void LoongArchAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, ++ raw_ostream &OS) { ++ // TODO: implement ++} ++ ++bool LoongArchAsmPrinter::isLongBranchPseudo(int Opcode) const { ++ return (Opcode == LoongArch::LONG_BRANCH_ADDIW ++ || Opcode == LoongArch::LONG_BRANCH_ADDIW2Op ++ || Opcode == LoongArch::LONG_BRANCH_ADDID ++ || Opcode == LoongArch::LONG_BRANCH_ADDID2Op ++ || Opcode == LoongArch::LONG_BRANCH_PCADDU12I); + } + + // Force static initialization. + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() { + RegisterAsmPrinter X(getTheLoongArch32Target()); +- RegisterAsmPrinter Y(getTheLoongArch64Target()); ++ RegisterAsmPrinter A(getTheLoongArch64Target()); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h +index b51c19188..3e4ca8ed1 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h +@@ -1,4 +1,4 @@ +-//===- LoongArchAsmPrinter.h - LoongArch LLVM Assembly Printer -*- C++ -*--===// ++//===- LoongArchAsmPrinter.h - LoongArch LLVM Assembly Printer -----------*- C++ -*--===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -13,36 +13,123 @@ + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H + ++#include "LoongArchMCInstLower.h" + #include "LoongArchSubtarget.h" + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/MC/MCStreamer.h" + #include "llvm/Support/Compiler.h" ++#include ++#include ++#include + + namespace llvm { + ++class MCOperand; ++class MCSubtargetInfo; ++class MCSymbol; ++class MachineBasicBlock; ++class MachineConstantPool; ++class MachineFunction; ++class MachineInstr; ++class MachineOperand; ++class LoongArchFunctionInfo; ++class LoongArchTargetStreamer; ++class Module; ++class raw_ostream; ++class TargetMachine; ++ + class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter { +- const MCSubtargetInfo *STI; ++ LoongArchTargetStreamer &getTargetStreamer() const; ++ ++ void EmitInstrWithMacroNoAT(const MachineInstr *MI); ++ ++ //===------------------------------------------------------------------===// ++ // XRay implementation ++ //===------------------------------------------------------------------===// + + public: +- explicit LoongArchAsmPrinter(TargetMachine &TM, +- std::unique_ptr Streamer) +- : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {} ++ // XRay-specific lowering for LoongArch. ++ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); ++ void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); ++ void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); + +- StringRef getPassName() const override { +- return "LoongArch Assembly Printer"; +- } ++private: ++ /// MCP - Keep a pointer to constantpool entries of the current ++ /// MachineFunction. ++ const MachineConstantPool *MCP = nullptr; + +- bool runOnMachineFunction(MachineFunction &MF) override; ++ /// InConstantPool - Maintain state when emitting a sequence of constant ++ /// pool entries so we can properly mark them as data regions. ++ bool InConstantPool = false; + +- void emitInstruction(const MachineInstr *MI) override; ++ void EmitSled(const MachineInstr &MI, SledKind Kind); + + // tblgen'erated function. + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); +- // Wrapper needed for tblgenned pseudo lowering. +- bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const { +- return lowerLoongArchMachineOperandToMCOperand(MO, MCOp, *this); +- } ++ ++ // Emit PseudoReturn, PseudoReturn64, PseudoIndirectBranch, ++ // and PseudoIndirectBranch64 as a JIRL as appropriate ++ // for the target. ++ void emitPseudoIndirectBranch(MCStreamer &OutStreamer, ++ const MachineInstr *MI); ++ ++ void emitPseudoTailBranch(MCStreamer &OutStreamer, ++ const MachineInstr *MI); ++ ++ // lowerOperand - Convert a MachineOperand into the equivalent MCOperand. ++ bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); ++ ++ void emitInlineAsmStart() const override; ++ ++ void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, ++ const MCSubtargetInfo *EndInfo) const override; ++ ++ void EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, unsigned Reg); ++ ++ void EmitInstrRegReg(const MCSubtargetInfo &STI, unsigned Opcode, ++ unsigned Reg1, unsigned Reg2); ++ ++ void EmitInstrRegRegReg(const MCSubtargetInfo &STI, unsigned Opcode, ++ unsigned Reg1, unsigned Reg2, unsigned Reg3); ++ ++ void EmitMovFPIntPair(const MCSubtargetInfo &STI, unsigned MovOpc, ++ unsigned Reg1, unsigned Reg2, unsigned FPReg1, ++ unsigned FPReg2, bool LE); ++ ++ bool isLongBranchPseudo(int Opcode) const; ++ ++public: ++ const LoongArchSubtarget *Subtarget; ++ const LoongArchFunctionInfo *LoongArchFI; ++ LoongArchMCInstLower MCInstLowering; ++ ++ explicit LoongArchAsmPrinter(TargetMachine &TM, ++ std::unique_ptr Streamer) ++ : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {} ++ ++ StringRef getPassName() const override { return "LoongArch Assembly Printer"; } ++ ++ bool runOnMachineFunction(MachineFunction &MF) override; ++ ++ void emitInstruction(const MachineInstr *MI) override; ++ const char *getCurrentABIString() const; ++ void emitFunctionEntryLabel() override; ++ void emitFunctionBodyStart() override; ++ void emitFunctionBodyEnd() override; ++ void emitBasicBlockEnd(const MachineBasicBlock &MBB) override; ++ bool isBlockOnlyReachableByFallthrough( ++ const MachineBasicBlock* MBB) const override; ++ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, ++ const char *ExtraCode, raw_ostream &O) override; ++ bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, ++ const char *ExtraCode, raw_ostream &O) override; ++ void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); ++ void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); ++ void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); ++ void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O); ++ void emitStartOfAsmFile(Module &M) override; ++ void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); + }; + + } // end namespace llvm +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp +new file mode 100644 +index 000000000..6630ca759 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.cpp +@@ -0,0 +1,165 @@ ++//===---- LoongArchCCState.cpp - CCState with LoongArch specific extensions ---------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchCCState.h" ++#include "LoongArchSubtarget.h" ++#include "llvm/IR/Module.h" ++ ++using namespace llvm; ++ ++/// This function returns true if CallSym is a long double emulation routine. ++static bool isF128SoftLibCall(const char *CallSym) { ++ const char *const LibCalls[] = { ++ "__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", ++ "__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti", ++ "__fixunstfdi", "__fixunstfsi", "__fixunstfti", "__floatditf", ++ "__floatsitf", "__floattitf", "__floatunditf", "__floatunsitf", ++ "__floatuntitf", "__getf2", "__gttf2", "__letf2", ++ "__lttf2", "__multf3", "__netf2", "__powitf2", ++ "__subtf3", "__trunctfdf2", "__trunctfsf2", "__unordtf2", ++ "ceill", "copysignl", "cosl", "exp2l", ++ "expl", "floorl", "fmal", "fmaxl", ++ "fmodl", "log10l", "log2l", "logl", ++ "nearbyintl", "powl", "rintl", "roundl", ++ "sinl", "sqrtl", "truncl"}; ++ ++ // Check that LibCalls is sorted alphabetically. ++ auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; }; ++ assert(std::is_sorted(std::begin(LibCalls), std::end(LibCalls), Comp)); ++ return std::binary_search(std::begin(LibCalls), std::end(LibCalls), ++ CallSym, Comp); ++} ++ ++/// This function returns true if Ty is fp128, {f128} or i128 which was ++/// originally a fp128. ++static bool originalTypeIsF128(const Type *Ty, const char *Func) { ++ if (Ty->isFP128Ty()) ++ return true; ++ ++ if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && ++ Ty->getStructElementType(0)->isFP128Ty()) ++ return true; ++ ++ // If the Ty is i128 and the function being called is a long double emulation ++ // routine, then the original type is f128. ++ return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func)); ++} ++ ++/// Return true if the original type was vXfXX. ++static bool originalEVTTypeIsVectorFloat(EVT Ty) { ++ if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint()) ++ return true; ++ ++ return false; ++} ++ ++/// Return true if the original type was vXfXX / vXfXX. ++static bool originalTypeIsVectorFloat(const Type * Ty) { ++ if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy()) ++ return true; ++ ++ return false; ++} ++ ++LoongArchCCState::SpecialCallingConvType ++LoongArchCCState::getSpecialCallingConvForCallee(const SDNode *Callee, ++ const LoongArchSubtarget &Subtarget) { ++ LoongArchCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; ++ return SpecialCallingConv; ++} ++ ++void LoongArchCCState::PreAnalyzeCallResultForF128( ++ const SmallVectorImpl &Ins, ++ const Type *RetTy, const char *Call) { ++ for (unsigned i = 0; i < Ins.size(); ++i) { ++ OriginalArgWasF128.push_back( ++ originalTypeIsF128(RetTy, Call)); ++ OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy()); ++ } ++} ++ ++/// Identify lowered values that originated from f128 or float arguments and ++/// record this for use by RetCC_LoongArchLP64LPX32. ++void LoongArchCCState::PreAnalyzeReturnForF128( ++ const SmallVectorImpl &Outs) { ++ const MachineFunction &MF = getMachineFunction(); ++ for (unsigned i = 0; i < Outs.size(); ++i) { ++ OriginalArgWasF128.push_back( ++ originalTypeIsF128(MF.getFunction().getReturnType(), nullptr)); ++ OriginalArgWasFloat.push_back( ++ MF.getFunction().getReturnType()->isFloatingPointTy()); ++ } ++} ++ ++/// Identify lower values that originated from vXfXX and record ++/// this. ++void LoongArchCCState::PreAnalyzeCallResultForVectorFloat( ++ const SmallVectorImpl &Ins, const Type *RetTy) { ++ for (unsigned i = 0; i < Ins.size(); ++i) { ++ OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy)); ++ } ++} ++ ++/// Identify lowered values that originated from vXfXX arguments and record ++/// this. ++void LoongArchCCState::PreAnalyzeReturnForVectorFloat( ++ const SmallVectorImpl &Outs) { ++ for (unsigned i = 0; i < Outs.size(); ++i) { ++ ISD::OutputArg Out = Outs[i]; ++ OriginalRetWasFloatVector.push_back( ++ originalEVTTypeIsVectorFloat(Out.ArgVT)); ++ } ++} ++ ++/// Identify lowered values that originated from f128, float and sret to vXfXX ++/// arguments and record this. ++void LoongArchCCState::PreAnalyzeCallOperands( ++ const SmallVectorImpl &Outs, ++ std::vector &FuncArgs, ++ const char *Func) { ++ for (unsigned i = 0; i < Outs.size(); ++i) { ++ TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex]; ++ ++ OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func)); ++ OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy()); ++ OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy()); ++ CallOperandIsFixed.push_back(Outs[i].IsFixed); ++ } ++} ++ ++/// Identify lowered values that originated from f128, float and vXfXX arguments ++/// and record this. ++void LoongArchCCState::PreAnalyzeFormalArgumentsForF128( ++ const SmallVectorImpl &Ins) { ++ const MachineFunction &MF = getMachineFunction(); ++ for (unsigned i = 0; i < Ins.size(); ++i) { ++ Function::const_arg_iterator FuncArg = MF.getFunction().arg_begin(); ++ ++ // SRet arguments cannot originate from f128 or {f128} returns so we just ++ // push false. We have to handle this specially since SRet arguments ++ // aren't mapped to an original argument. ++ if (Ins[i].Flags.isSRet()) { ++ OriginalArgWasF128.push_back(false); ++ OriginalArgWasFloat.push_back(false); ++ OriginalArgWasFloatVector.push_back(false); ++ continue; ++ } ++ ++ assert(Ins[i].getOrigArgIndex() < MF.getFunction().arg_size()); ++ std::advance(FuncArg, Ins[i].getOrigArgIndex()); ++ ++ OriginalArgWasF128.push_back( ++ originalTypeIsF128(FuncArg->getType(), nullptr)); ++ OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); ++ ++ // The LoongArch vector ABI exhibits a corner case of sorts or quirk; if the ++ // first argument is actually an SRet pointer to a vector, then the next ++ // argument slot is $a2. ++ OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy()); ++ } ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h +new file mode 100644 +index 000000000..1c1a1446e +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCCState.h +@@ -0,0 +1,165 @@ ++//===---- LoongArchCCState.h - CCState with LoongArch specific extensions -----------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LoongArchCCSTATE_H ++#define LoongArchCCSTATE_H ++ ++#include "LoongArchISelLowering.h" ++#include "llvm/ADT/SmallVector.h" ++#include "llvm/CodeGen/CallingConvLower.h" ++ ++namespace llvm { ++class SDNode; ++class LoongArchSubtarget; ++ ++class LoongArchCCState : public CCState { ++public: ++ enum SpecialCallingConvType { NoSpecialCallingConv }; ++ ++ /// Determine the SpecialCallingConvType for the given callee ++ static SpecialCallingConvType ++ getSpecialCallingConvForCallee(const SDNode *Callee, ++ const LoongArchSubtarget &Subtarget); ++ ++private: ++ /// Identify lowered values that originated from f128 arguments and record ++ /// this for use by RetCC_LoongArchLP64LPX32. ++ void PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, ++ const Type *RetTy, const char * Func); ++ ++ /// Identify lowered values that originated from f128 arguments and record ++ /// this for use by RetCC_LoongArchLP64LPX32. ++ void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs); ++ ++ /// Identify lowered values that originated from f128 arguments and record ++ /// this. ++ void ++ PreAnalyzeCallOperands(const SmallVectorImpl &Outs, ++ std::vector &FuncArgs, ++ const char *Func); ++ ++ /// Identify lowered values that originated from f128 arguments and record ++ /// this for use by RetCC_LoongArchLP64LPX32. ++ void ++ PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl &Ins); ++ ++ void ++ PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl &Ins, ++ const Type *RetTy); ++ ++ void PreAnalyzeFormalArgumentsForVectorFloat( ++ const SmallVectorImpl &Ins); ++ ++ void ++ PreAnalyzeReturnForVectorFloat(const SmallVectorImpl &Outs); ++ ++ /// Records whether the value has been lowered from an f128. ++ SmallVector OriginalArgWasF128; ++ ++ /// Records whether the value has been lowered from float. ++ SmallVector OriginalArgWasFloat; ++ ++ /// Records whether the value has been lowered from a floating point vector. ++ SmallVector OriginalArgWasFloatVector; ++ ++ /// Records whether the return value has been lowered from a floating point ++ /// vector. ++ SmallVector OriginalRetWasFloatVector; ++ ++ /// Records whether the value was a fixed argument. ++ /// See ISD::OutputArg::IsFixed, ++ SmallVector CallOperandIsFixed; ++ ++ // FIXME: This should probably be a fully fledged calling convention. ++ SpecialCallingConvType SpecialCallingConv; ++ ++public: ++ LoongArchCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, ++ SmallVectorImpl &locs, LLVMContext &C, ++ SpecialCallingConvType SpecialCC = NoSpecialCallingConv) ++ : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} ++ ++ void ++ AnalyzeCallOperands(const SmallVectorImpl &Outs, ++ CCAssignFn Fn, ++ std::vector &FuncArgs, ++ const char *Func) { ++ PreAnalyzeCallOperands(Outs, FuncArgs, Func); ++ CCState::AnalyzeCallOperands(Outs, Fn); ++ OriginalArgWasF128.clear(); ++ OriginalArgWasFloat.clear(); ++ OriginalArgWasFloatVector.clear(); ++ CallOperandIsFixed.clear(); ++ } ++ ++ // The AnalyzeCallOperands in the base class is not usable since we must ++ // provide a means of accessing ArgListEntry::IsFixed. Delete them from this ++ // class. This doesn't stop them being used via the base class though. ++ void AnalyzeCallOperands(const SmallVectorImpl &Outs, ++ CCAssignFn Fn) = delete; ++ void AnalyzeCallOperands(const SmallVectorImpl &Outs, ++ SmallVectorImpl &Flags, ++ CCAssignFn Fn) = delete; ++ ++ void AnalyzeFormalArguments(const SmallVectorImpl &Ins, ++ CCAssignFn Fn) { ++ PreAnalyzeFormalArgumentsForF128(Ins); ++ CCState::AnalyzeFormalArguments(Ins, Fn); ++ OriginalArgWasFloat.clear(); ++ OriginalArgWasF128.clear(); ++ OriginalArgWasFloatVector.clear(); ++ } ++ ++ void AnalyzeCallResult(const SmallVectorImpl &Ins, ++ CCAssignFn Fn, const Type *RetTy, ++ const char *Func) { ++ PreAnalyzeCallResultForF128(Ins, RetTy, Func); ++ PreAnalyzeCallResultForVectorFloat(Ins, RetTy); ++ CCState::AnalyzeCallResult(Ins, Fn); ++ OriginalArgWasFloat.clear(); ++ OriginalArgWasF128.clear(); ++ OriginalArgWasFloatVector.clear(); ++ } ++ ++ void AnalyzeReturn(const SmallVectorImpl &Outs, ++ CCAssignFn Fn) { ++ PreAnalyzeReturnForF128(Outs); ++ PreAnalyzeReturnForVectorFloat(Outs); ++ CCState::AnalyzeReturn(Outs, Fn); ++ OriginalArgWasFloat.clear(); ++ OriginalArgWasF128.clear(); ++ OriginalArgWasFloatVector.clear(); ++ } ++ ++ bool CheckReturn(const SmallVectorImpl &ArgsFlags, ++ CCAssignFn Fn) { ++ PreAnalyzeReturnForF128(ArgsFlags); ++ PreAnalyzeReturnForVectorFloat(ArgsFlags); ++ bool Return = CCState::CheckReturn(ArgsFlags, Fn); ++ OriginalArgWasFloat.clear(); ++ OriginalArgWasF128.clear(); ++ OriginalArgWasFloatVector.clear(); ++ return Return; ++ } ++ ++ bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } ++ bool WasOriginalArgFloat(unsigned ValNo) { ++ return OriginalArgWasFloat[ValNo]; ++ } ++ bool WasOriginalArgVectorFloat(unsigned ValNo) const { ++ return OriginalArgWasFloatVector[ValNo]; ++ } ++ bool WasOriginalRetVectorFloat(unsigned ValNo) const { ++ return OriginalRetWasFloatVector[ValNo]; ++ } ++ bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } ++ SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } ++}; ++} ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td +index 984416316..e8564e85b 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchCallingConv.td +@@ -1,23 +1,310 @@ +-//=- LoongArchCallingConv.td - Calling Conventions LoongArch -*- tablegen -*-=// ++//===-- LoongArchCallingConv.td - Calling Conventions for LoongArch --*- tablegen -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. + // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + // + //===----------------------------------------------------------------------===// ++// This describes the calling conventions for LoongArch architecture. ++//===----------------------------------------------------------------------===// ++ ++/// CCIfSubtarget - Match if the current subtarget has a feature F. ++class CCIfSubtarget ++ : CCIf" ++ "(State.getMachineFunction().getSubtarget()).", ++ F), ++ A>; ++ ++// The inverse of CCIfSubtarget ++class CCIfSubtargetNot : CCIfSubtarget; ++ ++/// Match if the original argument (before lowering) was a float. ++/// For example, this is true for i32's that were lowered from soft-float. ++class CCIfOrigArgWasNotFloat ++ : CCIf<"!static_cast(&State)->WasOriginalArgFloat(ValNo)", ++ A>; ++ ++/// Match if the original argument (before lowering) was a 128-bit float (i.e. ++/// long double). ++class CCIfOrigArgWasF128 ++ : CCIf<"static_cast(&State)->WasOriginalArgF128(ValNo)", A>; ++ ++/// Match if this specific argument is a vararg. ++/// This is slightly different fro CCIfIsVarArg which matches if any argument is ++/// a vararg. ++class CCIfArgIsVarArg ++ : CCIf<"!static_cast(&State)->IsCallOperandFixed(ValNo)", A>; ++ ++/// Match if the return was a floating point vector. ++class CCIfOrigArgWasNotVectorFloat ++ : CCIf<"!static_cast(&State)" ++ "->WasOriginalRetVectorFloat(ValNo)", A>; ++ ++/// Match if the special calling conv is the specified value. ++class CCIfSpecialCallingConv ++ : CCIf<"static_cast(&State)->getSpecialCallingConv() == " ++ "LoongArchCCState::" # CC, A>; ++ ++// For soft-float, f128 values are returned in A0_64 rather than V1_64. ++def RetCC_F128SoftFloat : CallingConv<[ ++ CCAssignToReg<[A0_64, A1_64]> ++]>; ++ + // +-// This describes the calling conventions for the LoongArch architecture. +-// ++// For hard-float, f128 values are returned as a pair of f64's rather than a ++// pair of i64's. ++def RetCC_F128HardFloat : CallingConv<[ ++ //CCBitConvertToType, ++ ++ // Contrary to the ABI documentation, a struct containing a long double is ++ // returned in $f0, and $f1 instead of the usual $f0, and $f2. This is to ++ // match the de facto ABI as implemented by GCC. ++ CCIfInReg>, ++ ++ CCAssignToReg<[A0_64, A1_64]> ++]>; ++ ++// Handle F128 specially since we can't identify the original type during the ++// tablegen-erated code. ++def RetCC_F128 : CallingConv<[ ++ CCIfSubtarget<"useSoftFloat()", ++ CCIfType<[i64], CCDelegateTo>>, ++ CCIfSubtargetNot<"useSoftFloat()", ++ CCIfType<[i64], CCDelegateTo>> ++]>; ++ ++//===----------------------------------------------------------------------===// ++// LoongArch LP32 Calling Convention ++//===----------------------------------------------------------------------===// ++ ++def CC_LoongArchLP32 : CallingConv<[ ++ // Promote i8/i16 arguments to i32. ++ CCIfType<[i1, i8, i16], CCPromoteToType>, ++ ++ // Integer values get stored in stack slots that are 4 bytes in ++ // size and 4-byte aligned. ++ CCIfType<[i32, f32], CCAssignToStack<4, 4>>, ++ ++ // Integer values get stored in stack slots that are 8 bytes in ++ // size and 8-byte aligned. ++ CCIfType<[f64], CCAssignToStack<8, 8>> ++]>; ++ ++// Only the return rules are defined here for LP32. The rules for argument ++// passing are defined in LoongArchISelLowering.cpp. ++def RetCC_LoongArchLP32 : CallingConv<[ ++ // Promote i1/i8/i16 return values to i32. ++ CCIfType<[i1, i8, i16], CCPromoteToType>, ++ ++ // i32 are returned in registers V0, V1, A0, A1, unless the original return ++ // type was a vector of floats. ++ CCIfOrigArgWasNotVectorFloat>>, ++ ++ // f32 are returned in registers F0, F2 ++ CCIfType<[f32], CCAssignToReg<[F0, F1]>>, ++ ++ // f64 arguments are returned in F0_64 and F2_64 in FP64bit mode or ++ // in F0 and F1 in FP32bit mode. ++ CCIfType<[f64], CCIfSubtarget<"isFP64bit()", CCAssignToReg<[F0_64, F1_64]>>> ++]>; ++ ++def CC_LoongArchLP32_FP32 : CustomCallingConv; ++def CC_LoongArchLP32_FP64 : CustomCallingConv; ++def CC_LoongArch_F128 : CustomCallingConv; ++ ++def CC_LoongArchLP32_FP : CallingConv<[ ++ CCIfSubtargetNot<"isFP64bit()", CCDelegateTo>, ++ CCIfSubtarget<"isFP64bit()", CCDelegateTo> ++]>; ++ ++//===----------------------------------------------------------------------===// ++// LoongArch LPX32/LP64 Calling Convention ++//===----------------------------------------------------------------------===// ++ ++def CC_LoongArchLP64LPX32_SoftFloat : CallingConv<[ ++ CCAssignToReg<[A0, A1, A2, A3, ++ A4, A5, A6, A7]>, ++ CCAssignToStack<4, 8> ++]>; ++ ++def CC_LoongArchLP64LPX32 : CallingConv<[ ++ ++ // All integers (except soft-float integers) are promoted to 64-bit. ++ CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat>>, ++ ++ // The only i32's we have left are soft-float arguments. ++ CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], CCDelegateTo>>, ++ ++ // Integer arguments are passed in integer registers. ++ //CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, ++ // A4_64, A5_64, A6_64, A7_64], ++ // [F0_64, F1_64, F2_64, F3_64, ++ // F4_64, F5_64, F6_64, F7_64]>>, ++ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, ++ A4_64, A5_64, A6_64, A7_64]>>, ++ ++ // f32 arguments are passed in single precision FP registers. ++ CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3, ++ F4, F5, F6, F7]>>, ++ ++ // f64 arguments are passed in double precision FP registers. ++ CCIfType<[f64], CCAssignToReg<[F0_64, F1_64, F2_64, F3_64, ++ F4_64, F5_64, F6_64, F7_64]>>, ++ ++ // others f32 arguments are passed in single precision FP registers. ++ CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, A4, A5, A6, A7]>>, ++ ++ // others f64 arguments are passed in double precision FP registers. ++ CCIfType<[f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, ++ A4_64, A5_64, A6_64, A7_64]>>, ++ ++ CCIfSubtarget<"hasLSX()", ++ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], ++ CCAssignToRegWithShadow<[VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7], ++ [A0_64, A1_64, A2_64, A3_64, ++ A4_64, A5_64, A6_64, A7_64]>>>, ++ CCIfSubtarget<"hasLASX()", ++ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], ++ CCAssignToRegWithShadow<[XR0, XR1, XR2, XR3, XR4, XR5, XR6, XR7], ++ [A0_64, A1_64, A2_64, A3_64, ++ A4_64, A5_64, A6_64, A7_64]>>>, ++ ++ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. ++ CCIfType<[f32], CCAssignToStack<4, 8>>, ++ CCIfType<[i64, f64], CCAssignToStack<8, 8>>, ++ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], ++ CCAssignToStack<16, 16>>, ++ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], ++ CCAssignToStack<32, 32>> ++]>; ++ ++// LPX32/LP64 variable arguments. ++// All arguments are passed in integer registers. ++def CC_LoongArchLP64LPX32_VarArg : CallingConv<[ ++ // All integers are promoted to 64-bit. ++ CCIfType<[i8, i16, i32], CCPromoteToType>, ++ ++ CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, A4, A5, A6, A7]>>, ++ ++ CCIfType<[i64], CCIfOrigArgWasF128>>, ++ ++ CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, ++ A4_64, A5_64, A6_64, A7_64]>>, ++ ++ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. ++ CCIfType<[f32], CCAssignToStack<4, 8>>, ++ CCIfType<[i64, f64], CCAssignToStack<8, 8>> ++]>; ++ ++def RetCC_LoongArchLP64LPX32 : CallingConv<[ ++ // f128 needs to be handled similarly to f32 and f64. However, f128 is not ++ // legal and is lowered to i128 which is further lowered to a pair of i64's. ++ // This presents us with a problem for the calling convention since hard-float ++ // still needs to pass them in FPU registers, and soft-float needs to use $v0, ++ // and $a0 instead of the usual $v0, and $v1. We therefore resort to a ++ // pre-analyze (see PreAnalyzeReturnForF128()) step to pass information on ++ // whether the result was originally an f128 into the tablegen-erated code. ++ // ++ // f128 should only occur for the LP64 ABI where long double is 128-bit. On ++ // LPX32, long double is equivalent to double. ++ CCIfType<[i64], CCIfOrigArgWasF128>>, ++ ++ CCIfType<[i8, i16, i32, i64], CCIfInReg>>, ++ ++ // i64 are returned in registers V0_64, V1_64 ++ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64]>>, ++ ++ CCIfSubtarget<"hasLSX()", ++ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToReg<[VR0]>>>, ++ ++ CCIfSubtarget<"hasLASX()", ++ CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], CCAssignToReg<[XR0]>>>, ++ ++ CCIfSubtarget<"hasLASX()", ++ CCIfType<[i64], CCAssignToReg<[A0_64, A1_64]>>>, ++ ++ // f32 are returned in registers F0, F2 ++ CCIfType<[f32], CCAssignToReg<[F0, F1]>>, ++ ++ // f64 are returned in registers D0, D2 ++ CCIfType<[f64], CCAssignToReg<[F0_64, F1_64]>> ++]>; ++ + //===----------------------------------------------------------------------===// ++// LoongArch Calling Convention Dispatch ++//===----------------------------------------------------------------------===// ++ ++def RetCC_LoongArch : CallingConv<[ ++ CCIfSubtarget<"isABI_LPX32()", CCDelegateTo>, ++ CCIfSubtarget<"isABI_LP64()", CCDelegateTo>, ++ CCDelegateTo ++]>; ++ ++def CC_LoongArch_ByVal : CallingConv<[ ++ CCIfSubtarget<"isABI_LP32()", CCIfByVal>>, ++ CCIfByVal> ++]>; ++ ++def CC_LoongArch_FixedArg : CallingConv<[ ++ CCIfByVal>, ++ //CCIfByVal>>, ++ ++ // f128 needs to be handled similarly to f32 and f64 on hard-float. However, ++ // f128 is not legal and is lowered to i128 which is further lowered to a pair ++ // of i64's. ++ // This presents us with a problem for the calling convention since hard-float ++ // still needs to pass them in FPU registers. We therefore resort to a ++ // pre-analyze (see PreAnalyzeFormalArgsForF128()) step to pass information on ++ // whether the argument was originally an f128 into the tablegen-erated code. ++ // ++ // f128 should only occur for the LP64 ABI where long double is 128-bit. On ++ // LPX32, long double is equivalent to double. ++ CCIfType<[i64], ++ CCIfSubtargetNot<"useSoftFloat()", ++ CCIfOrigArgWasF128>>>, ++ ++ CCIfSubtarget<"isABI_LP32()", CCDelegateTo>, ++ CCDelegateTo ++]>; ++ ++def CC_LoongArch_VarArg : CallingConv<[ ++ CCIfByVal>, ++ ++ CCIfSubtarget<"isABI_LP32()", CCDelegateTo>, ++ CCDelegateTo ++]>; ++ ++def CC_LoongArch : CallingConv<[ ++ CCIfVarArg>>, ++ CCDelegateTo ++]>; ++ ++//===----------------------------------------------------------------------===// ++// Callee-saved register lists. ++//===----------------------------------------------------------------------===// ++ ++def CSR_SingleFloatOnly : CalleeSavedRegs<(add (sequence "F%u", 31, 24), RA, FP, ++ (sequence "S%u", 8, 0))>; ++ ++//def CSR_LP32_FPXX : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, ++// (sequence "S%u", 8, 0))> { ++// let OtherPreserved = (add (decimate (sequence "F%u", 30, 20), 2)); ++//} + +-def CSR_ILP32S_LP64S +- : CalleeSavedRegs<(add R1, (sequence "R%u", 22, 31))>; ++def CSR_LP32 : CalleeSavedRegs<(add (sequence "F%u_64", 31, 24), RA, FP, ++ (sequence "S%u", 8, 0))>; + +-def CSR_ILP32F_LP64F +- : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u", 24, 31))>; ++//def CSR_LP32_FP64 : ++// CalleeSavedRegs<(add (decimate (sequence "D%u_64", 30, 20), 2), RA, FP, ++// (sequence "S%u", 8, 0))>; + +-def CSR_ILP32D_LP64D +- : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u_64", 24, 31))>; ++def CSR_LPX32 : CalleeSavedRegs<(add F20_64, F22_64, F24_64, F26_64, F28_64, ++ F30_64, RA_64, FP_64, ++ (sequence "S%u_64", 8, 0))>; + +-// Needed for implementation of LoongArchRegisterInfo::getNoPreservedMask() +-def CSR_NoRegs : CalleeSavedRegs<(add)>; ++//def CSR_LP64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, SP_64, FP_64, ++def CSR_LP64 : CalleeSavedRegs<(add (sequence "F%u_64", 31, 24), RA_64, FP_64, ++ (sequence "S%u_64", 8, 0))>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp +new file mode 100644 +index 000000000..0f33e1db6 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp +@@ -0,0 +1,2471 @@ ++//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains a pass that expands pseudo instructions into target ++// instructions to allow proper scheduling, if-conversion, and other late ++// optimizations. This pass should be run after register allocation but before ++// the post-regalloc scheduling pass. ++// ++// This is currently only used for expanding atomic pseudos after register ++// allocation. We do this to avoid the fast register allocator introducing ++// spills between ll and sc. These stores cause some LoongArch implementations to ++// abort the atomic RMW sequence. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArch.h" ++#include "LoongArchInstrInfo.h" ++#include "LoongArchSubtarget.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/CodeGen/LivePhysRegs.h" ++#include "llvm/CodeGen/MachineFunctionPass.h" ++#include "llvm/CodeGen/MachineInstrBuilder.h" ++ ++using namespace llvm; ++ ++#define DEBUG_TYPE "loongarch-pseudo" ++ ++namespace { ++ class LoongArchExpandPseudo : public MachineFunctionPass { ++ public: ++ static char ID; ++ LoongArchExpandPseudo() : MachineFunctionPass(ID) {} ++ ++ const LoongArchInstrInfo *TII; ++ const LoongArchSubtarget *STI; ++ ++ bool runOnMachineFunction(MachineFunction &Fn) override; ++ ++ MachineFunctionProperties getRequiredProperties() const override { ++ return MachineFunctionProperties().set( ++ MachineFunctionProperties::Property::NoVRegs); ++ } ++ ++ StringRef getPassName() const override { ++ return "LoongArch pseudo instruction expansion pass"; ++ } ++ ++ private: ++ bool expandAtomicCmpSwap(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MBBI, ++ MachineBasicBlock::iterator &NextMBBI); ++ bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MBBI, ++ MachineBasicBlock::iterator &NextMBBI); ++ ++ bool expandAtomicBinOp(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI, unsigned Size); ++ bool expandXINSERT_BOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandINSERT_HOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandXINSERT_FWOp(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandAtomicBinOpSubword(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ ++ bool expandPseudoCall(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandPseudoTailCall(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I); ++ ++ bool expandPseudoTEQ(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ ++ bool expandLoadAddr(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ ++ bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, ++ MachineBasicBlock::iterator &NMBB); ++ bool expandMBB(MachineBasicBlock &MBB); ++ }; ++ char LoongArchExpandPseudo::ID = 0; ++} ++ ++static bool hasDbar(MachineBasicBlock *MBB) { ++ ++ for (MachineBasicBlock::iterator MBBb = MBB->begin(), MBBe = MBB->end(); ++ MBBb != MBBe; ++MBBb) { ++ if (MBBb->getOpcode() == LoongArch::DBAR) ++ return true; ++ if (MBBb->mayLoad() || MBBb->mayStore()) ++ break; ++ } ++ return false; ++} ++ ++bool LoongArchExpandPseudo::expandAtomicCmpSwapSubword( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ unsigned LL, SC; ++ unsigned ZERO = LoongArch::ZERO; ++ unsigned BNE = LoongArch::BNE32; ++ unsigned BEQ = LoongArch::BEQ32; ++ unsigned SEOp = ++ I->getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA ? LoongArch::EXT_W_B32 : LoongArch::EXT_W_H32; ++ ++ LL = LoongArch::LL_W; ++ SC = LoongArch::SC_W; ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned Ptr = I->getOperand(1).getReg(); ++ unsigned Mask = I->getOperand(2).getReg(); ++ unsigned ShiftCmpVal = I->getOperand(3).getReg(); ++ unsigned Mask2 = I->getOperand(4).getReg(); ++ unsigned ShiftNewVal = I->getOperand(5).getReg(); ++ unsigned ShiftAmnt = I->getOperand(6).getReg(); ++ unsigned Scratch = I->getOperand(7).getReg(); ++ unsigned Scratch2 = I->getOperand(8).getReg(); ++ ++ // insert new blocks after the current block ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, loop1MBB); ++ MF->insert(It, loop2MBB); ++ MF->insert(It, sinkMBB); ++ MF->insert(It, exitMBB); ++ ++ // Transfer the remainder of BB and its successor edges to exitMBB. ++ exitMBB->splice(exitMBB->begin(), &BB, ++ std::next(MachineBasicBlock::iterator(I)), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ // thisMBB: ++ // ... ++ // fallthrough --> loop1MBB ++ BB.addSuccessor(loop1MBB, BranchProbability::getOne()); ++ loop1MBB->addSuccessor(sinkMBB); ++ loop1MBB->addSuccessor(loop2MBB); ++ loop1MBB->normalizeSuccProbs(); ++ loop2MBB->addSuccessor(loop1MBB); ++ loop2MBB->addSuccessor(sinkMBB); ++ loop2MBB->normalizeSuccProbs(); ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ // loop1MBB: ++ // ll dest, 0(ptr) ++ // and Mask', dest, Mask ++ // bne Mask', ShiftCmpVal, exitMBB ++ BuildMI(loop1MBB, DL, TII->get(LL), Scratch).addReg(Ptr).addImm(0); ++ BuildMI(loop1MBB, DL, TII->get(LoongArch::AND32), Scratch2) ++ .addReg(Scratch) ++ .addReg(Mask); ++ BuildMI(loop1MBB, DL, TII->get(BNE)) ++ .addReg(Scratch2).addReg(ShiftCmpVal).addMBB(sinkMBB); ++ ++ // loop2MBB: ++ // and dest, dest, mask2 ++ // or dest, dest, ShiftNewVal ++ // sc dest, dest, 0(ptr) ++ // beq dest, $0, loop1MBB ++ BuildMI(loop2MBB, DL, TII->get(LoongArch::AND32), Scratch) ++ .addReg(Scratch, RegState::Kill) ++ .addReg(Mask2); ++ BuildMI(loop2MBB, DL, TII->get(LoongArch::OR32), Scratch) ++ .addReg(Scratch, RegState::Kill) ++ .addReg(ShiftNewVal); ++ BuildMI(loop2MBB, DL, TII->get(SC), Scratch) ++ .addReg(Scratch, RegState::Kill) ++ .addReg(Ptr) ++ .addImm(0); ++ BuildMI(loop2MBB, DL, TII->get(BEQ)) ++ .addReg(Scratch, RegState::Kill) ++ .addReg(ZERO) ++ .addMBB(loop1MBB); ++ ++ // sinkMBB: ++ // srl srlres, Mask', shiftamt ++ // sign_extend dest,srlres ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::SRL_W), Dest) ++ .addReg(Scratch2) ++ .addReg(ShiftAmnt); ++ ++ BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); ++ ++ if (!hasDbar(sinkMBB)) { ++ MachineBasicBlock::iterator Pos = sinkMBB->begin(); ++ BuildMI(*sinkMBB, Pos, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); ++ } ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *loop1MBB); ++ computeAndAddLiveIns(LiveRegs, *loop2MBB); ++ computeAndAddLiveIns(LiveRegs, *sinkMBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ const unsigned Size = ++ I->getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8; ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned LL, SC, ZERO, BNE, BEQ, MOVE; ++ ++ if (Size == 4) { ++ LL = LoongArch::LL_W; ++ SC = LoongArch::SC_W; ++ BNE = LoongArch::BNE32; ++ BEQ = LoongArch::BEQ32; ++ ++ ZERO = LoongArch::ZERO; ++ MOVE = LoongArch::OR32; ++ } else { ++ LL = LoongArch::LL_D; ++ SC = LoongArch::SC_D; ++ ZERO = LoongArch::ZERO_64; ++ BNE = LoongArch::BNE; ++ BEQ = LoongArch::BEQ; ++ MOVE = LoongArch::OR; ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned Ptr = I->getOperand(1).getReg(); ++ unsigned OldVal = I->getOperand(2).getReg(); ++ unsigned NewVal = I->getOperand(3).getReg(); ++ unsigned Scratch = I->getOperand(4).getReg(); ++ ++ // insert new blocks after the current block ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, loop1MBB); ++ MF->insert(It, loop2MBB); ++ MF->insert(It, exitMBB); ++ ++ // Transfer the remainder of BB and its successor edges to exitMBB. ++ exitMBB->splice(exitMBB->begin(), &BB, ++ std::next(MachineBasicBlock::iterator(I)), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ // thisMBB: ++ // ... ++ // fallthrough --> loop1MBB ++ BB.addSuccessor(loop1MBB, BranchProbability::getOne()); ++ loop1MBB->addSuccessor(exitMBB); ++ loop1MBB->addSuccessor(loop2MBB); ++ loop1MBB->normalizeSuccProbs(); ++ loop2MBB->addSuccessor(loop1MBB); ++ loop2MBB->addSuccessor(exitMBB); ++ loop2MBB->normalizeSuccProbs(); ++ ++ // loop1MBB: ++ // ll dest, 0(ptr) ++ // bne dest, oldval, exitMBB ++ BuildMI(loop1MBB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); ++ BuildMI(loop1MBB, DL, TII->get(BNE)) ++ .addReg(Dest, RegState::Kill).addReg(OldVal).addMBB(exitMBB); ++ ++ // loop2MBB: ++ // move scratch, NewVal ++ // sc Scratch, Scratch, 0(ptr) ++ // beq Scratch, $0, loop1MBB ++ BuildMI(loop2MBB, DL, TII->get(MOVE), Scratch).addReg(NewVal).addReg(ZERO); ++ BuildMI(loop2MBB, DL, TII->get(SC), Scratch) ++ .addReg(Scratch).addReg(Ptr).addImm(0); ++ BuildMI(loop2MBB, DL, TII->get(BEQ)) ++ .addReg(Scratch, RegState::Kill).addReg(ZERO).addMBB(loop1MBB); ++ ++ if (!hasDbar(exitMBB)) { ++ MachineBasicBlock::iterator Pos = exitMBB->begin(); ++ BuildMI(*exitMBB, Pos, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); ++ } ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *loop1MBB); ++ computeAndAddLiveIns(LiveRegs, *loop2MBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandXINSERT_FWOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned Dsttmp = I->getOperand(4).getReg(); ++ unsigned RI = I->getOperand(5).getReg(); ++ unsigned RJ = I->getOperand(6).getReg(); ++ Dsttmp = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *blocks[11]; ++ MachineFunction::iterator It = ++BB.getIterator(); ++ for (int i = 0; i < 11; i++) { ++ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); ++ MF->insert(It, blocks[i]); ++ } ++ ++ MachineBasicBlock *mainMBB = blocks[0]; ++ MachineBasicBlock *FirstMBB = blocks[1]; ++ MachineBasicBlock *sinkMBB = blocks[9]; ++ MachineBasicBlock *exitMBB = blocks[10]; ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ for (int i = 1; i < 9; i++) { ++ mainMBB->addSuccessor(blocks[i]); ++ blocks[i]->addSuccessor(sinkMBB); ++ } ++ ++ unsigned ADDI, BLT, ZERO; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ for (int i = 1; i < 8; i++) { ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); ++ BuildMI(mainMBB, DL, TII->get(BLT)) ++ .addReg(LaneReg) ++ .addReg(RI) ++ .addMBB(blocks[i + 1]); ++ } ++ ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); ++ ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(RJ) ++ .addImm(7); ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ for (int i = 0; i < 7; i++) { ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(RJ) ++ .addImm(i); ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ } ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) ++ .addReg(Dsttmp) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ for (int i = 0; i < 11; i++) { ++ computeAndAddLiveIns(LiveRegs, *blocks[i]); ++ } ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandINSERT_HOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned Dsttmp = I->getOperand(4).getReg(); ++ unsigned RI = I->getOperand(5).getReg(); ++ Dsttmp = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *blocks[11]; ++ MachineFunction::iterator It = ++BB.getIterator(); ++ for (int i = 0; i < 11; i++) { ++ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); ++ MF->insert(It, blocks[i]); ++ } ++ ++ MachineBasicBlock *mainMBB = blocks[0]; ++ MachineBasicBlock *FirstMBB = blocks[1]; ++ MachineBasicBlock *sinkMBB = blocks[9]; ++ MachineBasicBlock *exitMBB = blocks[10]; ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ for (int i = 1; i < 9; i++) { ++ mainMBB->addSuccessor(blocks[i]); ++ blocks[i]->addSuccessor(sinkMBB); ++ } ++ ++ unsigned ADDI, BLT, ZERO; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ for (int i = 1; i < 8; i++) { ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); ++ BuildMI(mainMBB, DL, TII->get(BLT)) ++ .addReg(LaneReg) ++ .addReg(RI) ++ .addMBB(blocks[i + 1]); ++ } ++ ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); ++ ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(SrcValReg) ++ .addImm(7); ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ for (int i = 0; i < 7; i++) { ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(SrcValReg) ++ .addImm(i); ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ } ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::VORI_B), Dest) ++ .addReg(Dsttmp) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ for (int i = 0; i < 11; i++) { ++ computeAndAddLiveIns(LiveRegs, *blocks[i]); ++ } ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandXINSERT_BOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned R4r = I->getOperand(5).getReg(); ++ unsigned Rib = I->getOperand(6).getReg(); ++ unsigned Ris = I->getOperand(7).getReg(); ++ unsigned R7b1 = I->getOperand(8).getReg(); ++ unsigned R7b2 = I->getOperand(9).getReg(); ++ unsigned R7b3 = I->getOperand(10).getReg(); ++ unsigned R7r80_3 = I->getOperand(11).getReg(); ++ unsigned R7r80l_3 = I->getOperand(12).getReg(); ++ unsigned R7r81_3 = I->getOperand(13).getReg(); ++ unsigned R7r81l_3 = I->getOperand(14).getReg(); ++ unsigned R7r82_3 = I->getOperand(15).getReg(); ++ unsigned R7r82l_3 = I->getOperand(16).getReg(); ++ unsigned RI = I->getOperand(17).getReg(); ++ unsigned tmp_Dst73 = I->getOperand(18).getReg(); ++ unsigned Rimm = I->getOperand(19).getReg(); ++ unsigned R70 = I->getOperand(20).getReg(); ++ tmp_Dst73 = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, mainMBB); ++ MF->insert(It, SevenMBB); ++ MF->insert(It, SevenMBB3); ++ MF->insert(It, SevenMBB0); ++ MF->insert(It, SevenMBB1); ++ MF->insert(It, SevenMBB2); ++ MF->insert(It, ZeroMBB); ++ MF->insert(It, ZeroMBB3); ++ MF->insert(It, ZeroMBB0); ++ MF->insert(It, ZeroMBB1); ++ MF->insert(It, ZeroMBB2); ++ MF->insert(It, OneMBB); ++ MF->insert(It, OneMBB3); ++ MF->insert(It, OneMBB0); ++ MF->insert(It, OneMBB1); ++ MF->insert(It, OneMBB2); ++ MF->insert(It, TwoMBB); ++ MF->insert(It, TwoMBB3); ++ MF->insert(It, TwoMBB0); ++ MF->insert(It, TwoMBB1); ++ MF->insert(It, TwoMBB2); ++ MF->insert(It, ThreeMBB); ++ MF->insert(It, ThreeMBB3); ++ MF->insert(It, ThreeMBB0); ++ MF->insert(It, ThreeMBB1); ++ MF->insert(It, ThreeMBB2); ++ MF->insert(It, FourMBB); ++ MF->insert(It, FourMBB3); ++ MF->insert(It, FourMBB0); ++ MF->insert(It, FourMBB1); ++ MF->insert(It, FourMBB2); ++ MF->insert(It, FiveMBB); ++ MF->insert(It, FiveMBB3); ++ MF->insert(It, FiveMBB0); ++ MF->insert(It, FiveMBB1); ++ MF->insert(It, FiveMBB2); ++ MF->insert(It, SixMBB); ++ MF->insert(It, SixMBB3); ++ MF->insert(It, SixMBB0); ++ MF->insert(It, SixMBB1); ++ MF->insert(It, SixMBB2); ++ MF->insert(It, sinkMBB); ++ MF->insert(It, exitMBB); ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ mainMBB->addSuccessor(SevenMBB); ++ mainMBB->addSuccessor(ZeroMBB); ++ mainMBB->addSuccessor(OneMBB); ++ mainMBB->addSuccessor(TwoMBB); ++ mainMBB->addSuccessor(ThreeMBB); ++ mainMBB->addSuccessor(FourMBB); ++ mainMBB->addSuccessor(FiveMBB); ++ mainMBB->addSuccessor(SixMBB); ++ SevenMBB->addSuccessor(SevenMBB0); ++ SevenMBB->addSuccessor(SevenMBB1); ++ SevenMBB->addSuccessor(SevenMBB2); ++ SevenMBB->addSuccessor(SevenMBB3); ++ SevenMBB0->addSuccessor(sinkMBB); ++ SevenMBB1->addSuccessor(sinkMBB); ++ SevenMBB2->addSuccessor(sinkMBB); ++ SevenMBB3->addSuccessor(sinkMBB); ++ ZeroMBB->addSuccessor(ZeroMBB0); ++ ZeroMBB->addSuccessor(ZeroMBB1); ++ ZeroMBB->addSuccessor(ZeroMBB2); ++ ZeroMBB->addSuccessor(ZeroMBB3); ++ ZeroMBB0->addSuccessor(sinkMBB); ++ ZeroMBB1->addSuccessor(sinkMBB); ++ ZeroMBB2->addSuccessor(sinkMBB); ++ ZeroMBB3->addSuccessor(sinkMBB); ++ OneMBB->addSuccessor(OneMBB0); ++ OneMBB->addSuccessor(OneMBB1); ++ OneMBB->addSuccessor(OneMBB2); ++ OneMBB->addSuccessor(OneMBB3); ++ OneMBB0->addSuccessor(sinkMBB); ++ OneMBB1->addSuccessor(sinkMBB); ++ OneMBB2->addSuccessor(sinkMBB); ++ OneMBB3->addSuccessor(sinkMBB); ++ TwoMBB->addSuccessor(TwoMBB0); ++ TwoMBB->addSuccessor(TwoMBB1); ++ TwoMBB->addSuccessor(TwoMBB2); ++ TwoMBB->addSuccessor(TwoMBB3); ++ TwoMBB0->addSuccessor(sinkMBB); ++ TwoMBB1->addSuccessor(sinkMBB); ++ TwoMBB2->addSuccessor(sinkMBB); ++ TwoMBB3->addSuccessor(sinkMBB); ++ ThreeMBB->addSuccessor(ThreeMBB0); ++ ThreeMBB->addSuccessor(ThreeMBB1); ++ ThreeMBB->addSuccessor(ThreeMBB2); ++ ThreeMBB->addSuccessor(ThreeMBB3); ++ ThreeMBB0->addSuccessor(sinkMBB); ++ ThreeMBB1->addSuccessor(sinkMBB); ++ ThreeMBB2->addSuccessor(sinkMBB); ++ ThreeMBB3->addSuccessor(sinkMBB); ++ FourMBB->addSuccessor(FourMBB0); ++ FourMBB->addSuccessor(FourMBB1); ++ FourMBB->addSuccessor(FourMBB2); ++ FourMBB->addSuccessor(FourMBB3); ++ FourMBB0->addSuccessor(sinkMBB); ++ FourMBB1->addSuccessor(sinkMBB); ++ FourMBB2->addSuccessor(sinkMBB); ++ FourMBB3->addSuccessor(sinkMBB); ++ FiveMBB->addSuccessor(FiveMBB0); ++ FiveMBB->addSuccessor(FiveMBB1); ++ FiveMBB->addSuccessor(FiveMBB2); ++ FiveMBB->addSuccessor(FiveMBB3); ++ FiveMBB0->addSuccessor(sinkMBB); ++ FiveMBB1->addSuccessor(sinkMBB); ++ FiveMBB2->addSuccessor(sinkMBB); ++ FiveMBB3->addSuccessor(sinkMBB); ++ SixMBB->addSuccessor(SixMBB0); ++ SixMBB->addSuccessor(SixMBB1); ++ SixMBB->addSuccessor(SixMBB2); ++ SixMBB->addSuccessor(SixMBB3); ++ SixMBB0->addSuccessor(sinkMBB); ++ SixMBB1->addSuccessor(sinkMBB); ++ SixMBB2->addSuccessor(sinkMBB); ++ SixMBB3->addSuccessor(sinkMBB); ++ ++ unsigned SRLI, ADDI, OR, MOD, BLT, ZERO; ++ SRLI = isGP64 ? LoongArch::SRLI_D : LoongArch::SRLI_W; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ OR = isGP64 ? LoongArch::OR : LoongArch::OR32; ++ MOD = isGP64 ? LoongArch::MOD_DU : LoongArch::MOD_WU; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ BuildMI(mainMBB, DL, TII->get(SRLI), Rimm).addReg(LaneReg).addImm(2); ++ BuildMI(mainMBB, DL, TII->get(ADDI), R4r).addReg(ZERO).addImm(4); ++ BuildMI(mainMBB, DL, TII->get(OR), Rib).addReg(Rimm).addReg(ZERO); ++ BuildMI(mainMBB, DL, TII->get(MOD), Ris).addReg(Rib).addReg(R4r); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(1); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ZeroMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(2); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(OneMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(3); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(TwoMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(4); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ThreeMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(5); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FourMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(6); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FiveMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(7); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(SixMBB); ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB); ++ ++ BuildMI(SevenMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(7); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b1) ++ .addMBB(SevenMBB0); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b2) ++ .addMBB(SevenMBB1); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b3) ++ .addMBB(SevenMBB2); ++ BuildMI(SevenMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB3); ++ ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0x00fff); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xff00f); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xffff0); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xfffff); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(0); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(ZeroMBB0); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(ZeroMBB1); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(ZeroMBB2); ++ BuildMI(ZeroMBB, DL, TII->get(LoongArch::B32)).addMBB(ZeroMBB3); ++ ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(1); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(OneMBB0); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(OneMBB1); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(OneMBB2); ++ BuildMI(OneMBB, DL, TII->get(LoongArch::B32)).addMBB(OneMBB3); ++ ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(2); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(TwoMBB0); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(TwoMBB1); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(TwoMBB2); ++ BuildMI(TwoMBB, DL, TII->get(LoongArch::B32)).addMBB(TwoMBB3); ++ ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(3); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b1) ++ .addMBB(ThreeMBB0); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b2) ++ .addMBB(ThreeMBB1); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b3) ++ .addMBB(ThreeMBB2); ++ BuildMI(ThreeMBB, DL, TII->get(LoongArch::B32)).addMBB(ThreeMBB3); ++ ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0x00fff); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xff00f); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xffff0); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xfffff); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(4); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FourMBB0); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FourMBB1); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FourMBB2); ++ BuildMI(FourMBB, DL, TII->get(LoongArch::B32)).addMBB(FourMBB3); ++ ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(5); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FiveMBB0); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FiveMBB1); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FiveMBB2); ++ BuildMI(FiveMBB, DL, TII->get(LoongArch::B32)).addMBB(FiveMBB3); ++ ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(6); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(SixMBB0); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(SixMBB1); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(SixMBB2); ++ BuildMI(SixMBB, DL, TII->get(LoongArch::B32)).addMBB(SixMBB3); ++ ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) ++ .addReg(tmp_Dst73) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *mainMBB); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB0); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB1); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB2); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB3); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB0); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB1); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB2); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB3); ++ computeAndAddLiveIns(LiveRegs, *OneMBB); ++ computeAndAddLiveIns(LiveRegs, *OneMBB0); ++ computeAndAddLiveIns(LiveRegs, *OneMBB1); ++ computeAndAddLiveIns(LiveRegs, *OneMBB2); ++ computeAndAddLiveIns(LiveRegs, *OneMBB3); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB0); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB1); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB2); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB3); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB0); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB1); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB2); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB3); ++ computeAndAddLiveIns(LiveRegs, *FourMBB); ++ computeAndAddLiveIns(LiveRegs, *FourMBB0); ++ computeAndAddLiveIns(LiveRegs, *FourMBB1); ++ computeAndAddLiveIns(LiveRegs, *FourMBB2); ++ computeAndAddLiveIns(LiveRegs, *FourMBB3); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB0); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB1); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB2); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB3); ++ computeAndAddLiveIns(LiveRegs, *SixMBB); ++ computeAndAddLiveIns(LiveRegs, *SixMBB0); ++ computeAndAddLiveIns(LiveRegs, *SixMBB1); ++ computeAndAddLiveIns(LiveRegs, *SixMBB2); ++ computeAndAddLiveIns(LiveRegs, *SixMBB3); ++ computeAndAddLiveIns(LiveRegs, *sinkMBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandAtomicBinOpSubword( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ unsigned LL, SC; ++ unsigned BEQ = LoongArch::BEQ32; ++ unsigned SEOp = LoongArch::EXT_W_H32; ++ ++ LL = LoongArch::LL_W; ++ SC = LoongArch::SC_W; ++ ++ bool IsSwap = false; ++ bool IsNand = false; ++ bool IsMAX = false; ++ bool IsMIN = false; ++ bool IsUnsigned = false; ++ ++ unsigned Opcode = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA: ++ IsNand = true; ++ break; ++ case LoongArch::ATOMIC_SWAP_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_SWAP_I16_POSTRA: ++ IsSwap = true; ++ break; ++ case LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA: ++ Opcode = LoongArch::ADD_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_W; ++ IsMAX = true; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_W; ++ IsMIN = true; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_WU; ++ IsMAX = true; ++ IsUnsigned = true; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_WU; ++ IsMIN = true; ++ IsUnsigned = true; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA: ++ Opcode = LoongArch::SUB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_AND_I16_POSTRA: ++ Opcode = LoongArch::AND32; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_OR_I16_POSTRA: ++ Opcode = LoongArch::OR32; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA: ++ SEOp = LoongArch::EXT_W_B32; ++ LLVM_FALLTHROUGH; ++ case LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA: ++ Opcode = LoongArch::XOR32; ++ break; ++ default: ++ llvm_unreachable("Unknown subword atomic pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned Ptr = I->getOperand(1).getReg(); ++ unsigned Incr = I->getOperand(2).getReg(); ++ unsigned Mask = I->getOperand(3).getReg(); ++ unsigned Mask2 = I->getOperand(4).getReg(); ++ unsigned ShiftAmnt = I->getOperand(5).getReg(); ++ unsigned OldVal = I->getOperand(6).getReg(); ++ unsigned BinOpRes = I->getOperand(7).getReg(); ++ unsigned StoreVal = I->getOperand(8).getReg(); ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, loopMBB); ++ MF->insert(It, sinkMBB); ++ MF->insert(It, exitMBB); ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(loopMBB, BranchProbability::getOne()); ++ loopMBB->addSuccessor(sinkMBB); ++ loopMBB->addSuccessor(loopMBB); ++ loopMBB->normalizeSuccProbs(); ++ ++ BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); ++ if (IsNand) { ++ // and andres, oldval, incr2 ++ // nor binopres, $0, andres ++ // and newval, binopres, mask ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) ++ .addReg(OldVal) ++ .addReg(Incr); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::NOR32), BinOpRes) ++ .addReg(LoongArch::ZERO) ++ .addReg(BinOpRes); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) ++ .addReg(BinOpRes) ++ .addReg(Mask); ++ } else if (IsMAX || IsMIN) { ++ ++ unsigned SLTScratch4 = IsUnsigned ? LoongArch::SLTU32 : LoongArch::SLT32; ++ unsigned CMPIncr = IsMAX ? LoongArch::MASKEQZ32 : LoongArch::MASKNEZ32; ++ unsigned CMPOldVal = IsMAX ? LoongArch::MASKNEZ32 : LoongArch::MASKEQZ32; ++ ++ unsigned Scratch4 = I->getOperand(9).getReg(); ++ unsigned Scratch5 = I->getOperand(10).getReg(); ++ ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), Scratch5) ++ .addReg(OldVal) ++ .addReg(Mask); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), Incr) ++ .addReg(Incr) ++ .addReg(Mask); ++ BuildMI(loopMBB, DL, TII->get(SLTScratch4), Scratch4) ++ .addReg(Scratch5) ++ .addReg(Incr); ++ BuildMI(loopMBB, DL, TII->get(CMPOldVal), BinOpRes) ++ .addReg(Scratch5) ++ .addReg(Scratch4); ++ BuildMI(loopMBB, DL, TII->get(CMPIncr), Scratch4) ++ .addReg(Incr) ++ .addReg(Scratch4); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::OR32), BinOpRes) ++ .addReg(BinOpRes) ++ .addReg(Scratch4); ++ ++ } else if (!IsSwap) { ++ // binopres, oldval, incr2 ++ // and newval, binopres, mask ++ BuildMI(loopMBB, DL, TII->get(Opcode), BinOpRes) ++ .addReg(OldVal) ++ .addReg(Incr); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) ++ .addReg(BinOpRes) ++ .addReg(Mask); ++ } else { // atomic.swap ++ // and newval, incr2, mask ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), BinOpRes) ++ .addReg(Incr) ++ .addReg(Mask); ++ } ++ ++ // and StoreVal, OlddVal, Mask2 ++ // or StoreVal, StoreVal, BinOpRes ++ // StoreVal = sc StoreVal, 0(Ptr) ++ // beq StoreVal, zero, loopMBB ++ BuildMI(loopMBB, DL, TII->get(LoongArch::AND32), StoreVal) ++ .addReg(OldVal) ++ .addReg(Mask2); ++ BuildMI(loopMBB, DL, TII->get(LoongArch::OR32), StoreVal) ++ .addReg(StoreVal) ++ .addReg(BinOpRes); ++ BuildMI(loopMBB, DL, TII->get(SC), StoreVal) ++ .addReg(StoreVal) ++ .addReg(Ptr) ++ .addImm(0); ++ BuildMI(loopMBB, DL, TII->get(BEQ)) ++ .addReg(StoreVal) ++ .addReg(LoongArch::ZERO) ++ .addMBB(loopMBB); ++ ++ // sinkMBB: ++ // and maskedoldval1,oldval,mask ++ // srl srlres,maskedoldval1,shiftamt ++ // sign_extend dest,srlres ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::AND32), Dest) ++ .addReg(OldVal) ++ .addReg(Mask); ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::SRL_W), Dest) ++ .addReg(Dest) ++ .addReg(ShiftAmnt); ++ ++ BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *loopMBB); ++ computeAndAddLiveIns(LiveRegs, *sinkMBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI, ++ unsigned Size) { ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned LL, SC, ZERO, BEQ, SUB; ++ if (Size == 4) { ++ LL = LoongArch::LL_W; ++ SC = LoongArch::SC_W; ++ BEQ = LoongArch::BEQ32; ++ ZERO = LoongArch::ZERO; ++ SUB = LoongArch::SUB_W; ++ } else { ++ LL = LoongArch::LL_D; ++ SC = LoongArch::SC_D; ++ ZERO = LoongArch::ZERO_64; ++ BEQ = LoongArch::BEQ; ++ SUB = LoongArch::SUB_D; ++ } ++ ++ unsigned OldVal = I->getOperand(0).getReg(); ++ unsigned Ptr = I->getOperand(1).getReg(); ++ unsigned Incr = I->getOperand(2).getReg(); ++ unsigned Scratch = I->getOperand(3).getReg(); ++ ++ unsigned Opcode = 0; ++ unsigned OR = 0; ++ unsigned AND = 0; ++ unsigned NOR = 0; ++ bool IsNand = false; ++ bool IsSub = false; ++ switch (I->getOpcode()) { ++ case LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA: ++ Opcode = LoongArch::AMADD_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA: ++ IsSub = true; ++ Opcode = LoongArch::AMADD_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I32_POSTRA: ++ Opcode = LoongArch::AMAND_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I32_POSTRA: ++ Opcode = LoongArch::AMOR_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA: ++ Opcode = LoongArch::AMXOR_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA: ++ IsNand = true; ++ AND = LoongArch::AND32; ++ NOR = LoongArch::NOR32; ++ break; ++ case LoongArch::ATOMIC_SWAP_I32_POSTRA: ++ OR = LoongArch::AMSWAP_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_W; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_WU; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_WU; ++ break; ++ case LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA: ++ Opcode = LoongArch::AMADD_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA: ++ IsSub = true; ++ Opcode = LoongArch::AMADD_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I64_POSTRA: ++ Opcode = LoongArch::AMAND_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I64_POSTRA: ++ Opcode = LoongArch::AMOR_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA: ++ Opcode = LoongArch::AMXOR_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA: ++ IsNand = true; ++ AND = LoongArch::AND; ++ NOR = LoongArch::NOR; ++ break; ++ case LoongArch::ATOMIC_SWAP_I64_POSTRA: ++ OR = LoongArch::AMSWAP_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_D; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA: ++ Opcode = LoongArch::AMMAX_DB_DU; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA: ++ Opcode = LoongArch::AMMIN_DB_DU; ++ break; ++ default: ++ llvm_unreachable("Unknown pseudo atomic!"); ++ } ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, loopMBB); ++ MF->insert(It, exitMBB); ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(loopMBB, BranchProbability::getOne()); ++ loopMBB->addSuccessor(exitMBB); ++ loopMBB->addSuccessor(loopMBB); ++ loopMBB->normalizeSuccProbs(); ++ ++ assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); ++ assert((OldVal != Incr) && "Clobbered the wrong reg!"); ++ if (Opcode) { ++ if(IsSub){ ++ BuildMI(loopMBB, DL, TII->get(SUB), Scratch).addReg(ZERO).addReg(Incr); ++ BuildMI(loopMBB, DL, TII->get(Opcode), OldVal).addReg(Scratch).addReg(Ptr).addImm(0); ++ } ++ else{ ++ BuildMI(loopMBB, DL, TII->get(Opcode), OldVal).addReg(Incr).addReg(Ptr).addImm(0); ++ } ++ } else if (IsNand) { ++ assert(AND && NOR && ++ "Unknown nand instruction for atomic pseudo expansion"); ++ BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); ++ BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr); ++ BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch); ++ BuildMI(loopMBB, DL, TII->get(SC), Scratch).addReg(Scratch).addReg(Ptr).addImm(0); ++ BuildMI(loopMBB, DL, TII->get(BEQ)).addReg(Scratch).addReg(ZERO).addMBB(loopMBB); ++ } else { ++ assert(OR && "Unknown instruction for atomic pseudo expansion!"); ++ BuildMI(loopMBB, DL, TII->get(OR), OldVal).addReg(Incr).addReg(Ptr).addImm(0); ++ } ++ ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *loopMBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ MachineFunction *MF = BB.getParent(); ++ MachineInstr &MI = *I; ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned Op = MI.getOpcode(); ++ unsigned DestReg = MI.getOperand(0).getReg(); ++ unsigned TmpReg; ++ const MachineOperand &MO = MI.getOperand(1); ++ Reloc::Model RM = MF->getTarget().getRelocationModel(); ++ ++ MachineInstrBuilder MIB1, MIB2, MIB3, MIB4, MIB5; ++ unsigned HiFlag, LoFlag, HigherFlag, HighestFlag; ++ unsigned HiOp, LoOp, HigherOp, HighestOp, LastOp; ++ bool UseGot = false; ++ ++ HiOp = LoongArch::PCADDU12I_ri; ++ LoOp = LoongArch::ORI_rri; ++ HigherOp = LoongArch::LU32I_D_ri; ++ HighestOp = LoongArch::LU52I_D_rri; ++ ++ switch (Op) { ++ case LoongArch::LoadAddrLocal: ++ if (RM == Reloc::Static) { // for jit ++ HiFlag = LoongArchII::MO_ABS_HI; ++ LoFlag = LoongArchII::MO_ABS_LO; ++ HigherFlag = LoongArchII::MO_ABS_HIGHER; ++ HighestFlag = LoongArchII::MO_ABS_HIGHEST; ++ // lu12i.w + ori + lu32i.d + lu52i.d ++ HiOp = LoongArch::LU12I_W; ++ LoOp = LoongArch::ORI; ++ HigherOp = LoongArch::LU32I_D; ++ HighestOp = LoongArch::LU52I_D; ++ } else { ++ // pcaddu12i + addi.d ++ LoFlag = LoongArchII::MO_PCREL_LO; ++ HiFlag = LoongArchII::MO_PCREL_HI; ++ LoOp = LoongArch::ADDI_D_rri; ++ } ++ break; ++ case LoongArch::LoadAddrLocalRR: ++ // pcaddu12i + ori + lu32i.d + lu52i.d + add.d ++ LoFlag = LoongArchII::MO_PCREL_RRLO; ++ HiFlag = LoongArchII::MO_PCREL_RRHI; ++ HigherFlag = LoongArchII::MO_PCREL_RRHIGHER; ++ HighestFlag = LoongArchII::MO_PCREL_RRHIGHEST; ++ LastOp = LoongArch::ADD_D_rrr; ++ break; ++ case LoongArch::LoadAddrGlobal: ++ case LoongArch::LoadAddrGlobal_Alias: ++ // pcaddu12i + ld.d ++ LoFlag = LoongArchII::MO_GOT_LO; ++ HiFlag = LoongArchII::MO_GOT_HI; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::LD_D_rrii; ++ UseGot = true; ++ break; ++ case LoongArch::LoadAddrGlobalRR: ++ // pcaddu12i + ori + lu32i.d + lu52i.d +ldx.d ++ LoFlag = LoongArchII::MO_GOT_RRLO; ++ HiFlag = LoongArchII::MO_GOT_RRHI; ++ HigherFlag = LoongArchII::MO_GOT_RRHIGHER; ++ HighestFlag = LoongArchII::MO_GOT_RRHIGHEST; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::ORI_rrii; ++ HigherOp = LoongArch::LU32I_D_rii; ++ HighestOp = LoongArch::LU52I_D_rrii; ++ LastOp = LoongArch::LDX_D_rrr; ++ UseGot = true; ++ break; ++ case LoongArch::LoadAddrTLS_LE: ++ // lu12i.w + ori + lu32i.d + lu52i.d ++ LoFlag = LoongArchII::MO_TLSLE_LO; ++ HiFlag = LoongArchII::MO_TLSLE_HI; ++ HigherFlag = LoongArchII::MO_TLSLE_HIGHER; ++ HighestFlag = LoongArchII::MO_TLSLE_HIGHEST; ++ HiOp = LoongArch::LU12I_W_ri; ++ break; ++ case LoongArch::LoadAddrTLS_IE: ++ // pcaddu12i + ld.d ++ LoFlag = LoongArchII::MO_TLSIE_LO; ++ HiFlag = LoongArchII::MO_TLSIE_HI; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::LD_D_rrii; ++ UseGot = true; ++ break; ++ case LoongArch::LoadAddrTLS_IE_RR: ++ // pcaddu12i + ori + lu32i.d + lu52i.d +ldx.d ++ LoFlag = LoongArchII::MO_TLSIE_RRLO; ++ HiFlag = LoongArchII::MO_TLSIE_RRHI; ++ HigherFlag = LoongArchII::MO_TLSIE_RRHIGHER; ++ HighestFlag = LoongArchII::MO_TLSIE_RRHIGHEST; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::ORI_rrii; ++ HigherOp = LoongArch::LU32I_D_rii; ++ HighestOp = LoongArch::LU52I_D_rrii; ++ LastOp = LoongArch::LDX_D_rrr; ++ UseGot = true; ++ break; ++ case LoongArch::LoadAddrTLS_LD: ++ case LoongArch::LoadAddrTLS_GD: ++ // pcaddu12i + addi.d ++ LoFlag = LoongArchII::MO_TLSGD_LO; ++ HiFlag = LoongArchII::MO_TLSGD_HI; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::ADDI_D_rrii; ++ UseGot = true; ++ break; ++ case LoongArch::LoadAddrTLS_LD_RR: ++ case LoongArch::LoadAddrTLS_GD_RR: ++ // pcaddu12i + ori + lu32i.d + lu52i.d + add.d ++ LoFlag = LoongArchII::MO_TLSGD_RRLO; ++ HiFlag = LoongArchII::MO_TLSGD_RRHI; ++ HigherFlag = LoongArchII::MO_TLSGD_RRHIGHER; ++ HighestFlag = LoongArchII::MO_TLSGD_RRHIGHEST; ++ HiOp = LoongArch::PCADDU12I_rii; ++ LoOp = LoongArch::ORI_rrii; ++ HigherOp = LoongArch::LU32I_D_rii; ++ HighestOp = LoongArch::LU52I_D_rrii; ++ LastOp = LoongArch::ADD_D_rrr; ++ UseGot = true; ++ break; ++ default: ++ break; ++ } ++ ++ MIB1 = BuildMI(BB, I, DL, TII->get(HiOp), DestReg); ++ ++ switch (Op) { ++ case LoongArch::LoadAddrLocal: ++ if (RM == Reloc::Static) { // for jit ++ // la.abs rd, symbol ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg).addReg(DestReg); ++ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), DestReg); ++ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), DestReg).addReg(DestReg); ++ if (MO.isJTI()) { ++ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); ++ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); ++ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); ++ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); ++ } else if (MO.isBlockAddress()) { ++ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); ++ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); ++ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); ++ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ MIB3.addDisp(MO, 0, HigherFlag); ++ MIB4.addDisp(MO, 0, HighestFlag); ++ } ++ break; ++ } ++ LLVM_FALLTHROUGH; ++ case LoongArch::LoadAddrGlobal: // la.global rd, symbol ++ case LoongArch::LoadAddrGlobal_Alias: // la rd, symbol ++ case LoongArch::LoadAddrTLS_IE: // la.tls.ie rd, symbol ++ case LoongArch::LoadAddrTLS_LD: // la.tls.ld rd, symbol ++ case LoongArch::LoadAddrTLS_GD: // la.tls.gd rd, symbol ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg) ++ .addReg(DestReg); ++ if (MO.isJTI()) { ++ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); ++ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); ++ } else if (MO.isBlockAddress()) { ++ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); ++ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ } ++ if (UseGot == true) { ++ MIB1.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ MIB2.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ } ++ break; ++ ++ case LoongArch::LoadAddrLocalRR: //la.local rd, rs, symbol ++ case LoongArch::LoadAddrGlobalRR: // la.global rd, rs, symbol ++ case LoongArch::LoadAddrTLS_IE_RR: // la.tls.ie rd, rs, symbol ++ case LoongArch::LoadAddrTLS_LD_RR: // la.tls.ld rd, rs, symbol ++ case LoongArch::LoadAddrTLS_GD_RR: // la.tls.gd rd, rs, symbol ++ TmpReg = MI.getOperand(MI.getNumOperands()-1).getReg(); ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), TmpReg) ++ .addReg(TmpReg); ++ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), TmpReg); ++ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), TmpReg) ++ .addReg(TmpReg); ++ MIB5 = BuildMI(BB, I, DL, TII->get(LastOp), DestReg) ++ .addReg(DestReg) ++ .addReg(TmpReg); ++ if (MO.isJTI()) { ++ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); ++ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); ++ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); ++ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); ++ } else if (MO.isBlockAddress()) { ++ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); ++ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); ++ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); ++ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ MIB3.addDisp(MO, 0, HigherFlag); ++ MIB4.addDisp(MO, 0, HighestFlag); ++ } ++ if (UseGot == true) { ++ MIB1.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ MIB2.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ MIB3.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ MIB4.addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); ++ } ++ break; ++ case LoongArch::LoadAddrTLS_LE: // la.tls.le rd, symbol ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg) ++ .addReg(DestReg); ++ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), DestReg); ++ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), DestReg) ++ .addReg(DestReg); ++ if (MO.isJTI()) { ++ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); ++ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); ++ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); ++ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); ++ } else if (MO.isBlockAddress()) { ++ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); ++ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); ++ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); ++ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ MIB3.addDisp(MO, 0, HigherFlag); ++ MIB4.addDisp(MO, 0, HighestFlag); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ MI.eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandPseudoTailCall( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I) { ++ ++ MachineInstr &MI = *I; ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ const MachineOperand &MO = MI.getOperand(0); ++ ++ unsigned NoFlag = LoongArchII::MO_NO_FLAG; ++ ++ MachineInstrBuilder MIB = ++ BuildMI(BB, I, DL, TII->get(LoongArch::PseudoTailReturn)); ++ ++ if (MO.isSymbol()) { ++ MIB.addExternalSymbol(MO.getSymbolName(), NoFlag); ++ } else { ++ MIB.addDisp(MO, 0, NoFlag); ++ } ++ ++ MI.eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandPseudoCall(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ MachineFunction *MF = BB.getParent(); ++ MachineInstr &MI = *I; ++ DebugLoc DL = MI.getDebugLoc(); ++ CodeModel::Model M = MF->getTarget().getCodeModel(); ++ Reloc::Model RM = MF->getTarget().getRelocationModel(); ++ ++ unsigned Ra = LoongArch::RA_64; ++ const MachineOperand &MO = MI.getOperand(0); ++ unsigned HiFlag, LoFlag, HigherFlag, HighestFlag, NoFlag; ++ ++ HiFlag = LoongArchII::MO_CALL_HI; ++ LoFlag = LoongArchII::MO_CALL_LO; ++ NoFlag = LoongArchII::MO_NO_FLAG; ++ ++ if (RM == Reloc::Static) { // for jit ++ MachineInstrBuilder MIB1, MIB2, MIB3, MIB4, MIB5; ++ ++ HiFlag = LoongArchII::MO_ABS_HI; ++ LoFlag = LoongArchII::MO_ABS_LO; ++ HigherFlag = LoongArchII::MO_ABS_HIGHER; ++ HighestFlag = LoongArchII::MO_ABS_HIGHEST; ++ // lu12i.w + ori + lu32i.d + lu52i.d + jirl ++ ++ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::LU12I_W), Ra); ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::ORI), Ra) ++ .addReg(Ra); ++ MIB3 = BuildMI(BB, I, DL, TII->get(LoongArch::LU32I_D), Ra); ++ MIB4 = BuildMI(BB, I, DL, TII->get(LoongArch::LU52I_D), Ra) ++ .addReg(Ra); ++ MIB5 = ++ BuildMI(BB, I, DL, TII->get(LoongArch::JIRL), Ra).addReg(Ra).addImm(0); ++ if (MO.isSymbol()) { ++ MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); ++ MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); ++ MIB3.addExternalSymbol(MO.getSymbolName(), HigherFlag); ++ MIB4.addExternalSymbol(MO.getSymbolName(), HighestFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ MIB3.addDisp(MO, 0, HigherFlag); ++ MIB4.addDisp(MO, 0, HighestFlag); ++ } ++ } else if (M == CodeModel::Large) { ++ // pcaddu18i + jirl ++ MachineInstrBuilder MIB1; ++ MachineInstrBuilder MIB2; ++ ++ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::PCADDU18I), Ra); ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::JIRL_CALL), Ra).addReg(Ra); ++ if (MO.isSymbol()) { ++ MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); ++ MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ } ++ } else { ++ // bl ++ MachineInstrBuilder MIB1; ++ MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::BL)); ++ if (MO.isSymbol()) { ++ MIB1.addExternalSymbol(MO.getSymbolName(), NoFlag); ++ } else { ++ MIB1.addDisp(MO, 0, NoFlag); ++ } ++ } ++ ++ MI.eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandPseudoTEQ(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ MachineInstr &MI = *I; ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned Divisor = MI.getOperand(0).getReg(); ++ unsigned BneOp = LoongArch::BNE; ++ unsigned Zero = LoongArch::ZERO_64; ++ ++ // beq $Divisor, $zero, 8 ++ BuildMI(BB, I, DL, TII->get(BneOp), Divisor) ++ .addReg(Zero) ++ .addImm(8); ++ // break 7 ++ BuildMI(BB, I, DL, TII->get(LoongArch::BREAK)) ++ .addImm(7);; ++ ++ MI.eraseFromParent(); ++ ++ return true; ++} ++bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MBBI, ++ MachineBasicBlock::iterator &NMBB) { ++ ++ bool Modified = false; ++ ++ switch (MBBI->getOpcode()) { ++ case LoongArch::PseudoTEQ: ++ return expandPseudoTEQ(MBB, MBBI, NMBB); ++ case LoongArch::PseudoCall: ++ return expandPseudoCall(MBB, MBBI, NMBB); ++ case LoongArch::PseudoTailCall: ++ return expandPseudoTailCall(MBB, MBBI); ++ case LoongArch::LoadAddrLocal: ++ case LoongArch::LoadAddrLocalRR: ++ case LoongArch::LoadAddrGlobal: ++ case LoongArch::LoadAddrGlobalRR: ++ case LoongArch::LoadAddrGlobal_Alias: ++ case LoongArch::LoadAddrTLS_LD: ++ case LoongArch::LoadAddrTLS_LD_RR: ++ case LoongArch::LoadAddrTLS_GD: ++ case LoongArch::LoadAddrTLS_GD_RR: ++ case LoongArch::LoadAddrTLS_IE: ++ case LoongArch::LoadAddrTLS_IE_RR: ++ case LoongArch::LoadAddrTLS_LE: ++ return expandLoadAddr(MBB, MBBI, NMBB); ++ case LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA: ++ case LoongArch::ATOMIC_CMP_SWAP_I64_POSTRA: ++ return expandAtomicCmpSwap(MBB, MBBI, NMBB); ++ case LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA: ++ case LoongArch::ATOMIC_CMP_SWAP_I16_POSTRA: ++ return expandAtomicCmpSwapSubword(MBB, MBBI, NMBB); ++ case LoongArch::ATOMIC_SWAP_I8_POSTRA: ++ case LoongArch::ATOMIC_SWAP_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_AND_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_AND_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_OR_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_OR_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA: ++ return expandAtomicBinOpSubword(MBB, MBBI, NMBB); ++ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: ++ return expandXINSERT_BOp(MBB, MBBI, NMBB); ++ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: ++ return expandINSERT_HOp(MBB, MBBI, NMBB); ++ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: ++ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: ++ return expandXINSERT_FWOp(MBB, MBBI, NMBB); ++ case LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_AND_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_OR_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA: ++ case LoongArch::ATOMIC_SWAP_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA: ++ return expandAtomicBinOp(MBB, MBBI, NMBB, 4); ++ case LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_AND_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_OR_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA: ++ case LoongArch::ATOMIC_SWAP_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA: ++ case LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA: ++ return expandAtomicBinOp(MBB, MBBI, NMBB, 8); ++ default: ++ return Modified; ++ } ++} ++ ++bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) { ++ bool Modified = false; ++ ++ MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); ++ while (MBBI != E) { ++ MachineBasicBlock::iterator NMBBI = std::next(MBBI); ++ Modified |= expandMI(MBB, MBBI, NMBBI); ++ MBBI = NMBBI; ++ } ++ ++ return Modified; ++} ++ ++bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) { ++ STI = &static_cast(MF.getSubtarget()); ++ TII = STI->getInstrInfo(); ++ ++ bool Modified = false; ++ for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; ++ ++MFI) ++ Modified |= expandMBB(*MFI); ++ ++ if (Modified) ++ MF.RenumberBlocks(); ++ ++ return Modified; ++} ++ ++/// createLoongArchExpandPseudoPass - returns an instance of the pseudo instruction ++/// expansion pass. ++FunctionPass *llvm::createLoongArchExpandPseudoPass() { ++ return new LoongArchExpandPseudo(); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td +deleted file mode 100644 +index 20448492a..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td ++++ /dev/null +@@ -1,229 +0,0 @@ +-//=-- LoongArchInstrInfoF.td - Single-Precision Float instr --*- tablegen -*-=// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +-// +-// This file describes the baisc single-precision floating-point instructions. +-// +-//===----------------------------------------------------------------------===// +- +-//===----------------------------------------------------------------------===// +-// LoongArch specific DAG Nodes. +-//===----------------------------------------------------------------------===// +- +-def SDT_LoongArchMOVGR2FR_W_LA64 +- : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>; +-def SDT_LoongArchMOVFR2GR_S_LA64 +- : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>; +-def SDT_LoongArchFTINT : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>; +- +-def loongarch_movgr2fr_w_la64 +- : SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>; +-def loongarch_movfr2gr_s_la64 +- : SDNode<"LoongArchISD::MOVFR2GR_S_LA64", SDT_LoongArchMOVFR2GR_S_LA64>; +-def loongarch_ftint : SDNode<"LoongArchISD::FTINT", SDT_LoongArchFTINT>; +- +-//===----------------------------------------------------------------------===// +-// Instructions +-//===----------------------------------------------------------------------===// +- +-let Predicates = [HasBasicF] in { +- +-// Arithmetic Operation Instructions +-def FADD_S : FP_ALU_3R<0b00000001000000001, "fadd.s", FPR32>; +-def FSUB_S : FP_ALU_3R<0b00000001000000101, "fsub.s", FPR32>; +-def FMUL_S : FP_ALU_3R<0b00000001000001001, "fmul.s", FPR32>; +-def FDIV_S : FP_ALU_3R<0b00000001000001101, "fdiv.s", FPR32>; +-def FMADD_S : FP_ALU_4R<0b000010000001, "fmadd.s", FPR32>; +-def FMSUB_S : FP_ALU_4R<0b000010000101, "fmsub.s", FPR32>; +-def FNMADD_S : FP_ALU_4R<0b000010001001, "fnmadd.s", FPR32>; +-def FNMSUB_S : FP_ALU_4R<0b000010001101, "fnmsub.s", FPR32>; +-def FMAX_S : FP_ALU_3R<0b00000001000010001, "fmax.s", FPR32>; +-def FMIN_S : FP_ALU_3R<0b00000001000010101, "fmin.s", FPR32>; +-def FMAXA_S : FP_ALU_3R<0b00000001000011001, "fmaxa.s", FPR32>; +-def FMINA_S : FP_ALU_3R<0b00000001000011101, "fmina.s", FPR32>; +-def FABS_S : FP_ALU_2R<0b0000000100010100000001, "fabs.s", FPR32>; +-def FNEG_S : FP_ALU_2R<0b0000000100010100000101, "fneg.s", FPR32>; +-def FSQRT_S : FP_ALU_2R<0b0000000100010100010001, "fsqrt.s", FPR32>; +-def FRECIP_S : FP_ALU_2R<0b0000000100010100010101, "frecip.s", FPR32>; +-def FRSQRT_S : FP_ALU_2R<0b0000000100010100011001, "frsqrt.s", FPR32>; +-def FSCALEB_S : FP_ALU_3R<0b00000001000100001, "fscaleb.s", FPR32>; +-def FLOGB_S : FP_ALU_2R<0b0000000100010100001001, "flogb.s", FPR32>; +-def FCOPYSIGN_S : FP_ALU_3R<0b00000001000100101, "fcopysign.s", FPR32>; +-def FCLASS_S : FP_ALU_2R<0b0000000100010100001101, "fclass.s", FPR32>; +- +- +-// Comparison Instructions +-def FCMP_CAF_S : FP_CMP; +-def FCMP_CUN_S : FP_CMP; +-def FCMP_CEQ_S : FP_CMP; +-def FCMP_CUEQ_S : FP_CMP; +-def FCMP_CLT_S : FP_CMP; +-def FCMP_CULT_S : FP_CMP; +-def FCMP_CLE_S : FP_CMP; +-def FCMP_CULE_S : FP_CMP; +-def FCMP_CNE_S : FP_CMP; +-def FCMP_COR_S : FP_CMP; +-def FCMP_CUNE_S : FP_CMP; +-def FCMP_SAF_S : FP_CMP; +-def FCMP_SUN_S : FP_CMP; +-def FCMP_SEQ_S : FP_CMP; +-def FCMP_SUEQ_S : FP_CMP; +-def FCMP_SLT_S : FP_CMP; +-def FCMP_SULT_S : FP_CMP; +-def FCMP_SLE_S : FP_CMP; +-def FCMP_SULE_S : FP_CMP; +-def FCMP_SNE_S : FP_CMP; +-def FCMP_SOR_S : FP_CMP; +-def FCMP_SUNE_S : FP_CMP; +- +-// Conversion Instructions +-def FFINT_S_W : FP_CONV<0b0000000100011101000100, "ffint.s.w", FPR32, FPR32>; +-def FTINT_W_S : FP_CONV<0b0000000100011011000001, "ftint.w.s", FPR32, FPR32>; +-def FTINTRM_W_S : FP_CONV<0b0000000100011010000001, "ftintrm.w.s", FPR32, +- FPR32>; +-def FTINTRP_W_S : FP_CONV<0b0000000100011010010001, "ftintrp.w.s", FPR32, +- FPR32>; +-def FTINTRZ_W_S : FP_CONV<0b0000000100011010100001, "ftintrz.w.s", FPR32, +- FPR32>; +-def FTINTRNE_W_S : FP_CONV<0b0000000100011010110001, "ftintrne.w.s", FPR32, +- FPR32>; +-def FRINT_S : FP_CONV<0b0000000100011110010001, "frint.s", FPR32, FPR32>; +- +-// Move Instructions +-def FSEL_S : FP_SEL<0b00001101000000, "fsel", FPR32>; +-def FMOV_S : FP_MOV<0b0000000100010100100101, "fmov.s", FPR32, FPR32>; +-def MOVGR2FR_W : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR32, GPR>; +-def MOVFR2GR_S : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR32>; +-def MOVGR2FCSR : FP_MOV<0b0000000100010100110000, "movgr2fcsr", FCSR, GPR>; +-def MOVFCSR2GR : FP_MOV<0b0000000100010100110010, "movfcsr2gr", GPR, FCSR>; +-def MOVFR2CF_S : FP_MOV<0b0000000100010100110100, "movfr2cf", CFR, FPR32>; +-def MOVCF2FR_S : FP_MOV<0b0000000100010100110101, "movcf2fr", FPR32, CFR>; +-def MOVGR2CF : FP_MOV<0b0000000100010100110110, "movgr2cf", CFR, GPR>; +-def MOVCF2GR : FP_MOV<0b0000000100010100110111, "movcf2gr", GPR, CFR>; +- +-// Branch Instructions +-def BCEQZ : FP_BRANCH<0b01001000, "bceqz">; +-def BCNEZ : FP_BRANCH<0b01001001, "bcnez">; +- +-// Common Memory Access Instructions +-def FLD_S : FP_LOAD_2RI12<0b0010101100, "fld.s", FPR32>; +-def FST_S : FP_STORE_2RI12<0b0010101101, "fst.s", FPR32>; +-def FLDX_S : FP_LOAD_3R<0b00111000001100000, "fldx.s", FPR32>; +-def FSTX_S : FP_STORE_3R<0b00111000001110000, "fstx.s", FPR32>; +- +-// Bound Check Memory Access Instructions +-def FLDGT_S : FP_LOAD_3R<0b00111000011101000, "fldgt.s", FPR32>; +-def FLDLE_S : FP_LOAD_3R<0b00111000011101010, "fldle.s", FPR32>; +-def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>; +-def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>; +- +-} // Predicates = [HasBasicF] +- +-//===----------------------------------------------------------------------===// +-// Pseudo-instructions and codegen patterns +-//===----------------------------------------------------------------------===// +- +-/// Generic pattern classes +- +-class PatFpr +- : Pat<(OpNode RegTy:$fj), (Inst $fj)>; +-class PatFprFpr +- : Pat<(OpNode RegTy:$fj, RegTy:$fk), (Inst $fj, $fk)>; +- +-let Predicates = [HasBasicF] in { +- +-/// Float arithmetic operations +- +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFpr; +- +-/// Setcc +- +-// Match non-signaling comparison +- +-// TODO: change setcc to any_fsetcc after call is supported because +-// we need to call llvm.experimental.constrained.fcmp.f32 in testcase. +-// See RISCV float-fcmp-strict.ll for reference. +-class PatFPSetcc +- : Pat<(setcc RegTy:$fj, RegTy:$fk, cc), +- (MOVCF2GR (CmpInst RegTy:$fj, RegTy:$fk))>; +-// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE. +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +- +-// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_S instructions. +- +-/// Select +- +-def : Pat<(select GPR:$cc, FPR32:$fk, FPR32:$fj), +- (FSEL_S FPR32:$fj, FPR32:$fk, (MOVGR2CF GPR:$cc))>; +- +-/// Selectcc +- +-class PatFPSelectcc +- : Pat<(select (GRLenVT (setcc RegTy:$a, RegTy:$b, cc)), RegTy:$t, RegTy:$f), +- (SelInst RegTy:$f, RegTy:$t, (CmpInst RegTy:$a, RegTy:$b))>; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +- +-/// Loads +- +-defm : LdPat; +- +-/// Stores +- +-defm : StPat; +- +-/// Floating point constants +- +-def : Pat<(f32 fpimm0), (MOVGR2FR_W R0)>; +-def : Pat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W R0))>; +-def : Pat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1)))>; +- +-// FP Conversion +-def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>; +-} // Predicates = [HasBasicF] +- +-let Predicates = [HasBasicF, IsLA64] in { +-// GPR -> FPR +-def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>; +-// FPR -> GPR +-def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src), +- (MOVFR2GR_S FPR32:$src)>; +-// int -> f32 +-def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>; +-} // Predicates = [HasBasicF, IsLA64] +- +-let Predicates = [HasBasicF, IsLA32] in { +-// GPR -> FPR +-def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>; +-// FPR -> GPR +-def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>; +-// int -> f32 +-def : Pat<(f32 (sint_to_fp (i32 GPR:$src))), (FFINT_S_W (MOVGR2FR_W GPR:$src))>; +-} // Predicates = [HasBasicF, IsLA64] +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td +deleted file mode 100644 +index bb50cec9f..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td ++++ /dev/null +@@ -1,242 +0,0 @@ +-//=-- LoongArchInstrInfoD.td - Double-Precision Float instr -*- tablegen -*-==// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +-// +-// This file describes the basic double-precision floating-point instructions. +-// +-//===----------------------------------------------------------------------===// +- +-//===----------------------------------------------------------------------===// +-// Instructions +-//===----------------------------------------------------------------------===// +- +-let Predicates = [HasBasicD] in { +- +-// Arithmetic Operation Instructions +-def FADD_D : FP_ALU_3R<0b00000001000000010, "fadd.d", FPR64>; +-def FSUB_D : FP_ALU_3R<0b00000001000000110, "fsub.d", FPR64>; +-def FMUL_D : FP_ALU_3R<0b00000001000001010, "fmul.d", FPR64>; +-def FDIV_D : FP_ALU_3R<0b00000001000001110, "fdiv.d", FPR64>; +-def FMADD_D : FP_ALU_4R<0b000010000010, "fmadd.d", FPR64>; +-def FMSUB_D : FP_ALU_4R<0b000010000110, "fmsub.d", FPR64>; +-def FNMADD_D : FP_ALU_4R<0b000010001010, "fnmadd.d", FPR64>; +-def FNMSUB_D : FP_ALU_4R<0b000010001110, "fnmsub.d", FPR64>; +-def FMAX_D : FP_ALU_3R<0b00000001000010010, "fmax.d", FPR64>; +-def FMIN_D : FP_ALU_3R<0b00000001000010110, "fmin.d", FPR64>; +-def FMAXA_D : FP_ALU_3R<0b00000001000011010, "fmaxa.d", FPR64>; +-def FMINA_D : FP_ALU_3R<0b00000001000011110, "fmina.d", FPR64>; +-def FABS_D : FP_ALU_2R<0b0000000100010100000010, "fabs.d", FPR64>; +-def FNEG_D : FP_ALU_2R<0b0000000100010100000110, "fneg.d", FPR64>; +-def FSQRT_D : FP_ALU_2R<0b0000000100010100010010, "fsqrt.d", FPR64>; +-def FRECIP_D : FP_ALU_2R<0b0000000100010100010110, "frecip.d", FPR64>; +-def FRSQRT_D : FP_ALU_2R<0b0000000100010100011010, "frsqrt.d", FPR64>; +-def FSCALEB_D : FP_ALU_3R<0b00000001000100010, "fscaleb.d", FPR64>; +-def FLOGB_D : FP_ALU_2R<0b0000000100010100001010, "flogb.d", FPR64>; +-def FCOPYSIGN_D : FP_ALU_3R<0b00000001000100110, "fcopysign.d", FPR64>; +-def FCLASS_D : FP_ALU_2R<0b0000000100010100001110, "fclass.d", FPR64>; +- +-// Comparison Instructions +-def FCMP_CAF_D : FP_CMP; +-def FCMP_CUN_D : FP_CMP; +-def FCMP_CEQ_D : FP_CMP; +-def FCMP_CUEQ_D : FP_CMP; +-def FCMP_CLT_D : FP_CMP; +-def FCMP_CULT_D : FP_CMP; +-def FCMP_CLE_D : FP_CMP; +-def FCMP_CULE_D : FP_CMP; +-def FCMP_CNE_D : FP_CMP; +-def FCMP_COR_D : FP_CMP; +-def FCMP_CUNE_D : FP_CMP; +-def FCMP_SAF_D : FP_CMP; +-def FCMP_SUN_D : FP_CMP; +-def FCMP_SEQ_D : FP_CMP; +-def FCMP_SUEQ_D : FP_CMP; +-def FCMP_SLT_D : FP_CMP; +-def FCMP_SULT_D : FP_CMP; +-def FCMP_SLE_D : FP_CMP; +-def FCMP_SULE_D : FP_CMP; +-def FCMP_SNE_D : FP_CMP; +-def FCMP_SOR_D : FP_CMP; +-def FCMP_SUNE_D : FP_CMP; +- +-// Conversion Instructions +-def FFINT_S_L : FP_CONV<0b0000000100011101000110, "ffint.s.l", FPR32, FPR64>; +-def FTINT_L_S : FP_CONV<0b0000000100011011001001, "ftint.l.s", FPR64, FPR32>; +-def FTINTRM_L_S : FP_CONV<0b0000000100011010001001, "ftintrm.l.s", FPR64, +- FPR32>; +-def FTINTRP_L_S : FP_CONV<0b0000000100011010011001, "ftintrp.l.s", FPR64, +- FPR32>; +-def FTINTRZ_L_S : FP_CONV<0b0000000100011010101001, "ftintrz.l.s", FPR64, +- FPR32>; +-def FTINTRNE_L_S : FP_CONV<0b0000000100011010111001, "ftintrne.l.s", FPR64, +- FPR32>; +-def FCVT_S_D : FP_CONV<0b0000000100011001000110, "fcvt.s.d", FPR32, FPR64>; +-def FCVT_D_S : FP_CONV<0b0000000100011001001001, "fcvt.d.s", FPR64, FPR32>; +-def FFINT_D_W : FP_CONV<0b0000000100011101001000, "ffint.d.w", FPR64, FPR32>; +-def FFINT_D_L : FP_CONV<0b0000000100011101001010, "ffint.d.l", FPR64, FPR64>; +-def FTINT_W_D : FP_CONV<0b0000000100011011000010, "ftint.w.d", FPR32, FPR64>; +-def FTINT_L_D : FP_CONV<0b0000000100011011001010, "ftint.l.d", FPR64, FPR64>; +-def FTINTRM_W_D : FP_CONV<0b0000000100011010000010, "ftintrm.w.d", FPR32, +- FPR64>; +-def FTINTRM_L_D : FP_CONV<0b0000000100011010001010, "ftintrm.l.d", FPR64, +- FPR64>; +-def FTINTRP_W_D : FP_CONV<0b0000000100011010010010, "ftintrp.w.d", FPR32, +- FPR64>; +-def FTINTRP_L_D : FP_CONV<0b0000000100011010011010, "ftintrp.l.d", FPR64, +- FPR64>; +-def FTINTRZ_W_D : FP_CONV<0b0000000100011010100010, "ftintrz.w.d", FPR32, +- FPR64>; +-def FTINTRZ_L_D : FP_CONV<0b0000000100011010101010, "ftintrz.l.d", FPR64, +- FPR64>; +-def FTINTRNE_W_D : FP_CONV<0b0000000100011010110010, "ftintrne.w.d", FPR32, +- FPR64>; +-def FTINTRNE_L_D : FP_CONV<0b0000000100011010111010, "ftintrne.l.d", FPR64, +- FPR64>; +-def FRINT_D : FP_CONV<0b0000000100011110010010, "frint.d", FPR64, FPR64>; +- +-// Move Instructions +-def FMOV_D : FP_MOV<0b0000000100010100100110, "fmov.d", FPR64, FPR64>; +-def MOVFRH2GR_S : FP_MOV<0b0000000100010100101111, "movfrh2gr.s", GPR, FPR64>; +-let isCodeGenOnly = 1 in { +-def MOVFR2GR_S_64 : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR64>; +-def FSEL_D : FP_SEL<0b00001101000000, "fsel", FPR64>; +-} // isCodeGenOnly = 1 +-let Constraints = "$dst = $out" in { +-def MOVGR2FRH_W : FPFmtMOV<0b0000000100010100101011, (outs FPR64:$out), +- (ins FPR64:$dst, GPR:$src), "movgr2frh.w", +- "$dst, $src">; +-} // Constraints = "$dst = $out" +- +-// Common Memory Access Instructions +-def FLD_D : FP_LOAD_2RI12<0b0010101110, "fld.d", FPR64>; +-def FST_D : FP_STORE_2RI12<0b0010101111, "fst.d", FPR64>; +-def FLDX_D : FP_LOAD_3R<0b00111000001101000, "fldx.d", FPR64>; +-def FSTX_D : FP_STORE_3R<0b00111000001111000, "fstx.d", FPR64>; +- +-// Bound Check Memory Access Instructions +-def FLDGT_D : FP_LOAD_3R<0b00111000011101001, "fldgt.d", FPR64>; +-def FLDLE_D : FP_LOAD_3R<0b00111000011101011, "fldle.d", FPR64>; +-def FSTGT_D : FP_STORE_3R<0b00111000011101101, "fstgt.d", FPR64>; +-def FSTLE_D : FP_STORE_3R<0b00111000011101111, "fstle.d", FPR64>; +- +-} // Predicates = [HasBasicD] +- +-// Instructions only available on LA64 +-let Predicates = [HasBasicD, IsLA64] in { +-def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>; +-def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>; +-} // Predicates = [HasBasicD, IsLA64] +- +-// Instructions only available on LA32 +-let Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 in { +-def MOVGR2FR_W_64 : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR64, GPR>; +-} // Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 +- +-//===----------------------------------------------------------------------===// +-// Pseudo-instructions and codegen patterns +-//===----------------------------------------------------------------------===// +- +-let Predicates = [HasBasicD] in { +- +-/// Float arithmetic operations +- +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFprFpr; +-def : PatFpr; +- +-/// Setcc +- +-// Match non-signaling comparison +- +-// TODO: Change setcc to any_fsetcc after call is supported because +-// we need to call llvm.experimental.constrained.fcmp.f64 in testcase. +-// See RISCV float-fcmp-strict.ll for reference. +- +-// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE. +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +-def : PatFPSetcc; +- +-// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_D instructions. +- +-/// Select +- +-def : Pat<(select GPR:$cc, FPR64:$fk, FPR64:$fj), +- (FSEL_D FPR64:$fj, FPR64:$fk, (MOVGR2CF GPR:$cc))>; +- +-/// Selectcc +- +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +-def : PatFPSelectcc; +- +-/// Loads +- +-defm : LdPat; +- +-/// Stores +- +-defm : StPat; +- +-/// FP conversion operations +- +-def : Pat<(loongarch_ftint FPR64:$src), (FTINTRZ_W_D FPR64:$src)>; +-def : Pat<(f64 (loongarch_ftint FPR64:$src)), (FTINTRZ_L_D FPR64:$src)>; +-def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_L_S FPR32:$src)>; +- +-// f64 -> f32 +-def : Pat<(f32 (fpround FPR64:$src)), (FCVT_S_D FPR64:$src)>; +-// f32 -> f64 +-def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>; +-} // Predicates = [HasBasicD] +- +-/// Floating point constants +- +-let Predicates = [HasBasicD, IsLA64] in { +-def : Pat<(f64 fpimm0), (MOVGR2FR_D R0)>; +-def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FR_D R0))>; +-def : Pat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D R0, 1)))>; +- +-// Convert int to FP +-def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))), +- (FFINT_D_W (MOVGR2FR_W GPR:$src))>; +-def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>; +- +-def : Pat<(f64 (uint_to_fp (i64 (zexti32 (i64 GPR:$src))))), +- (FFINT_D_W (MOVGR2FR_W GPR:$src))>; +- +-def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>; +- +-// Convert FP to int +-def : Pat<(bitconvert FPR64:$src), (MOVFR2GR_D FPR64:$src)>; +-} // Predicates = [HasBasicD, IsLA64] +- +-let Predicates = [HasBasicD, IsLA32] in { +-def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>; +-def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>; +-def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>; +- +-// Convert int to FP +-def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>; +-} // Predicates = [HasBasicD, IsLA32] +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td +deleted file mode 100644 +index d2ba1fdff..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td ++++ /dev/null +@@ -1,241 +0,0 @@ +-//==- LoongArchInstrFormatsF.td - LoongArch FP Instr Formats -*- tablegen -*-=// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +- +-//===----------------------------------------------------------------------===// +-// Describe LoongArch floating-point instructions format +-// +-// opcode - operation code. +-// fd - destination register operand. +-// {c/f}{j/k/a} - source register operand. +-// immN - immediate data operand. +-// +-//===----------------------------------------------------------------------===// +- +-// 2R-type +-// +-class FPFmt2R op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> fj; +- bits<5> fd; +- +- let Inst{31-10} = op; +- let Inst{9-5} = fj; +- let Inst{4-0} = fd; +-} +- +-// 3R-type +-// +-class FPFmt3R op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> fk; +- bits<5> fj; +- bits<5> fd; +- +- let Inst{31-15} = op; +- let Inst{14-10} = fk; +- let Inst{9-5} = fj; +- let Inst{4-0} = fd; +-} +- +-// 4R-type +-// +-class FPFmt4R op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> fa; +- bits<5> fk; +- bits<5> fj; +- bits<5> fd; +- +- let Inst{31-20} = op; +- let Inst{19-15} = fa; +- let Inst{14-10} = fk; +- let Inst{9-5} = fj; +- let Inst{4-0} = fd; +-} +- +-// 2RI12-type +-// +-class FPFmt2RI12 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<12> imm12; +- bits<5> rj; +- bits<5> fd; +- +- let Inst{31-22} = op; +- let Inst{21-10} = imm12; +- let Inst{9-5} = rj; +- let Inst{4-0} = fd; +-} +- +-// FmtFCMP +-// +-class FPFmtFCMP op, bits<5> cond, dag outs, dag ins, string opcstr, +- string opnstr, list pattern = []> +- : LAInst { +- bits<5> fk; +- bits<5> fj; +- bits<3> cd; +- +- let Inst{31-20} = op; +- let Inst{19-15} = cond; +- let Inst{14-10} = fk; +- let Inst{9-5} = fj; +- let Inst{4-3} = 0b00; +- let Inst{2-0} = cd; +-} +- +-// FPFmtBR +-// +-class FPFmtBR opcode, dag outs, dag ins, string opcstr, +- string opnstr, list pattern = []> +- : LAInst { +- bits<21> imm21; +- bits<3> cj; +- +- let Inst{31-26} = opcode{7-2}; +- let Inst{25-10} = imm21{15-0}; +- let Inst{9-8} = opcode{1-0}; +- let Inst{7-5} = cj; +- let Inst{4-0} = imm21{20-16}; +-} +- +-// FmtFSEL +-// +-class FPFmtFSEL op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<3> ca; +- bits<5> fk; +- bits<5> fj; +- bits<5> fd; +- +- let Inst{31-18} = op; +- let Inst{17-15} = ca; +- let Inst{14-10} = fk; +- let Inst{9-5} = fj; +- let Inst{4-0} = fd; +-} +- +-// FPFmtMOV +-// +-class FPFmtMOV op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> src; +- bits<5> dst; +- +- let Inst{31-10} = op; +- let Inst{9-5} = src; +- let Inst{4-0} = dst; +-} +- +-// FPFmtMEM +-// +-class FPFmtMEM op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> rk; +- bits<5> rj; +- bits<5> fd; +- +- let Inst{31-15} = op; +- let Inst{14-10} = rk; +- let Inst{9-5} = rj; +- let Inst{4-0} = fd; +-} +- +-//===----------------------------------------------------------------------===// +-// Instruction class templates +-//===----------------------------------------------------------------------===// +- +-class FP_ALU_2R op, string opstr, RegisterClass rc> +- : FPFmt2R; +- +-class FP_ALU_3R op, string opstr, RegisterClass rc> +- : FPFmt3R; +- +-class FP_ALU_4R op, string opstr, RegisterClass rc> +- : FPFmt4R; +- +-class FPCMPOpc value> { +- bits<12> val = value; +-} +- +-class FPCMPCond value> { +- bits<5> val = value; +-} +- +-class FP_CMP +- : FPFmtFCMP; +- +-class FP_CONV op, string opstr, RegisterClass rcd, RegisterClass rcs> +- : FPFmt2R; +- +-class FP_MOV op, string opstr, RegisterClass rcd, RegisterClass rcs> +- : FPFmtMOV; +- +-class FP_SEL op, string opstr, RegisterClass rc> +- : FPFmtFSEL; +- +-class FP_BRANCH opcode, string opstr> +- : FPFmtBR { +- let isBranch = 1; +- let isTerminator = 1; +-} +- +-let mayLoad = 1 in { +-class FP_LOAD_3R op, string opstr, RegisterClass rc> +- : FPFmtMEM; +-class FP_LOAD_2RI12 op, string opstr, RegisterClass rc> +- : FPFmt2RI12; +-} // mayLoad = 1 +- +-let mayStore = 1 in { +-class FP_STORE_3R op, string opstr, RegisterClass rc> +- : FPFmtMEM; +-class FP_STORE_2RI12 op, string opstr, RegisterClass rc> +- : FPFmt2RI12; +-} // mayStore = 1 +- +-def FPCMP_OPC_S : FPCMPOpc<0b000011000001>; +-def FPCMP_OPC_D : FPCMPOpc<0b000011000010>; +- +-def FPCMP_COND_CAF : FPCMPCond<0x0>; +-def FPCMP_COND_CUN : FPCMPCond<0x8>; +-def FPCMP_COND_CEQ : FPCMPCond<0x4>; +-def FPCMP_COND_CUEQ : FPCMPCond<0xC>; +-def FPCMP_COND_CLT : FPCMPCond<0x2>; +-def FPCMP_COND_CULT : FPCMPCond<0xA>; +-def FPCMP_COND_CLE : FPCMPCond<0x6>; +-def FPCMP_COND_CULE : FPCMPCond<0xE>; +-def FPCMP_COND_CNE : FPCMPCond<0x10>; +-def FPCMP_COND_COR : FPCMPCond<0x14>; +-def FPCMP_COND_CUNE : FPCMPCond<0x18>; +-def FPCMP_COND_SAF : FPCMPCond<0x1>; +-def FPCMP_COND_SUN : FPCMPCond<0x9>; +-def FPCMP_COND_SEQ : FPCMPCond<0x5>; +-def FPCMP_COND_SUEQ : FPCMPCond<0xD>; +-def FPCMP_COND_SLT : FPCMPCond<0x3>; +-def FPCMP_COND_SULT : FPCMPCond<0xB>; +-def FPCMP_COND_SLE : FPCMPCond<0x7>; +-def FPCMP_COND_SULE : FPCMPCond<0xF>; +-def FPCMP_COND_SNE : FPCMPCond<0x11>; +-def FPCMP_COND_SOR : FPCMPCond<0x15>; +-def FPCMP_COND_SUNE : FPCMPCond<0x19>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp +index 0d9ec9e2e..7c4c141e1 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information -*- C++ -*-==// ++//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information --------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,192 +11,365 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchFrameLowering.h" +-#include "LoongArchMachineFunctionInfo.h" +-#include "LoongArchSubtarget.h" + #include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "LoongArchInstrInfo.h" ++#include "LoongArchMachineFunction.h" ++#include "LoongArchTargetMachine.h" ++#include "LoongArchRegisterInfo.h" ++#include "LoongArchSubtarget.h" ++#include "llvm/ADT/BitVector.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstr.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineModuleInfo.h" ++#include "llvm/CodeGen/MachineOperand.h" + #include "llvm/CodeGen/MachineRegisterInfo.h" + #include "llvm/CodeGen/RegisterScavenging.h" +-#include "llvm/IR/DiagnosticInfo.h" ++#include "llvm/CodeGen/TargetInstrInfo.h" ++#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++#include "llvm/IR/DataLayout.h" ++#include "llvm/IR/DebugLoc.h" ++#include "llvm/IR/Function.h" + #include "llvm/MC/MCDwarf.h" ++#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/MC/MachineLocation.h" ++#include "llvm/Support/CodeGen.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Target/TargetOptions.h" ++#include ++#include ++#include ++#include + + using namespace llvm; + +-#define DEBUG_TYPE "loongarch-frame-lowering" +- +-// Return true if the specified function should have a dedicated frame +-// pointer register. This is true if frame pointer elimination is +-// disabled, if it needs dynamic stack realignment, if the function has +-// variable sized allocas, or if the frame address is taken. +-bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const { +- const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); +- +- const MachineFrameInfo &MFI = MF.getFrameInfo(); +- return MF.getTarget().Options.DisableFramePointerElim(MF) || +- RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || +- MFI.isFrameAddressTaken(); +-} +- +-bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const { ++// We would like to split the SP adjustment to reduce prologue/epilogue ++// as following instructions. In this way, the offset of the callee saved ++// register could fit in a single store. ++uint64_t ++LoongArchFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF, ++ bool IsPrologue) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); +- const TargetRegisterInfo *TRI = STI.getRegisterInfo(); +- +- return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF); +-} +- +-void LoongArchFrameLowering::adjustReg(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator MBBI, +- const DebugLoc &DL, Register DestReg, +- Register SrcReg, int64_t Val, +- MachineInstr::MIFlag Flag) const { +- const LoongArchInstrInfo *TII = STI.getInstrInfo(); +- bool IsLA64 = STI.is64Bit(); +- +- if (DestReg == SrcReg && Val == 0) +- return; ++ const std::vector &CSI = MFI.getCalleeSavedInfo(); ++ uint64_t StackSize = MFI.getStackSize(); + +- if (isInt<12>(Val)) { +- // addi.w/d $DstReg, $SrcReg, Val +- BuildMI(MBB, MBBI, DL, +- TII->get(IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W), DestReg) +- .addReg(SrcReg) +- .addImm(Val) +- .setMIFlag(Flag); +- return; ++ // Return the FirstSPAdjustAmount if the StackSize can not fit in signed ++ // 12-bit and there exists a callee saved register need to be pushed. ++ if (!isInt<12>(StackSize)) { ++ // FirstSPAdjustAmount is choosed as (2048 - StackAlign) ++ // because 2048 will cause sp = sp + 2048 in epilogue split into ++ // multi-instructions. The offset smaller than 2048 can fit in signle ++ // load/store instruction and we have to stick with the stack alignment. ++ return CSI.size() > 0 ? 2048 - getStackAlign().value() ++ : (IsPrologue ? 2048 : 0); + } +- +- report_fatal_error("adjustReg cannot yet handle adjustments >12 bits"); ++ return 0; + } + +-// Determine the size of the frame and maximum call frame size. +-void LoongArchFrameLowering::determineFrameLayout(MachineFunction &MF) const { +- MachineFrameInfo &MFI = MF.getFrameInfo(); +- +- // Get the number of bytes to allocate from the FrameInfo. +- uint64_t FrameSize = MFI.getStackSize(); +- +- // Make sure the frame is aligned. +- FrameSize = alignTo(FrameSize, getStackAlign()); +- +- // Update frame info. +- MFI.setStackSize(FrameSize); +-} ++//===----------------------------------------------------------------------===// ++// ++// Stack Frame Processing methods ++// +----------------------------+ ++// ++// The stack is allocated decrementing the stack pointer on ++// the first instruction of a function prologue. Once decremented, ++// all stack references are done thought a positive offset ++// from the stack/frame pointer, so the stack is considering ++// to grow up! Otherwise terrible hacks would have to be made ++// to get this stack ABI compliant :) ++// ++// The stack frame required by the ABI (after call): ++// Offset ++// ++// 0 ---------- ++// 4 Args to pass ++// . Alloca allocations ++// . Local Area ++// . CPU "Callee Saved" Registers ++// . saved FP ++// . saved RA ++// . FPU "Callee Saved" Registers ++// StackSize ----------- ++// ++// Offset - offset from sp after stack allocation on function prologue ++// ++// The sp is the stack pointer subtracted/added from the stack size ++// at the Prologue/Epilogue ++// ++// References to the previous stack (to obtain arguments) are done ++// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1)) ++// ++// Examples: ++// - reference to the actual stack frame ++// for any local area var there is smt like : FI >= 0, StackOffset: 4 ++// st.w REGX, SP, 4 ++// ++// - reference to previous stack frame ++// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16. ++// The emitted instruction will be something like: ++// ld.w REGX, SP, 16+StackSize ++// ++// Since the total stack size is unknown on LowerFormalArguments, all ++// stack references (ObjectOffset) created to reference the function ++// arguments, are negative numbers. This way, on eliminateFrameIndex it's ++// possible to detect those references and the offsets are adjusted to ++// their real location. ++// ++//===----------------------------------------------------------------------===// ++// ++LoongArchFrameLowering::LoongArchFrameLowering(const LoongArchSubtarget &STI) ++ : TargetFrameLowering(StackGrowsDown, STI.getStackAlignment(), 0, ++ STI.getStackAlignment()), STI(STI) {} + + void LoongArchFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); +- const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); +- const LoongArchInstrInfo *TII = STI.getInstrInfo(); +- MachineBasicBlock::iterator MBBI = MBB.begin(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); + +- Register SPReg = LoongArch::R3; +- Register FPReg = LoongArch::R22; +- +- // Debug location must be unknown since the first debug location is used +- // to determine the end of the prologue. +- DebugLoc DL; +- +- // Determine the correct frame layout +- determineFrameLayout(MF); ++ const LoongArchInstrInfo &TII = ++ *static_cast(STI.getInstrInfo()); ++ const LoongArchRegisterInfo &RegInfo = ++ *static_cast(STI.getRegisterInfo()); ++ MachineBasicBlock::iterator MBBI = MBB.begin(); ++ DebugLoc dl; ++ LoongArchABIInfo ABI = STI.getABI(); ++ unsigned SP = ABI.GetStackPtr(); ++ unsigned FP = ABI.GetFramePtr(); ++ unsigned ZERO = ABI.GetNullPtr(); ++ unsigned MOVE = ABI.GetGPRMoveOp(); ++ unsigned ADDI = ABI.GetPtrAddiOp(); ++ unsigned AND = ABI.IsLP64() ? LoongArch::AND : LoongArch::AND32; ++ unsigned SLLI = ABI.IsLP64() ? LoongArch::SLLI_D : LoongArch::SLLI_W; ++ ++ const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? ++ &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; + + // First, compute final stack size. + uint64_t StackSize = MFI.getStackSize(); ++ uint64_t RealStackSize = StackSize; + +- // Early exit if there is no need to allocate space in the stack. ++ // No need to allocate space on the stack. + if (StackSize == 0 && !MFI.adjustsStack()) + return; + ++ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF, true); ++ uint64_t SecondSPAdjustAmount = RealStackSize - FirstSPAdjustAmount; ++ // Split the SP adjustment to reduce the offsets of callee saved spill. ++ if (FirstSPAdjustAmount) ++ StackSize = FirstSPAdjustAmount; ++ + // Adjust stack. +- adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); +- // Emit ".cfi_def_cfa_offset StackSize". +- unsigned CFIIndex = +- MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); +- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) +- .addCFIIndex(CFIIndex) +- .setMIFlag(MachineInstr::FrameSetup); ++ TII.adjustReg(SP, SP, -StackSize, MBB, MBBI, MachineInstr::FrameSetup); ++ if (FirstSPAdjustAmount != 2048 || SecondSPAdjustAmount == 0) { ++ // Emit ".cfi_def_cfa_offset StackSize". ++ unsigned CFIIndex = ++ MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); ++ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) ++ .addCFIIndex(CFIIndex); ++ } + +- const auto &CSI = MFI.getCalleeSavedInfo(); ++ MachineModuleInfo &MMI = MF.getMMI(); ++ const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); ++ ++ const std::vector &CSI = MFI.getCalleeSavedInfo(); ++ ++ if (!CSI.empty()) { ++ // Find the instruction past the last instruction that saves a callee-saved ++ // register to the stack. ++ for (unsigned i = 0; i < CSI.size(); ++i) ++ ++MBBI; ++ ++ // Iterate over list of callee-saved registers and emit .cfi_offset ++ // directives. ++ for (std::vector::const_iterator I = CSI.begin(), ++ E = CSI.end(); I != E; ++I) { ++ int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); ++ unsigned Reg = I->getReg(); ++ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( ++ nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); ++ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) ++ .addCFIIndex(CFIIndex); ++ } ++ } + +- // The frame pointer is callee-saved, and code has been generated for us to +- // save it to the stack. We need to skip over the storing of callee-saved +- // registers as the frame pointer must be modified after it has been saved +- // to the stack, not before. +- std::advance(MBBI, CSI.size()); +- +- // Iterate over list of callee-saved registers and emit .cfi_offset +- // directives. +- for (const auto &Entry : CSI) { +- int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx()); +- unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( +- nullptr, RI->getDwarfRegNum(Entry.getReg(), true), Offset)); +- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) +- .addCFIIndex(CFIIndex) +- .setMIFlag(MachineInstr::FrameSetup); ++ if (LoongArchFI->callsEhReturn()) { ++ // Insert instructions that spill eh data registers. ++ for (int I = 0; I < 4; ++I) { ++ if (!MBB.isLiveIn(ABI.GetEhDataReg(I))) ++ MBB.addLiveIn(ABI.GetEhDataReg(I)); ++ TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false, ++ LoongArchFI->getEhDataRegFI(I), RC, &RegInfo); ++ } ++ ++ // Emit .cfi_offset directives for eh data registers. ++ for (int I = 0; I < 4; ++I) { ++ int64_t Offset = MFI.getObjectOffset(LoongArchFI->getEhDataRegFI(I)); ++ unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true); ++ unsigned CFIIndex = MF.addFrameInst( ++ MCCFIInstruction::createOffset(nullptr, Reg, Offset)); ++ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) ++ .addCFIIndex(CFIIndex); ++ } + } + +- // Generate new FP. ++ // If framepointer enabled, set it to point to the stack pointer on entry. + if (hasFP(MF)) { +- adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); +- +- // Emit ".cfi_def_cfa $fp, 0" +- unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( +- nullptr, RI->getDwarfRegNum(FPReg, true), 0)); +- BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) ++ // Insert instruction "addi.w/d $fp, $sp, StackSize" at this location. ++ TII.adjustReg(FP, SP, StackSize - LoongArchFI->getVarArgsSaveSize(), MBB, ++ MBBI, MachineInstr::FrameSetup); ++ // Emit ".cfi_def_cfa $fp, $varargs_size". ++ unsigned CFIIndex = MF.addFrameInst( ++ MCCFIInstruction::cfiDefCfa(nullptr, MRI->getDwarfRegNum(FP, true), ++ LoongArchFI->getVarArgsSaveSize())); ++ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlag(MachineInstr::FrameSetup); + } ++ ++ // Emit the second SP adjustment after saving callee saved registers. ++ if (FirstSPAdjustAmount && SecondSPAdjustAmount) { ++ if (hasFP(MF)) { ++ assert(SecondSPAdjustAmount > 0 && ++ "SecondSPAdjustAmount should be greater than zero"); ++ TII.adjustReg(SP, SP, -SecondSPAdjustAmount, MBB, MBBI, ++ MachineInstr::FrameSetup); ++ } else { ++ // FIXME: RegScavenger will place the spill instruction before the ++ // prologue if a VReg is created in the prologue. This will pollute the ++ // caller's stack data. Therefore, until there is better way, we just use ++ // the `addi.w/d` instruction for stack adjustment to ensure that VReg ++ // will not be created. ++ for (int Val = SecondSPAdjustAmount; Val > 0; Val -= 2048) ++ BuildMI(MBB, MBBI, dl, TII.get(ADDI), SP) ++ .addReg(SP) ++ .addImm(Val < 2048 ? -Val : -2048) ++ .setMIFlag(MachineInstr::FrameSetup); ++ // If we are using a frame-pointer, and thus emitted ".cfi_def_cfa fp, 0", ++ // don't emit an sp-based .cfi_def_cfa_offset. ++ // Emit ".cfi_def_cfa_offset StackSize" ++ unsigned CFIIndex = MF.addFrameInst( ++ MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize())); ++ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) ++ .addCFIIndex(CFIIndex) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++ ++ // Realign stack. ++ if (hasFP(MF)) { ++ if (RegInfo.hasStackRealignment(MF)) { ++ // addiu $Reg, $zero, -MaxAlignment ++ // andi $sp, $sp, $Reg ++ unsigned VR = MF.getRegInfo().createVirtualRegister(RC); ++ assert((Log2(MFI.getMaxAlign()) < 16) && ++ "Function's alignment size requirement is not supported."); ++ int MaxAlign = -(int)MFI.getMaxAlign().value(); ++ int Alignment = (int)MFI.getMaxAlign().value(); ++ ++ if (Alignment <= 2048) { ++ BuildMI(MBB, MBBI, dl, TII.get(ADDI), VR).addReg(ZERO).addImm(MaxAlign); ++ BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); ++ } else { ++ const unsigned NrBitsToZero = countTrailingZeros((unsigned)Alignment); ++ BuildMI(MBB, MBBI, dl, TII.get(ADDI), VR).addReg(ZERO).addImm(-1); ++ BuildMI(MBB, MBBI, dl, TII.get(SLLI), VR) ++ .addReg(VR) ++ .addImm(NrBitsToZero); ++ BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); ++ } ++ ++ if (hasBP(MF)) { ++ // move $s7, $sp ++ unsigned BP = STI.isABI_LP64() ? LoongArch::S7_64 : LoongArch::S7; ++ BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP).addReg(SP).addReg(ZERO); ++ } ++ } ++ } + } + + void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { +- const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); +- MachineFrameInfo &MFI = MF.getFrameInfo(); +- Register SPReg = LoongArch::R3; +- + MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); +- DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); + +- const auto &CSI = MFI.getCalleeSavedInfo(); +- // Skip to before the restores of callee-saved registers. +- auto LastFrameDestroy = MBBI; +- if (!CSI.empty()) +- LastFrameDestroy = std::prev(MBBI, CSI.size()); ++ const LoongArchInstrInfo &TII = ++ *static_cast(STI.getInstrInfo()); ++ const LoongArchRegisterInfo &RegInfo = ++ *static_cast(STI.getRegisterInfo()); ++ ++ DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); ++ LoongArchABIInfo ABI = STI.getABI(); ++ unsigned SP = ABI.GetStackPtr(); ++ unsigned FP = ABI.GetFramePtr(); + + // Get the number of bytes from FrameInfo. + uint64_t StackSize = MFI.getStackSize(); + + // Restore the stack pointer. +- if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) { +- assert(hasFP(MF) && "frame pointer should not have been eliminated"); +- adjustReg(MBB, LastFrameDestroy, DL, SPReg, LoongArch::R22, -StackSize, +- MachineInstr::FrameDestroy); ++ if (hasFP(MF) && ++ (RegInfo.hasStackRealignment(MF) || MFI.hasVarSizedObjects())) { ++ // Find the first instruction that restores a callee-saved register. ++ MachineBasicBlock::iterator I = MBBI; ++ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) ++ --I; ++ TII.adjustReg(SP, FP, -(StackSize - LoongArchFI->getVarArgsSaveSize()), MBB, ++ I); + } + +- // Deallocate stack +- adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); +-} ++ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); ++ if (FirstSPAdjustAmount) { ++ uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount; ++ assert(SecondSPAdjustAmount > 0 && ++ "SecondSPAdjustAmount should be greater than zero"); ++ // Find the first instruction that restores a callee-saved register. ++ MachineBasicBlock::iterator I = MBBI; ++ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) ++ --I; ++ ++ TII.adjustReg(SP, SP, SecondSPAdjustAmount, MBB, I); ++ } + +-void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, +- BitVector &SavedRegs, +- RegScavenger *RS) const { +- TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); +- // Unconditionally spill RA and FP only if the function uses a frame +- // pointer. +- if (hasFP(MF)) { +- SavedRegs.set(LoongArch::R1); +- SavedRegs.set(LoongArch::R22); ++ if (LoongArchFI->callsEhReturn()) { ++ const TargetRegisterClass *RC = ++ ABI.ArePtrs64bit() ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ ++ // Find first instruction that restores a callee-saved register. ++ MachineBasicBlock::iterator I = MBBI; ++ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) ++ --I; ++ ++ // Insert instructions that restore eh data registers. ++ for (int J = 0; J < 4; ++J) ++ TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J), ++ LoongArchFI->getEhDataRegFI(J), RC, &RegInfo); + } +- // Mark BP as used if function has dedicated base pointer. +- if (hasBP(MF)) +- SavedRegs.set(LoongArchABI::getBPReg()); ++ ++ if (FirstSPAdjustAmount) ++ StackSize = FirstSPAdjustAmount; ++ ++ if (!StackSize) ++ return; ++ ++ // Final adjust stack. ++ TII.adjustReg(SP, SP, StackSize, MBB, MBBI); + } + +-StackOffset LoongArchFrameLowering::getFrameIndexReference( +- const MachineFunction &MF, int FI, Register &FrameReg) const { ++StackOffset ++LoongArchFrameLowering::getFrameIndexReference(const MachineFunction &MF, ++ int FI, ++ Register &FrameReg) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); ++ LoongArchABIInfo ABI = STI.getABI(); ++ const auto *LoongArchFI = MF.getInfo(); + + // Callee-saved registers should be referenced relative to the stack + // pointer (positive offset), otherwise use the frame pointer (negative +@@ -207,17 +380,182 @@ StackOffset LoongArchFrameLowering::getFrameIndexReference( + StackOffset Offset = + StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + + MFI.getOffsetAdjustment()); ++ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); + + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } + +- FrameReg = RI->getFrameRegister(MF); +- if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) { +- FrameReg = LoongArch::R3; ++ bool EhDataRegFI = LoongArchFI->isEhDataRegFI(FI); ++ if ((FI >= MinCSFI && FI <= MaxCSFI) || EhDataRegFI) { ++ FrameReg = ABI.GetStackPtr(); ++ ++ if (FirstSPAdjustAmount) ++ Offset += StackOffset::getFixed(FirstSPAdjustAmount); ++ else ++ Offset += StackOffset::getFixed(MFI.getStackSize()); ++ } else if (RI->hasStackRealignment(MF) && !MFI.isFixedObjectIndex(FI)) { ++ // If the stack was realigned, the frame pointer is set in order to allow ++ // SP to be restored, so we need another base register to record the stack ++ // after realignment. ++ FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr(); + Offset += StackOffset::getFixed(MFI.getStackSize()); ++ } else { ++ FrameReg = RI->getFrameRegister(MF); ++ if (hasFP(MF)) ++ Offset += StackOffset::getFixed(LoongArchFI->getVarArgsSaveSize()); ++ else ++ Offset += StackOffset::getFixed(MFI.getStackSize()); + } +- + return Offset; + } ++ ++bool LoongArchFrameLowering::spillCalleeSavedRegisters( ++ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ ArrayRef CSI, const TargetRegisterInfo *TRI) const { ++ MachineFunction *MF = MBB.getParent(); ++ const TargetInstrInfo &TII = *STI.getInstrInfo(); ++ ++ for (unsigned i = 0, e = CSI.size(); i != e; ++i) { ++ // Add the callee-saved register as live-in. Do not add if the register is ++ // RA and return address is taken, because it has already been added in ++ // method LoongArchTargetLowering::lowerRETURNADDR. ++ // It's killed at the spill, unless the register is RA and return address ++ // is taken. ++ unsigned Reg = CSI[i].getReg(); ++ bool IsRAAndRetAddrIsTaken = (Reg == LoongArch::RA || Reg == LoongArch::RA_64) ++ && MF->getFrameInfo().isReturnAddressTaken(); ++ if (!IsRAAndRetAddrIsTaken) ++ MBB.addLiveIn(Reg); ++ ++ // Insert the spill to the stack frame. ++ bool IsKill = !IsRAAndRetAddrIsTaken; ++ const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); ++ TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, ++ CSI[i].getFrameIdx(), RC, TRI); ++ } ++ ++ return true; ++} ++ ++bool ++LoongArchFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { ++ const MachineFrameInfo &MFI = MF.getFrameInfo(); ++ // Reserve call frame if the size of the maximum call frame fits into 12-bit ++ // immediate field and there are no variable sized objects on the stack. ++ // Make sure the second register scavenger spill slot can be accessed with one ++ // instruction. ++ return isInt<12>(MFI.getMaxCallFrameSize() + getStackAlignment()) && ++ !MFI.hasVarSizedObjects(); ++} ++ ++/// Mark \p Reg and all registers aliasing it in the bitset. ++static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, ++ unsigned Reg) { ++ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); ++ for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) ++ SavedRegs.set(*AI); ++} ++ ++void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, ++ BitVector &SavedRegs, ++ RegScavenger *RS) const { ++ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); ++ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); ++ LoongArchABIInfo ABI = STI.getABI(); ++ unsigned FP = ABI.GetFramePtr(); ++ unsigned BP = ABI.IsLP64() ? LoongArch::S7_64 : LoongArch::S7; ++ ++ // Mark $fp as used if function has dedicated frame pointer. ++ if (hasFP(MF)) ++ setAliasRegs(MF, SavedRegs, FP); ++ // Mark $s7 as used if function has dedicated base pointer. ++ if (hasBP(MF)) ++ setAliasRegs(MF, SavedRegs, BP); ++ ++ // Create spill slots for eh data registers if function calls eh_return. ++ if (LoongArchFI->callsEhReturn()) ++ LoongArchFI->createEhDataRegsFI(); ++ ++ // Set scavenging frame index if necessary. ++ uint64_t MaxSPOffset = estimateStackSize(MF); ++ ++ // If there is a variable ++ // sized object on the stack, the estimation cannot account for it. ++ if (isIntN(12, MaxSPOffset) && ++ !MF.getFrameInfo().hasVarSizedObjects()) ++ return; ++ ++ const TargetRegisterClass &RC = ++ ABI.ArePtrs64bit() ? LoongArch::GPR64RegClass : LoongArch::GPR32RegClass; ++ int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC), ++ TRI->getSpillAlign(RC), false); ++ RS->addScavengingFrameIndex(FI); ++} ++ ++// hasFP - Return true if the specified function should have a dedicated frame ++// pointer register. This is true if the function has variable sized allocas, ++// if it needs dynamic stack realignment, if frame pointer elimination is ++// disabled, or if the frame address is taken. ++bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const { ++ const MachineFrameInfo &MFI = MF.getFrameInfo(); ++ const TargetRegisterInfo *TRI = STI.getRegisterInfo(); ++ ++ return MF.getTarget().Options.DisableFramePointerElim(MF) || ++ MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || ++ TRI->hasStackRealignment(MF); ++} ++ ++bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const { ++ const MachineFrameInfo &MFI = MF.getFrameInfo(); ++ const TargetRegisterInfo *TRI = STI.getRegisterInfo(); ++ ++ return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF); ++} ++ ++// Estimate the size of the stack, including the incoming arguments. We need to ++// account for register spills, local objects, reserved call frame and incoming ++// arguments. This is required to determine the largest possible positive offset ++// from $sp so that it can be determined if an emergency spill slot for stack ++// addresses is required. ++uint64_t LoongArchFrameLowering:: ++estimateStackSize(const MachineFunction &MF) const { ++ const MachineFrameInfo &MFI = MF.getFrameInfo(); ++ const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); ++ ++ int64_t Size = 0; ++ ++ // Iterate over fixed sized objects which are incoming arguments. ++ for (int I = MFI.getObjectIndexBegin(); I != 0; ++I) ++ if (MFI.getObjectOffset(I) > 0) ++ Size += MFI.getObjectSize(I); ++ ++ // Conservatively assume all callee-saved registers will be saved. ++ for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) { ++ unsigned RegSize = TRI.getSpillSize(*TRI.getMinimalPhysRegClass(*R)); ++ Size = alignTo(Size + RegSize, RegSize); ++ } ++ ++ // Get the size of the rest of the frame objects and any possible reserved ++ // call frame, accounting for alignment. ++ return Size + MFI.estimateStackSize(MF); ++} ++ ++// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions ++MachineBasicBlock::iterator LoongArchFrameLowering:: ++eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const { ++ unsigned SP = STI.getABI().IsLP64() ? LoongArch::SP_64 : LoongArch::SP; ++ ++ if (!hasReservedCallFrame(MF)) { ++ int64_t Amount = I->getOperand(0).getImm(); ++ if (I->getOpcode() == LoongArch::ADJCALLSTACKDOWN) ++ Amount = -Amount; ++ ++ STI.getInstrInfo()->adjustReg(SP, SP, Amount, MBB, I); ++ } ++ ++ return MBB.erase(I); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h +index 72d8e006a..74aabaeb4 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h +@@ -1,4 +1,4 @@ +-//=- LoongArchFrameLowering.h - TargetFrameLowering for LoongArch -*- C++ -*--// ++//===-- LoongArchFrameLowering.h - Define frame lowering for LoongArch ----*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,51 +6,66 @@ + // + //===----------------------------------------------------------------------===// + // +-// This class implements LoongArch-specific bits of TargetFrameLowering class. ++// + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H + ++#include "LoongArch.h" + #include "llvm/CodeGen/TargetFrameLowering.h" + + namespace llvm { +-class LoongArchSubtarget; ++ class LoongArchSubtarget; + + class LoongArchFrameLowering : public TargetFrameLowering { + const LoongArchSubtarget &STI; + + public: +- explicit LoongArchFrameLowering(const LoongArchSubtarget &STI) +- : TargetFrameLowering(StackGrowsDown, +- /*StackAlignment=*/Align(16), +- /*LocalAreaOffset=*/0), +- STI(STI) {} ++ explicit LoongArchFrameLowering(const LoongArchSubtarget &STI); + ++ /// emitProlog/emitEpilog - These methods insert prolog and epilog code into ++ /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + ++ StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, ++ Register &FrameReg) const override; ++ ++ bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI, ++ ArrayRef CSI, ++ const TargetRegisterInfo *TRI) const override; ++ ++ bool hasReservedCallFrame(const MachineFunction &MF) const override; ++ + void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, + RegScavenger *RS) const override; + +- MachineBasicBlock::iterator +- eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, +- MachineBasicBlock::iterator MI) const override { +- return MBB.erase(MI); ++ bool hasFP(const MachineFunction &MF) const override; ++ ++ bool hasBP(const MachineFunction &MF) const; ++ ++ bool enableShrinkWrapping(const MachineFunction &MF) const override { ++ return true; + } + +- StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, +- Register &FrameReg) const override; ++ MachineBasicBlock::iterator ++ eliminateCallFramePseudoInstr(MachineFunction &MF, ++ MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const override; + +- bool hasFP(const MachineFunction &MF) const override; +- bool hasBP(const MachineFunction &MF) const; ++ // Get the first stack adjustment amount for split the SP adjustment. ++ // Return 0 if we don't want to to split the SP adjustment in prologue and ++ // epilogue. ++ uint64_t getFirstSPAdjustAmount(const MachineFunction &MF, ++ bool IsPrologue = false) const; + +-private: +- void determineFrameLayout(MachineFunction &MF) const; +- void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, +- const DebugLoc &DL, Register DestReg, Register SrcReg, +- int64_t Val, MachineInstr::MIFlag Flag) const; ++protected: ++ uint64_t estimateStackSize(const MachineFunction &MF) const; + }; +-} // end namespace llvm +-#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H ++ ++} // End llvm namespace ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp +index bb40ff817..0efb739e0 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp +@@ -1,4 +1,4 @@ +-//=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===// ++//===-- LoongArchISelDAGToDAG.cpp - A Dag to Dag Inst Selector for LoongArch --------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,176 +11,868 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchISelDAGToDAG.h" +-#include "LoongArchISelLowering.h" ++#include "LoongArch.h" ++#include "LoongArchMachineFunction.h" ++#include "LoongArchRegisterInfo.h" ++#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" +-#include "MCTargetDesc/LoongArchMatInt.h" +-#include "llvm/Support/KnownBits.h" +- ++#include "llvm/CodeGen/MachineConstantPool.h" ++#include "llvm/CodeGen/MachineFrameInfo.h" ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/SelectionDAGNodes.h" ++#include "llvm/IR/CFG.h" ++#include "llvm/IR/Dominators.h" ++#include "llvm/IR/GlobalValue.h" ++#include "llvm/IR/Instructions.h" ++#include "llvm/IR/Intrinsics.h" ++#include "llvm/IR/IntrinsicsLoongArch.h" ++#include "llvm/IR/Type.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/raw_ostream.h" ++#include "llvm/Target/TargetMachine.h" + using namespace llvm; + + #define DEBUG_TYPE "loongarch-isel" + +-void LoongArchDAGToDAGISel::Select(SDNode *Node) { +- // If we have a custom node, we have already selected. +- if (Node->isMachineOpcode()) { +- LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); +- Node->setNodeId(-1); +- return; +- } ++//===----------------------------------------------------------------------===// ++// Instruction Selector Implementation ++//===----------------------------------------------------------------------===// + +- // Instruction Selection not handled by the auto-generated tablegen selection +- // should be handled here. +- unsigned Opcode = Node->getOpcode(); +- MVT GRLenVT = Subtarget->getGRLenVT(); +- SDLoc DL(Node); +- MVT VT = Node->getSimpleValueType(0); ++//===----------------------------------------------------------------------===// ++// LoongArchDAGToDAGISel - LoongArch specific code to select LoongArch machine ++// instructions for SelectionDAG operations. ++//===----------------------------------------------------------------------===// + +- switch (Opcode) { +- default: +- break; +- case ISD::Constant: { +- int64_t Imm = cast(Node)->getSExtValue(); +- if (Imm == 0 && VT == GRLenVT) { +- SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, +- LoongArch::R0, GRLenVT); +- ReplaceNode(Node, New.getNode()); +- return; +- } +- SDNode *Result = nullptr; +- SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT); +- // The instructions in the sequence are handled here. +- for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { +- SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT); +- if (Inst.Opc == LoongArch::LU12I_W) +- Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm); +- else +- Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm); +- SrcReg = SDValue(Result, 0); +- } ++void LoongArchDAGToDAGISel::PostprocessISelDAG() { doPeepholeLoadStoreADDI(); } + +- ReplaceNode(Node, Result); +- return; ++void LoongArchDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { ++ AU.addRequired(); ++ SelectionDAGISel::getAnalysisUsage(AU); ++} ++ ++bool LoongArchDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { ++ Subtarget = &static_cast(MF.getSubtarget()); ++ bool Ret = SelectionDAGISel::runOnMachineFunction(MF); ++ ++ return Ret; ++} ++ ++/// Match frameindex ++bool LoongArchDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { ++ EVT ValTy = Addr.getValueType(); ++ ++ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); ++ Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); ++ return true; + } +- case ISD::FrameIndex: { +- SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT); +- int FI = cast(Node)->getIndex(); +- SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); +- unsigned ADDIOp = +- Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; +- ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm)); +- return; ++ return false; ++} ++ ++/// Match frameindex+offset and frameindex|offset ++bool LoongArchDAGToDAGISel::selectAddrFrameIndexOffset( ++ SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits, ++ unsigned ShiftAmount = 0) const { ++ if (CurDAG->isBaseWithConstantOffset(Addr)) { ++ ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)); ++ if (isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) { ++ EVT ValTy = Addr.getValueType(); ++ ++ // If the first operand is a FI, get the TargetFI Node ++ if (FrameIndexSDNode *FIN = ++ dyn_cast(Addr.getOperand(0))) ++ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); ++ else { ++ Base = Addr.getOperand(0); ++ // If base is a FI, additional offset calculation is done in ++ // eliminateFrameIndex, otherwise we need to check the alignment ++ const Align Alignment(1ULL << ShiftAmount); ++ if (!isAligned(Alignment, CN->getZExtValue())) ++ return false; ++ } ++ ++ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ++ ValTy); ++ return true; ++ } + } +- // TODO: Add selection nodes needed later. ++ return false; ++} ++ ++/// ComplexPattern used on LoongArchInstrInfo ++/// Used on LoongArch Load/Store instructions ++bool LoongArchDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ // if Address is FI, get the TargetFrameIndex. ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (!TM.isPositionIndependent()) { ++ if ((Addr.getOpcode() == ISD::TargetExternalSymbol || ++ Addr.getOpcode() == ISD::TargetGlobalAddress)) ++ return false; + } + +- // Select the default instruction. +- SelectCode(Node); ++ // Addresses of the form FI+const or FI|const ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) ++ return true; ++ ++ return false; + } + +-bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { +- // If this is FrameIndex, select it directly. Otherwise just let it get +- // selected to a register independently. +- if (auto *FIN = dyn_cast(Addr)) +- Base = +- CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT()); +- else +- Base = Addr; ++/// ComplexPattern used on LoongArchInstrInfo ++/// Used on LoongArch Load/Store instructions ++bool LoongArchDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ Base = Addr; ++ Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); + return true; + } + +-bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, +- SDValue &ShAmt) { +- // Shift instructions on LoongArch only read the lower 5 or 6 bits of the +- // shift amount. If there is an AND on the shift amount, we can bypass it if +- // it doesn't affect any of those bits. +- if (N.getOpcode() == ISD::AND && isa(N.getOperand(1))) { +- const APInt &AndMask = N->getConstantOperandAPInt(1); ++bool LoongArchDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ return selectAddrRegImm(Addr, Base, Offset) || ++ selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) ++ return true; ++ ++ return false; ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm12(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; + +- // Since the max shift amount is a power of 2 we can subtract 1 to make a +- // mask that covers the bits needed to represent all shift amounts. +- assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); +- APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1); ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 1)) ++ return true; + +- if (ShMask.isSubsetOf(AndMask)) { +- ShAmt = N.getOperand(0); ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 2)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm11Lsl1(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11, 1)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm9Lsl3(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9, 3)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm14Lsl2(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 14, 2)) ++ return true; ++ ++ return false; ++} ++ ++bool LoongArchDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const { ++ if (selectAddrFrameIndex(Addr, Base, Offset)) ++ return true; ++ ++ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 3)) ++ return true; ++ ++ return selectAddrDefault(Addr, Base, Offset); ++} ++ ++// Select constant vector splats. ++// ++// Returns true and sets Imm if: ++// * LSX is enabled ++// * N is a ISD::BUILD_VECTOR representing a constant splat ++bool LoongArchDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, ++ unsigned MinSizeInBits) const { ++ if (!(Subtarget->hasLSX() || Subtarget->hasLASX())) ++ return false; ++ ++ BuildVectorSDNode *Node = dyn_cast(N); ++ ++ if (!Node) ++ return false; ++ ++ APInt SplatValue, SplatUndef; ++ unsigned SplatBitSize; ++ bool HasAnyUndefs; ++ ++ if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, ++ MinSizeInBits)) ++ return false; ++ ++ Imm = SplatValue; ++ ++ return true; ++} ++ ++// Select constant vector splats. ++// ++// In addition to the requirements of selectVSplat(), this function returns ++// true and sets Imm if: ++// * The splat value is the same width as the elements of the vector ++// * The splat value fits in an integer with the specified signed-ness and ++// width. ++// ++// This function looks through ISD::BITCAST nodes. ++// TODO: This might not be appropriate for big-endian LSX since BITCAST is ++// sometimes a shuffle in big-endian mode. ++// ++// It's worth noting that this function is not used as part of the selection ++// of [v/xv]ldi.[bhwd] since it does not permit using the wrong-typed ++// [v/xv]ldi.[bhwd] instruction to achieve the desired bit pattern. ++// [v/xv]ldi.[bhwd] is selected in LoongArchDAGToDAGISel::selectNode. ++bool LoongArchDAGToDAGISel::selectVSplatCommon(SDValue N, SDValue &Imm, ++ bool Signed, ++ unsigned ImmBitSize) const { ++ APInt ImmValue; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); ++ ++ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ++ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { ++ ++ if ((Signed && ImmValue.isSignedIntN(ImmBitSize)) || ++ (!Signed && ImmValue.isIntN(ImmBitSize))) { ++ Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy); + return true; + } ++ } ++ ++ return false; ++} ++ ++// Select constant vector splats. ++bool LoongArchDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 1); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 2); ++} + +- // SimplifyDemandedBits may have optimized the mask so try restoring any +- // bits that are known zero. +- KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); +- if (ShMask.isSubsetOf(AndMask | Known.Zero)) { +- ShAmt = N.getOperand(0); ++bool LoongArchDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 3); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 4); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 5); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 6); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, false, 8); ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const { ++ return selectVSplatCommon(N, Imm, true, 5); ++} ++ ++// Select constant vector splats whose value is a power of 2. ++// ++// In addition to the requirements of selectVSplat(), this function returns ++// true and sets Imm if: ++// * The splat value is the same width as the elements of the vector ++// * The splat value is a power of two. ++// ++// This function looks through ISD::BITCAST nodes. ++// TODO: This might not be appropriate for big-endian LSX since BITCAST is ++// sometimes a shuffle in big-endian mode. ++bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N, ++ SDValue &Imm) const { ++ APInt ImmValue; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); ++ ++ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ++ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { ++ int32_t Log2 = ImmValue.exactLogBase2(); ++ ++ if (Log2 != -1) { ++ Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); + return true; + } +- } else if (N.getOpcode() == LoongArchISD::BSTRPICK) { +- // Similar to the above AND, if there is a BSTRPICK on the shift amount, we +- // can bypass it. +- assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); +- assert(isa(N.getOperand(1)) && "Illegal msb operand!"); +- assert(isa(N.getOperand(2)) && "Illegal lsb operand!"); +- uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2); +- if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) { +- ShAmt = N.getOperand(0); ++ } ++ ++ return false; ++} ++ ++bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, ++ SDValue &Imm) const { ++ APInt ImmValue; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); ++ ++ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ++ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { ++ int32_t Log2 = (~ImmValue).exactLogBase2(); ++ ++ if (Log2 != -1) { ++ Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); + return true; + } +- } else if (N.getOpcode() == ISD::SUB && +- isa(N.getOperand(0))) { +- uint64_t Imm = N.getConstantOperandVal(0); +- // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to +- // generate a NEG instead of a SUB of a constant. +- if (Imm != 0 && Imm % ShiftWidth == 0) { +- SDLoc DL(N); +- EVT VT = N.getValueType(); +- SDValue Zero = +- CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT); +- unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W; +- MachineSDNode *Neg = +- CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1)); +- ShAmt = SDValue(Neg, 0); ++ } ++ ++ return false; ++} ++ ++// Select constant vector splats whose value only has a consecutive sequence ++// of left-most bits set (e.g. 0b11...1100...00). ++// ++// In addition to the requirements of selectVSplat(), this function returns ++// true and sets Imm if: ++// * The splat value is the same width as the elements of the vector ++// * The splat value is a consecutive sequence of left-most bits. ++// ++// This function looks through ISD::BITCAST nodes. ++// TODO: This might not be appropriate for big-endian LSX since BITCAST is ++// sometimes a shuffle in big-endian mode. ++bool LoongArchDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { ++ APInt ImmValue; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); ++ ++ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ++ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { ++ // Extract the run of set bits starting with bit zero from the bitwise ++ // inverse of ImmValue, and test that the inverse of this is the same ++ // as the original value. ++ if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { ++ ++ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), ++ EltTy); + return true; + } + } + +- ShAmt = N; +- return true; ++ return false; + } + +-bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { +- if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && +- cast(N.getOperand(1))->getVT() == MVT::i32) { +- Val = N.getOperand(0); +- return true; +- } +- MVT VT = N.getSimpleValueType(); +- if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) { +- Val = N; +- return true; ++// Select constant vector splats whose value only has a consecutive sequence ++// of right-most bits set (e.g. 0b00...0011...11). ++// ++// In addition to the requirements of selectVSplat(), this function returns ++// true and sets Imm if: ++// * The splat value is the same width as the elements of the vector ++// * The splat value is a consecutive sequence of right-most bits. ++// ++// This function looks through ISD::BITCAST nodes. ++// TODO: This might not be appropriate for big-endian LSX since BITCAST is ++// sometimes a shuffle in big-endian mode. ++bool LoongArchDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { ++ APInt ImmValue; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); ++ ++ if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ++ ImmValue.getBitWidth() == EltTy.getSizeInBits()) { ++ // Extract the run of set bits starting with bit zero, and test that the ++ // result is the same as the original value ++ if (ImmValue == (ImmValue & ~(ImmValue + 1))) { ++ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), ++ EltTy); ++ return true; ++ } + } + + return false; + } + +-bool LoongArchDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { +- if (N.getOpcode() == ISD::AND) { +- auto *C = dyn_cast(N.getOperand(1)); +- if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) { +- Val = N.getOperand(0); ++bool LoongArchDAGToDAGISel::trySelect(SDNode *Node) { ++ unsigned Opcode = Node->getOpcode(); ++ SDLoc DL(Node); ++ ++ /// ++ // Instruction Selection not handled by the auto-generated ++ // tablegen selection should be handled here. ++ /// ++ switch(Opcode) { ++ default: break; ++ case ISD::ConstantFP: { ++ ConstantFPSDNode *CN = dyn_cast(Node); ++ if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { ++ if (Subtarget->is64Bit()) { ++ SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, ++ LoongArch::ZERO_64, MVT::i64); ++ ReplaceNode(Node, ++ CurDAG->getMachineNode(LoongArch::MOVGR2FR_D, DL, MVT::f64, Zero)); ++ } + return true; + } ++ break; + } +- MVT VT = N.getSimpleValueType(); +- APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 32); +- if (CurDAG->MaskedValueIsZero(N, Mask)) { +- Val = N; ++ ++ case ISD::Constant: { ++ const ConstantSDNode *CN = dyn_cast(Node); ++ MVT VT = CN->getSimpleValueType(0); ++ int64_t Imm = CN->getSExtValue(); ++ LoongArchAnalyzeImmediate::InstSeq Seq = ++ LoongArchAnalyzeImmediate::generateInstSeq(Imm, VT == MVT::i64); ++ SDLoc DL(CN); ++ SDNode *Result = nullptr; ++ SDValue SrcReg = CurDAG->getRegister( ++ VT == MVT::i64 ? LoongArch::ZERO_64 : LoongArch::ZERO, VT); ++ ++ // The instructions in the sequence are handled here. ++ for (LoongArchAnalyzeImmediate::Inst &Inst : Seq) { ++ SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, VT); ++ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) ++ Result = CurDAG->getMachineNode(Inst.Opc, DL, VT, SDImm); ++ else ++ Result = CurDAG->getMachineNode(Inst.Opc, DL, VT, SrcReg, SDImm); ++ SrcReg = SDValue(Result, 0); ++ } ++ ReplaceNode(Node, Result); + return true; + } + ++ case ISD::BUILD_VECTOR: { ++ // Select appropriate vldi.[bhwd] instructions for constant splats of ++ // 128-bit when LSX is enabled. Select appropriate xvldi.[bhwd] instructions ++ // for constant splats of 256-bit when LASX is enabled. Fixup any register ++ // class mismatches that occur as a result. ++ // ++ // This allows the compiler to use a wider range of immediates than would ++ // otherwise be allowed. If, for example, v4i32 could only use [v/xv]ldi.h ++ // then it would not be possible to load { 0x01010101, 0x01010101, ++ // 0x01010101, 0x01010101 } without using a constant pool. This would be ++ // sub-optimal when // '[v/xv]ldi.b vd, 1' is capable of producing that ++ // bit-pattern in the same set/ of registers. Similarly, [v/xv]ldi.h isn't ++ // capable of producing { 0x00000000, 0x00000001, 0x00000000, 0x00000001 } ++ // but '[v/xv]ldi.d vd, 1' can. ++ ++ const LoongArchABIInfo &ABI = ++ static_cast(TM).getABI(); ++ ++ BuildVectorSDNode *BVN = cast(Node); ++ APInt SplatValue, SplatUndef; ++ unsigned SplatBitSize; ++ bool HasAnyUndefs; ++ unsigned LdiOp; ++ EVT ResVecTy = BVN->getValueType(0); ++ EVT ViaVecTy; ++ ++ if ((!Subtarget->hasLSX() || !BVN->getValueType(0).is128BitVector()) && ++ (!Subtarget->hasLASX() || !BVN->getValueType(0).is256BitVector())) ++ return false; ++ ++ if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, ++ HasAnyUndefs, 8)) ++ return false; ++ ++ bool IsLASX256 = BVN->getValueType(0).is256BitVector(); ++ ++ switch (SplatBitSize) { ++ default: ++ return false; ++ case 8: ++ LdiOp = IsLASX256 ? LoongArch::XVLDI_B : LoongArch::VLDI_B; ++ ViaVecTy = IsLASX256 ? MVT::v32i8 : MVT::v16i8; ++ break; ++ case 16: ++ LdiOp = IsLASX256 ? LoongArch::XVLDI_H : LoongArch::VLDI_H; ++ ViaVecTy = IsLASX256 ? MVT::v16i16 : MVT::v8i16; ++ break; ++ case 32: ++ LdiOp = IsLASX256 ? LoongArch::XVLDI_W : LoongArch::VLDI_W; ++ ViaVecTy = IsLASX256 ? MVT::v8i32 : MVT::v4i32; ++ break; ++ case 64: ++ LdiOp = IsLASX256 ? LoongArch::XVLDI_D : LoongArch::VLDI_D; ++ ViaVecTy = IsLASX256 ? MVT::v4i64 : MVT::v2i64; ++ break; ++ } ++ ++ SDNode *Res; ++ ++ // If we have a signed 13 bit integer, we can splat it directly. ++ // ++ // If we have something bigger we can synthesize the value into a GPR and ++ // splat from there. ++ if (SplatValue.isSignedIntN(10)) { ++ SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, ++ ViaVecTy.getVectorElementType()); ++ ++ Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); ++ } else if (SplatValue.isSignedIntN(12)) { ++ bool Is32BitSplat = SplatBitSize < 64 ? true : false; ++ const unsigned ADDIOp = ++ Is32BitSplat ? LoongArch::ADDI_W : LoongArch::ADDI_D; ++ const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; ++ SDValue ZeroVal = CurDAG->getRegister( ++ Is32BitSplat ? LoongArch::ZERO : LoongArch::ZERO_64, SplatMVT); ++ ++ const unsigned FILLOp = ++ (SplatBitSize == 16) ++ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_H : LoongArch::VREPLGR2VR_H) ++ : (SplatBitSize == 32 ++ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_W ++ : LoongArch::VREPLGR2VR_W) ++ : (SplatBitSize == 64 ++ ? (IsLASX256 ? LoongArch::XVREPLGR2VR_D ++ : LoongArch::VREPLGR2VR_D) ++ : 0)); ++ ++ assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!"); ++ ++ short Lo = SplatValue.getLoBits(12).getSExtValue(); ++ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT); ++ ++ Res = CurDAG->getMachineNode(ADDIOp, DL, SplatMVT, ZeroVal, LoVal); ++ Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0)); ++ } else if (SplatValue.isSignedIntN(16) && SplatBitSize == 16) { ++ const unsigned Lo = SplatValue.getLoBits(12).getZExtValue(); ++ const unsigned Hi = SplatValue.lshr(12).getLoBits(4).getZExtValue(); ++ SDValue ZeroVal = CurDAG->getRegister(LoongArch::ZERO, MVT::i32); ++ ++ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); ++ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); ++ if (Hi) ++ Res = CurDAG->getMachineNode(LoongArch::LU12I_W32, DL, MVT::i32, HiVal); ++ ++ if (Lo) ++ Res = CurDAG->getMachineNode(LoongArch::ORI32, DL, MVT::i32, ++ Hi ? SDValue(Res, 0) : ZeroVal, LoVal); ++ ++ assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); ++ const unsigned FILLOp = ++ IsLASX256 ? LoongArch::XVREPLGR2VR_H : LoongArch::VREPLGR2VR_H; ++ EVT FILLTy = IsLASX256 ? MVT::v16i16 : MVT::v8i16; ++ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); ++ } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) { ++ // Only handle the cases where the splat size agrees with the size ++ // of the SplatValue here. ++ const unsigned Lo = SplatValue.getLoBits(12).getZExtValue(); ++ const unsigned Hi = SplatValue.lshr(12).getLoBits(20).getZExtValue(); ++ SDValue ZeroVal = CurDAG->getRegister(LoongArch::ZERO, MVT::i32); ++ ++ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); ++ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); ++ if (Hi) ++ Res = CurDAG->getMachineNode(LoongArch::LU12I_W32, DL, MVT::i32, HiVal); ++ ++ if (Lo) ++ Res = CurDAG->getMachineNode(LoongArch::ORI32, DL, MVT::i32, ++ Hi ? SDValue(Res, 0) : ZeroVal, LoVal); ++ ++ assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); ++ const unsigned FILLOp = ++ IsLASX256 ? LoongArch::XVREPLGR2VR_W : LoongArch::VREPLGR2VR_W; ++ EVT FILLTy = IsLASX256 ? MVT::v8i32 : MVT::v4i32; ++ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); ++ ++ } else if ((SplatValue.isSignedIntN(32) && SplatBitSize == 64 && ++ ABI.IsLP64()) || ++ (SplatValue.isSignedIntN(64))) { ++ ++ int64_t Imm = SplatValue.getSExtValue(); ++ LoongArchAnalyzeImmediate::InstSeq Seq = ++ LoongArchAnalyzeImmediate::generateInstSeq(Imm, true); ++ SDValue SrcReg = CurDAG->getRegister(LoongArch::ZERO_64, MVT::i64); ++ ++ for (LoongArchAnalyzeImmediate::Inst &Inst : Seq) { ++ SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, MVT::i64); ++ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) ++ Res = CurDAG->getMachineNode(Inst.Opc, DL, MVT::i64, SDImm); ++ else ++ Res = CurDAG->getMachineNode(Inst.Opc, DL, MVT::i64, SrcReg, SDImm); ++ SrcReg = SDValue(Res, 0); ++ } ++ ++ const unsigned FILLOp = ++ IsLASX256 ? LoongArch::XVREPLGR2VR_D : LoongArch::VREPLGR2VR_D; ++ EVT FILLTy = IsLASX256 ? MVT::v4i64 : MVT::v2i64; ++ Res = CurDAG->getMachineNode(FILLOp, DL, FILLTy, SDValue(Res, 0)); ++ ++ } else ++ return false; ++ ++ if (ResVecTy != ViaVecTy) { ++ // If LdiOp is writing to a different register class to ResVecTy, then ++ // fix it up here. This COPY_TO_REGCLASS should never cause a move.v ++ // since the source and destination register sets contain the same ++ // registers. ++ const TargetLowering *TLI = getTargetLowering(); ++ MVT ResVecTySimple = ResVecTy.getSimpleVT(); ++ const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple); ++ Res = CurDAG->getMachineNode( ++ LoongArch::COPY_TO_REGCLASS, DL, ResVecTy, SDValue(Res, 0), ++ CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); ++ } ++ ++ ReplaceNode(Node, Res); ++ return true; ++ } ++ } ++ + return false; + } + +-// This pass converts a legalized DAG into a LoongArch-specific DAG, ready +-// for instruction scheduling. +-FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { +- return new LoongArchDAGToDAGISel(TM); ++/// Select instructions not customized! Used for ++/// expanded, promoted and normal instructions ++void LoongArchDAGToDAGISel::Select(SDNode *Node) { ++ // If we have a custom node, we already have selected! ++ if (Node->isMachineOpcode()) { ++ LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); ++ Node->setNodeId(-1); ++ return; ++ } ++ ++ // See if subclasses can handle this node. ++ if (trySelect(Node)) ++ return; ++ ++ // Select the default instruction ++ SelectCode(Node); ++} ++ ++bool LoongArchDAGToDAGISel:: ++SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, ++ std::vector &OutOps) { ++ SDValue Base, Offset; ++ ++ switch(ConstraintID) { ++ default: ++ llvm_unreachable("Unexpected asm memory constraint"); ++ // All memory constraints can at least accept raw pointers. ++ case InlineAsm::Constraint_i: ++ OutOps.push_back(Op); ++ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); ++ return false; ++ case InlineAsm::Constraint_m: ++ if (selectAddrRegImm12(Op, Base, Offset)) { ++ OutOps.push_back(Base); ++ OutOps.push_back(Offset); ++ return false; ++ } ++ OutOps.push_back(Op); ++ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); ++ return false; ++ case InlineAsm::Constraint_R: ++ if (selectAddrRegImm12(Op, Base, Offset)) { ++ OutOps.push_back(Base); ++ OutOps.push_back(Offset); ++ return false; ++ } ++ OutOps.push_back(Op); ++ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); ++ return false; ++ case InlineAsm::Constraint_ZC: ++ if (selectIntAddrSImm14Lsl2(Op, Base, Offset)) { ++ OutOps.push_back(Base); ++ OutOps.push_back(Offset); ++ return false; ++ } ++ OutOps.push_back(Op); ++ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); ++ return false; ++ case InlineAsm::Constraint_ZB: ++ OutOps.push_back(Op); ++ OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); ++ return false; ++ } ++ return true; ++} ++ ++// This optimisation is ported from RISCV. ++// Merge an ADDI into the offset of a load/store instruction where possible. ++// (load (addi base, off1), off2) -> (load base, off1+off2) ++// (store val, (addi base, off1), off2) -> (store val, base, off1+off2) ++// This is possible when off1+off2 fits a 12-bit immediate. ++void LoongArchDAGToDAGISel::doPeepholeLoadStoreADDI() { ++ SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); ++ ++Position; ++ ++ while (Position != CurDAG->allnodes_begin()) { ++ SDNode *N = &*--Position; ++ // Skip dead nodes and any non-machine opcodes. ++ if (N->use_empty() || !N->isMachineOpcode()) ++ continue; ++ ++ int OffsetOpIdx; ++ int BaseOpIdx; ++ ++ // TODO: handle more instructions. ++ switch (N->getMachineOpcode()) { ++ default: ++ continue; ++ case LoongArch::LD_B: ++ case LoongArch::LD_B32: ++ case LoongArch::LD_BU: ++ case LoongArch::LD_BU32: ++ case LoongArch::LD_H: ++ case LoongArch::LD_H32: ++ case LoongArch::LD_HU: ++ case LoongArch::LD_HU32: ++ case LoongArch::LD_W: ++ case LoongArch::LD_W32: ++ case LoongArch::LD_WU: ++ case LoongArch::LD_D: ++ BaseOpIdx = 0; ++ OffsetOpIdx = 1; ++ break; ++ case LoongArch::ST_B: ++ case LoongArch::ST_B32: ++ case LoongArch::ST_H: ++ case LoongArch::ST_H32: ++ case LoongArch::ST_W: ++ case LoongArch::ST_W32: ++ case LoongArch::ST_D: ++ BaseOpIdx = 1; ++ OffsetOpIdx = 2; ++ break; ++ } ++ ++ if (!isa(N->getOperand(OffsetOpIdx))) ++ continue; ++ ++ SDValue Base = N->getOperand(BaseOpIdx); ++ ++ // If the base is an ADDI, we can merge it in to the load/store. ++ // TODO: handle more instructions, i.e. ADDI_W. ++ if (!Base.isMachineOpcode() || Base.getMachineOpcode() != LoongArch::ADDI_D) ++ continue; ++ ++ SDValue ImmOperand = Base.getOperand(1); ++ uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); ++ ++ if (auto *Const = dyn_cast(ImmOperand)) { ++ int64_t Offset1 = Const->getSExtValue(); ++ int64_t CombinedOffset = Offset1 + Offset2; ++ if (!isInt<12>(CombinedOffset)) ++ continue; ++ ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand), ++ ImmOperand.getValueType()); ++ // TODO: handle below cases. ++#if 0 ++ } else if (auto *GA = dyn_cast(ImmOperand)) { ++ // If the off1 in (addi base, off1) is a global variable's address (its ++ // low part, really), then we can rely on the alignment of that variable ++ // to provide a margin of safety before off1 can overflow the 12 bits. ++ // Check if off2 falls within that margin; if so off1+off2 can't overflow. ++ const DataLayout &DL = CurDAG->getDataLayout(); ++ Align Alignment = GA->getGlobal()->getPointerAlignment(DL); ++ if (Offset2 != 0 && Alignment <= Offset2) ++ continue; ++ int64_t Offset1 = GA->getOffset(); ++ int64_t CombinedOffset = Offset1 + Offset2; ++ ImmOperand = CurDAG->getTargetGlobalAddress( ++ GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(), ++ CombinedOffset, GA->getTargetFlags()); ++ } else if (auto *CP = dyn_cast(ImmOperand)) { ++ // Ditto. ++ Align Alignment = CP->getAlign(); ++ if (Offset2 != 0 && Alignment <= Offset2) ++ continue; ++ int64_t Offset1 = CP->getOffset(); ++ int64_t CombinedOffset = Offset1 + Offset2; ++ ImmOperand = CurDAG->getTargetConstantPool( ++ CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(), ++ CombinedOffset, CP->getTargetFlags()); ++#endif ++ } else { ++ continue; ++ } ++ ++ LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); ++ LLVM_DEBUG(Base->dump(CurDAG)); ++ LLVM_DEBUG(dbgs() << "\nN: "); ++ LLVM_DEBUG(N->dump(CurDAG)); ++ LLVM_DEBUG(dbgs() << "\n"); ++ ++ // Modify the offset operand of the load/store. ++ if (BaseOpIdx == 0) // Load ++ CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, ++ N->getOperand(2)); ++ else // Store ++ CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), ++ ImmOperand, N->getOperand(3)); ++ ++ // The add-immediate may now be dead, in which case remove it. ++ if (Base.getNode()->use_empty()) ++ CurDAG->RemoveDeadNode(Base.getNode()); ++ } ++} ++ ++FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM, ++ CodeGenOpt::Level OptLevel) { ++ return new LoongArchDAGToDAGISel(TM, OptLevel); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h +index 8c9357d75..765497318 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h +@@ -1,4 +1,4 @@ +-//=- LoongArchISelDAGToDAG.h - A dag to dag inst selector for LoongArch ---===// ++//===---- LoongArchISelDAGToDAG.h - A Dag to Dag Inst Selector for LoongArch --------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -14,47 +14,138 @@ + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H + + #include "LoongArch.h" ++#include "LoongArchSubtarget.h" + #include "LoongArchTargetMachine.h" + #include "llvm/CodeGen/SelectionDAGISel.h" + +-// LoongArch-specific code to select LoongArch machine instructions for +-// SelectionDAG operations. ++//===----------------------------------------------------------------------===// ++// Instruction Selector Implementation ++//===----------------------------------------------------------------------===// ++ ++//===----------------------------------------------------------------------===// ++// LoongArchDAGToDAGISel - LoongArch specific code to select LoongArch machine ++// instructions for SelectionDAG operations. ++//===----------------------------------------------------------------------===// + namespace llvm { +-class LoongArchDAGToDAGISel : public SelectionDAGISel { +- const LoongArchSubtarget *Subtarget = nullptr; + ++class LoongArchDAGToDAGISel : public SelectionDAGISel { + public: +- explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM) +- : SelectionDAGISel(TM) {} ++ explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM, CodeGenOpt::Level OL) ++ : SelectionDAGISel(TM, OL), Subtarget(nullptr) {} + ++ // Pass Name + StringRef getPassName() const override { + return "LoongArch DAG->DAG Pattern Instruction Selection"; + } + +- bool runOnMachineFunction(MachineFunction &MF) override { +- Subtarget = &MF.getSubtarget(); +- return SelectionDAGISel::runOnMachineFunction(MF); +- } ++ bool runOnMachineFunction(MachineFunction &MF) override; + +- void Select(SDNode *Node) override; ++ void PostprocessISelDAG() override; + +- bool SelectBaseAddr(SDValue Addr, SDValue &Base); ++ void getAnalysisUsage(AnalysisUsage &AU) const override; + +- bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); +- bool selectShiftMaskGRLen(SDValue N, SDValue &ShAmt) { +- return selectShiftMask(N, Subtarget->getGRLen(), ShAmt); +- } +- bool selectShiftMask32(SDValue N, SDValue &ShAmt) { +- return selectShiftMask(N, 32, ShAmt); +- } ++private: ++ /// Keep a pointer to the LoongArchSubtarget around so that we can make the right ++ /// decision when generating code for different targets. ++ const LoongArchSubtarget *Subtarget; ++ // Include the pieces autogenerated from the target description. ++ #include "LoongArchGenDAGISel.inc" ++ ++ void doPeepholeLoadStoreADDI(); ++ ++ bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const; ++ ++ bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, ++ unsigned OffsetBits, ++ unsigned ShiftAmount) const; ++ ++ // Complex Pattern. ++ /// (reg + imm). ++ bool selectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) const; ++ ++ /// Fall back on this function if all else fails. ++ bool selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const; + +- bool selectSExti32(SDValue N, SDValue &Val); +- bool selectZExti32(SDValue N, SDValue &Val); ++ /// Match integer address pattern. ++ bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const; ++ ++ bool selectAddrRegImm12(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ /// Match addr+simm12 and addr ++ bool selectIntAddrSImm12(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm10(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm9Lsl3(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm11Lsl1(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm14Lsl2(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ bool selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, ++ SDValue &Offset) const; ++ ++ /// Select constant vector splats. ++ bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const; ++ /// Select constant vector splats whose value fits in a given integer. ++ bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, ++ unsigned ImmBitSize) const; ++ /// Select constant vector splats whose value fits in a uimm1. ++ bool selectVSplatUimm1(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm2. ++ bool selectVSplatUimm2(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm3. ++ bool selectVSplatUimm3(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm4. ++ bool selectVSplatUimm4(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm5. ++ bool selectVSplatUimm5(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm6. ++ bool selectVSplatUimm6(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a uimm8. ++ bool selectVSplatUimm8(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value fits in a simm5. ++ bool selectVSplatSimm5(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value is a power of 2. ++ bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value is the inverse of a ++ /// power of 2. ++ bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value is a run of set bits ++ /// ending at the most significant bit ++ bool selectVSplatMaskL(SDValue N, SDValue &Imm) const; ++ /// Select constant vector splats whose value is a run of set bits ++ /// starting at bit zero. ++ bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; ++ ++ void Select(SDNode *N) override; ++ ++ bool trySelect(SDNode *Node); ++ ++ // getImm - Return a target constant with the specified value. ++ inline SDValue getImm(const SDNode *Node, uint64_t Imm) { ++ return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0)); ++ } + +-// Include the pieces autogenerated from the target description. +-#include "LoongArchGenDAGISel.inc" ++ bool SelectInlineAsmMemoryOperand(const SDValue &Op, ++ unsigned ConstraintID, ++ std::vector &OutOps) override; + }; + +-} // end namespace llvm ++FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM, ++ CodeGenOpt::Level OptLevel); ++} + +-#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +index 93c886434..6b258813b 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +@@ -1,4 +1,4 @@ +-//=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ---===// ++//===- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,1094 +6,8213 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file defines the interfaces that LoongArch uses to lower LLVM code into +-// a selection DAG. ++// This file defines the interfaces that LoongArch uses to lower LLVM code into a ++// selection DAG. + // + //===----------------------------------------------------------------------===// + + #include "LoongArchISelLowering.h" +-#include "LoongArch.h" +-#include "LoongArchMachineFunctionInfo.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchInstPrinter.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "LoongArchCCState.h" ++#include "LoongArchInstrInfo.h" ++#include "LoongArchMachineFunction.h" + #include "LoongArchRegisterInfo.h" + #include "LoongArchSubtarget.h" + #include "LoongArchTargetMachine.h" +-#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "LoongArchTargetObjectFile.h" ++#include "llvm/ADT/APFloat.h" ++#include "llvm/ADT/APInt.h" ++#include "llvm/ADT/ArrayRef.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/Statistic.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/ADT/Triple.h" ++#include "llvm/CodeGen/CallingConvLower.h" ++#include "llvm/CodeGen/FunctionLoweringInfo.h" + #include "llvm/CodeGen/ISDOpcodes.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" ++#include "llvm/CodeGen/MachineFrameInfo.h" ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineJumpTableInfo.h" ++#include "llvm/CodeGen/MachineMemOperand.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/RuntimeLibcalls.h" ++#include "llvm/CodeGen/SelectionDAG.h" ++#include "llvm/CodeGen/SelectionDAGNodes.h" ++#include "llvm/CodeGen/TargetFrameLowering.h" ++#include "llvm/CodeGen/TargetInstrInfo.h" ++#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++#include "llvm/CodeGen/ValueTypes.h" ++#include "llvm/IR/CallingConv.h" ++#include "llvm/IR/Constants.h" ++#include "llvm/IR/DataLayout.h" ++#include "llvm/IR/DebugLoc.h" ++#include "llvm/IR/DerivedTypes.h" ++#include "llvm/IR/Function.h" ++#include "llvm/IR/GlobalValue.h" ++#include "llvm/IR/Intrinsics.h" ++#include "llvm/IR/IntrinsicsLoongArch.h" ++#include "llvm/IR/Type.h" ++#include "llvm/IR/Value.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/CodeGen.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Support/Compiler.h" + #include "llvm/Support/Debug.h" +-#include "llvm/Support/KnownBits.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MachineValueType.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Support/raw_ostream.h" ++#include "llvm/Target/TargetMachine.h" ++#include "llvm/Target/TargetOptions.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + + using namespace llvm; + +-#define DEBUG_TYPE "loongarch-isel-lowering" ++#define DEBUG_TYPE "loongarch-lower" + +-static cl::opt ZeroDivCheck( +- "loongarch-check-zero-division", cl::Hidden, +- cl::desc("Trap on integer division by zero."), +- cl::init(false)); ++STATISTIC(NumTailCalls, "Number of tail calls"); + +-LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, +- const LoongArchSubtarget &STI) +- : TargetLowering(TM), Subtarget(STI) { ++static cl::opt ++NoZeroDivCheck("mnocheck-zero-division", cl::Hidden, ++ cl::desc("LoongArch: Don't trap on integer division by zero."), ++ cl::init(false)); + +- MVT GRLenVT = Subtarget.getGRLenVT(); +- // Set up the register classes. +- addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); +- if (Subtarget.hasBasicF()) +- addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass); +- if (Subtarget.hasBasicD()) +- addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass); ++static const MCPhysReg LoongArch64DPRegs[8] = { ++ LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, ++ LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64 ++}; + +- setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT, +- MVT::i1, Promote); ++// If I is a shifted mask, set the size (SMSize) and the first bit of the ++// mask (SMLsb), and return true. ++// For example, if I is 0x003ff800, (SMLsb, SMSize) = (11, 11). ++static bool isShiftedMask(uint64_t I, uint64_t &SMLsb, uint64_t &SMSize) { ++ if (!isShiftedMask_64(I)) ++ return false; + +- // TODO: add necessary setOperationAction calls later. +- setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); +- setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); +- setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); +- setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); ++ SMSize = countPopulation(I); ++ SMLsb = countTrailingZeros(I); ++ return true; ++} + +- setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); ++SDValue LoongArchTargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty, ++ SelectionDAG &DAG, ++ unsigned Flag) const { ++ return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty, 0, Flag); ++} + +- if (Subtarget.is64Bit()) { +- setOperationAction(ISD::SHL, MVT::i32, Custom); +- setOperationAction(ISD::SRA, MVT::i32, Custom); +- setOperationAction(ISD::SRL, MVT::i32, Custom); +- setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); +- setOperationAction(ISD::BITCAST, MVT::i32, Custom); +- if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) +- setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); ++SDValue LoongArchTargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty, ++ SelectionDAG &DAG, ++ unsigned Flag) const { ++ return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag); ++} ++ ++SDValue LoongArchTargetLowering::getTargetNode(BlockAddressSDNode *N, EVT Ty, ++ SelectionDAG &DAG, ++ unsigned Flag) const { ++ return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(), Flag); ++} ++ ++SDValue LoongArchTargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty, ++ SelectionDAG &DAG, ++ unsigned Flag) const { ++ return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag); ++} ++ ++SDValue LoongArchTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, ++ SelectionDAG &DAG, ++ unsigned Flag) const { ++ return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(), ++ N->getOffset(), Flag); ++} ++ ++const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { ++ switch ((LoongArchISD::NodeType)Opcode) { ++ case LoongArchISD::FIRST_NUMBER: break; ++ case LoongArchISD::JmpLink: return "LoongArchISD::JmpLink"; ++ case LoongArchISD::TailCall: return "LoongArchISD::TailCall"; ++ case LoongArchISD::GlobalAddress: return "LoongArchISD::GlobalAddress"; ++ case LoongArchISD::Ret: return "LoongArchISD::Ret"; ++ case LoongArchISD::ERet: return "LoongArchISD::ERet"; ++ case LoongArchISD::EH_RETURN: return "LoongArchISD::EH_RETURN"; ++ case LoongArchISD::FPBrcond: return "LoongArchISD::FPBrcond"; ++ case LoongArchISD::FPCmp: return "LoongArchISD::FPCmp"; ++ case LoongArchISD::CMovFP_T: return "LoongArchISD::CMovFP_T"; ++ case LoongArchISD::CMovFP_F: return "LoongArchISD::CMovFP_F"; ++ case LoongArchISD::TruncIntFP: return "LoongArchISD::TruncIntFP"; ++ case LoongArchISD::DBAR: return "LoongArchISD::DBAR"; ++ case LoongArchISD::BSTRPICK: return "LoongArchISD::BSTRPICK"; ++ case LoongArchISD::BSTRINS: return "LoongArchISD::BSTRINS"; ++ case LoongArchISD::VALL_ZERO: ++ return "LoongArchISD::VALL_ZERO"; ++ case LoongArchISD::VANY_ZERO: ++ return "LoongArchISD::VANY_ZERO"; ++ case LoongArchISD::VALL_NONZERO: ++ return "LoongArchISD::VALL_NONZERO"; ++ case LoongArchISD::VANY_NONZERO: ++ return "LoongArchISD::VANY_NONZERO"; ++ case LoongArchISD::VEXTRACT_SEXT_ELT: ++ return "LoongArchISD::VEXTRACT_SEXT_ELT"; ++ case LoongArchISD::VEXTRACT_ZEXT_ELT: ++ return "LoongArchISD::VEXTRACT_ZEXT_ELT"; ++ case LoongArchISD::VNOR: ++ return "LoongArchISD::VNOR"; ++ case LoongArchISD::VSHF: ++ return "LoongArchISD::VSHF"; ++ case LoongArchISD::SHF: ++ return "LoongArchISD::SHF"; ++ case LoongArchISD::VPACKEV: ++ return "LoongArchISD::VPACKEV"; ++ case LoongArchISD::VPACKOD: ++ return "LoongArchISD::VPACKOD"; ++ case LoongArchISD::VILVH: ++ return "LoongArchISD::VILVH"; ++ case LoongArchISD::VILVL: ++ return "LoongArchISD::VILVL"; ++ case LoongArchISD::VPICKEV: ++ return "LoongArchISD::VPICKEV"; ++ case LoongArchISD::VPICKOD: ++ return "LoongArchISD::VPICKOD"; ++ case LoongArchISD::INSVE: ++ return "LoongArchISD::INSVE"; ++ case LoongArchISD::VROR: ++ return "LoongArchISD::VROR"; ++ case LoongArchISD::VRORI: ++ return "LoongArchISD::VRORI"; ++ case LoongArchISD::XVBROADCAST: ++ return "LoongArchISD::XVBROADCAST"; ++ case LoongArchISD::VBROADCAST: ++ return "LoongArchISD::VBROADCAST"; ++ case LoongArchISD::VABSD: ++ return "LoongArchISD::VABSD"; ++ case LoongArchISD::UVABSD: ++ return "LoongArchISD::UVABSD"; ++ case LoongArchISD::XVPICKVE: ++ return "LoongArchISD::XVPICKVE"; ++ case LoongArchISD::XVPERMI: ++ return "LoongArchISD::XVPERMI"; ++ case LoongArchISD::XVSHUF4I: ++ return "LoongArchISD::XVSHUF4I"; ++ case LoongArchISD::REVBD: ++ return "LoongArchISD::REVBD"; ++ case LoongArchISD::FSEL: ++ return "LoongArchISD::FSEL"; + } ++ return nullptr; ++} ++ ++LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &TM, ++ const LoongArchSubtarget &STI) ++ : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { ++ // Set up the register classes ++ addRegisterClass(MVT::i32, &LoongArch::GPR32RegClass); + +- static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE, +- ISD::SETUGT, ISD::SETUGE}; ++ if (Subtarget.is64Bit()) ++ addRegisterClass(MVT::i64, &LoongArch::GPR64RegClass); + +- if (Subtarget.hasBasicF()) { +- setCondCodeAction(FPCCToExpand, MVT::f32, Expand); +- setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); ++ // LoongArch does not have i1 type, so use i32 for ++ // setcc operations results (slt, sgt, ...). ++ setBooleanContents(ZeroOrOneBooleanContent); ++ setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); ++ ++ // Load extented operations for i1 types must be promoted ++ for (MVT VT : MVT::integer_valuetypes()) { ++ setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); ++ setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); ++ setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); + } +- if (Subtarget.hasBasicD()) { +- setCondCodeAction(FPCCToExpand, MVT::f64, Expand); +- setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); +- setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); +- setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); ++ ++ // LoongArch doesn't have extending float->double load/store. Set LoadExtAction ++ // for f32, f16 ++ for (MVT VT : MVT::fp_valuetypes()) { ++ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); ++ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); + } + +- setOperationAction(ISD::BR_CC, GRLenVT, Expand); +- setOperationAction(ISD::SELECT_CC, GRLenVT, Expand); +- setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); +- setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, GRLenVT, Expand); +- if (!Subtarget.is64Bit()) +- setLibcallName(RTLIB::MUL_I128, nullptr); ++ // Set LoadExtAction for f16 vectors to Expand ++ for (MVT VT : MVT::fp_fixedlen_vector_valuetypes()) { ++ MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements()); ++ if (F16VT.isValid()) ++ setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand); ++ } + +- setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom); +- setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom); ++ setTruncStoreAction(MVT::f32, MVT::f16, Expand); ++ setTruncStoreAction(MVT::f64, MVT::f16, Expand); ++ ++ setTruncStoreAction(MVT::f64, MVT::f32, Expand); ++ ++ // Used by legalize types to correctly generate the setcc result. ++ // Without this, every float setcc comes with a AND/OR with the result, ++ // we don't want this, since the fpcmp result goes to a flag register, ++ // which is used implicitly by brcond and select operations. ++ AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); ++ ++ // LoongArch Custom Operations ++ setOperationAction(ISD::BR_JT, MVT::Other, Expand); ++ setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); ++ setOperationAction(ISD::BlockAddress, MVT::i32, Custom); ++ setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); ++ setOperationAction(ISD::JumpTable, MVT::i32, Custom); ++ setOperationAction(ISD::ConstantPool, MVT::i32, Custom); ++ setOperationAction(ISD::SELECT, MVT::f32, Custom); ++ setOperationAction(ISD::SELECT, MVT::f64, Custom); ++ setOperationAction(ISD::SELECT, MVT::i32, Custom); ++ setOperationAction(ISD::SETCC, MVT::f32, Custom); ++ setOperationAction(ISD::SETCC, MVT::f64, Custom); ++ setOperationAction(ISD::BRCOND, MVT::Other, Custom); ++ setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + +- // Compute derived properties from the register classes. +- computeRegisterProperties(STI.getRegisterInfo()); ++ if (Subtarget.is64Bit()) { ++ setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); ++ setOperationAction(ISD::BlockAddress, MVT::i64, Custom); ++ setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); ++ setOperationAction(ISD::JumpTable, MVT::i64, Custom); ++ setOperationAction(ISD::ConstantPool, MVT::i64, Custom); ++ setOperationAction(ISD::SELECT, MVT::i64, Custom); ++ setOperationAction(ISD::LOAD, MVT::i64, Legal); ++ setOperationAction(ISD::STORE, MVT::i64, Legal); ++ setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); ++ setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); ++ setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); ++ setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); ++ } + +- setStackPointerRegisterToSaveRestore(LoongArch::R3); ++ if (!Subtarget.is64Bit()) { ++ setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); ++ setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); ++ setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); ++ } + +- setBooleanContents(ZeroOrOneBooleanContent); ++ setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom); ++ if (Subtarget.is64Bit()) ++ setOperationAction(ISD::EH_DWARF_CFA, MVT::i64, Custom); ++ ++ setOperationAction(ISD::SDIV, MVT::i32, Expand); ++ setOperationAction(ISD::SREM, MVT::i32, Expand); ++ setOperationAction(ISD::UDIV, MVT::i32, Expand); ++ setOperationAction(ISD::UREM, MVT::i32, Expand); ++ setOperationAction(ISD::SDIV, MVT::i64, Expand); ++ setOperationAction(ISD::SREM, MVT::i64, Expand); ++ setOperationAction(ISD::UDIV, MVT::i64, Expand); ++ setOperationAction(ISD::UREM, MVT::i64, Expand); ++ ++ // Operations not directly supported by LoongArch. ++ setOperationAction(ISD::BR_CC, MVT::f32, Expand); ++ setOperationAction(ISD::BR_CC, MVT::f64, Expand); ++ setOperationAction(ISD::BR_CC, MVT::i32, Expand); ++ setOperationAction(ISD::BR_CC, MVT::i64, Expand); ++ setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); ++ setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); ++ setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); ++ setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); ++ setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); ++ setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); ++ setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); ++ setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); ++ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); ++ setOperationAction(ISD::CTPOP, MVT::i32, Expand); ++ setOperationAction(ISD::CTPOP, MVT::i64, Expand); ++ setOperationAction(ISD::ROTL, MVT::i32, Expand); ++ setOperationAction(ISD::ROTL, MVT::i64, Expand); ++ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); ++ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); ++ ++ setOperationAction(ISD::FSIN, MVT::f32, Expand); ++ setOperationAction(ISD::FSIN, MVT::f64, Expand); ++ setOperationAction(ISD::FCOS, MVT::f32, Expand); ++ setOperationAction(ISD::FCOS, MVT::f64, Expand); ++ setOperationAction(ISD::FSINCOS, MVT::f32, Expand); ++ setOperationAction(ISD::FSINCOS, MVT::f64, Expand); ++ setOperationAction(ISD::FPOW, MVT::f32, Expand); ++ setOperationAction(ISD::FPOW, MVT::f64, Expand); ++ setOperationAction(ISD::FLOG, MVT::f32, Expand); ++ setOperationAction(ISD::FRINT, MVT::f32, Legal); ++ setOperationAction(ISD::FRINT, MVT::f64, Legal); ++ ++ setOperationAction(ISD::FLOG10, MVT::f32, Expand); ++ setOperationAction(ISD::FEXP, MVT::f32, Expand); ++ setOperationAction(ISD::FMA, MVT::f32, Legal); ++ setOperationAction(ISD::FMA, MVT::f64, Legal); ++ setOperationAction(ISD::FREM, MVT::f32, Expand); ++ setOperationAction(ISD::FREM, MVT::f64, Expand); ++ ++ setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal); ++ setOperationAction(ISD::FMINNUM_IEEE, MVT::f64, Legal); ++ setOperationAction(ISD::FMAXNUM_IEEE, MVT::f32, Legal); ++ setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal); ++ ++ // Lower f16 conversion operations into library calls ++ setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); ++ setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); ++ setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); ++ setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); ++ ++ setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); ++ ++ setOperationAction(ISD::VASTART, MVT::Other, Custom); ++ setOperationAction(ISD::VAARG, MVT::Other, Custom); ++ setOperationAction(ISD::VACOPY, MVT::Other, Expand); ++ setOperationAction(ISD::VAEND, MVT::Other, Expand); ++ ++ // Use the default for now ++ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); ++ setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); ++ ++ if (!Subtarget.is64Bit()) { ++ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); ++ setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); ++ } + +- setMaxAtomicSizeInBitsSupported(Subtarget.getGRLen()); ++ if (Subtarget.is64Bit()) { ++ setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); ++ setTruncStoreAction(MVT::i64, MVT::i32, Custom); ++ } + +- // Function alignments. +- const Align FunctionAlignment(4); +- setMinFunctionAlignment(FunctionAlignment); ++ setOperationAction(ISD::TRAP, MVT::Other, Legal); ++ setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); ++ setOperationAction(ISD::BITREVERSE, MVT::i64, Legal); + ++ setTargetDAGCombine(ISD::SELECT); + setTargetDAGCombine(ISD::AND); + setTargetDAGCombine(ISD::OR); ++ setTargetDAGCombine(ISD::AssertZext); ++ setTargetDAGCombine(ISD::SHL); ++ setTargetDAGCombine(ISD::SIGN_EXTEND); ++ setTargetDAGCombine(ISD::ZERO_EXTEND); ++ setTargetDAGCombine(ISD::ADD); ++ setTargetDAGCombine(ISD::SUB); ++ setTargetDAGCombine(ISD::MUL); + setTargetDAGCombine(ISD::SRL); +-} ++ setTargetDAGCombine(ISD::SRA); + +-SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, +- SelectionDAG &DAG) const { +- switch (Op.getOpcode()) { +- default: +- report_fatal_error("unimplemented operand"); +- case ISD::GlobalAddress: +- return lowerGlobalAddress(Op, DAG); +- case ISD::SHL_PARTS: +- return lowerShiftLeftParts(Op, DAG); +- case ISD::SRA_PARTS: +- return lowerShiftRightParts(Op, DAG, true); +- case ISD::SRL_PARTS: +- return lowerShiftRightParts(Op, DAG, false); +- case ISD::SHL: +- case ISD::SRA: +- case ISD::SRL: +- // This can be called for an i32 shift amount that needs to be promoted. +- assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && +- "Unexpected custom legalisation"); +- return SDValue(); +- case ISD::ConstantPool: +- return lowerConstantPool(Op, DAG); +- case ISD::FP_TO_SINT: +- return lowerFP_TO_SINT(Op, DAG); +- case ISD::BITCAST: +- return lowerBITCAST(Op, DAG); +- case ISD::FP_TO_UINT: +- return SDValue(); +- case ISD::UINT_TO_FP: +- return lowerUINT_TO_FP(Op, DAG); ++ if (ABI.IsLP32()) { ++ // These libcalls are not available in 32-bit. ++ setLibcallName(RTLIB::SHL_I128, nullptr); ++ setLibcallName(RTLIB::SRL_I128, nullptr); ++ setLibcallName(RTLIB::SRA_I128, nullptr); + } +-} + +-SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, +- SelectionDAG &DAG) const { ++ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { ++ // Expand all truncating stores and extending loads. ++ for (MVT VT0 : MVT::vector_valuetypes()) { ++ for (MVT VT1 : MVT::vector_valuetypes()) { ++ setTruncStoreAction(VT0, VT1, Expand); ++ setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand); ++ setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand); ++ setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand); ++ } ++ } ++ } + +- SDLoc DL(Op); +- auto &TLI = DAG.getTargetLoweringInfo(); +- SDValue Tmp1, Tmp2; +- SDValue Op1 = Op.getOperand(0); +- if (Op1->getOpcode() == ISD::AssertZext || +- Op1->getOpcode() == ISD::AssertSext) +- return Op; +- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0)); +- SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc); +- SDNode *N = Res.getNode(); +- TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG); +- return Tmp1; +-} ++ if (Subtarget.hasLSX()) { ++ addLSXIntType(MVT::v16i8, &LoongArch::LSX128BRegClass); ++ addLSXIntType(MVT::v8i16, &LoongArch::LSX128HRegClass); ++ addLSXIntType(MVT::v4i32, &LoongArch::LSX128WRegClass); ++ addLSXIntType(MVT::v2i64, &LoongArch::LSX128DRegClass); ++ addLSXFloatType(MVT::v4f32, &LoongArch::LSX128WRegClass); ++ addLSXFloatType(MVT::v2f64, &LoongArch::LSX128DRegClass); ++ ++ // f16 is a storage-only type, always promote it to f32. ++ setOperationAction(ISD::SETCC, MVT::f16, Promote); ++ setOperationAction(ISD::BR_CC, MVT::f16, Promote); ++ setOperationAction(ISD::SELECT_CC, MVT::f16, Promote); ++ setOperationAction(ISD::SELECT, MVT::f16, Promote); ++ setOperationAction(ISD::FADD, MVT::f16, Promote); ++ setOperationAction(ISD::FSUB, MVT::f16, Promote); ++ setOperationAction(ISD::FMUL, MVT::f16, Promote); ++ setOperationAction(ISD::FDIV, MVT::f16, Promote); ++ setOperationAction(ISD::FREM, MVT::f16, Promote); ++ setOperationAction(ISD::FMA, MVT::f16, Promote); ++ setOperationAction(ISD::FNEG, MVT::f16, Promote); ++ setOperationAction(ISD::FABS, MVT::f16, Promote); ++ setOperationAction(ISD::FCEIL, MVT::f16, Promote); ++ setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote); ++ setOperationAction(ISD::FCOS, MVT::f16, Promote); ++ setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote); ++ setOperationAction(ISD::FFLOOR, MVT::f16, Promote); ++ setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote); ++ setOperationAction(ISD::FPOW, MVT::f16, Promote); ++ setOperationAction(ISD::FPOWI, MVT::f16, Promote); ++ setOperationAction(ISD::FRINT, MVT::f16, Promote); ++ setOperationAction(ISD::FSIN, MVT::f16, Promote); ++ setOperationAction(ISD::FSINCOS, MVT::f16, Promote); ++ setOperationAction(ISD::FSQRT, MVT::f16, Promote); ++ setOperationAction(ISD::FEXP, MVT::f16, Promote); ++ setOperationAction(ISD::FEXP2, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG2, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG10, MVT::f16, Promote); ++ setOperationAction(ISD::FROUND, MVT::f16, Promote); ++ setOperationAction(ISD::FTRUNC, MVT::f16, Promote); ++ setOperationAction(ISD::FMINNUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMAXNUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMINIMUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote); ++ ++ setTargetDAGCombine(ISD::AND); ++ setTargetDAGCombine(ISD::OR); ++ setTargetDAGCombine(ISD::SRA); ++ setTargetDAGCombine(ISD::VSELECT); ++ setTargetDAGCombine(ISD::XOR); ++ } + +-SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op, +- SelectionDAG &DAG) const { ++ if (Subtarget.hasLASX()) { ++ addLASXIntType(MVT::v32i8, &LoongArch::LASX256BRegClass); ++ addLASXIntType(MVT::v16i16, &LoongArch::LASX256HRegClass); ++ addLASXIntType(MVT::v8i32, &LoongArch::LASX256WRegClass); ++ addLASXIntType(MVT::v4i64, &LoongArch::LASX256DRegClass); ++ addLASXFloatType(MVT::v8f32, &LoongArch::LASX256WRegClass); ++ addLASXFloatType(MVT::v4f64, &LoongArch::LASX256DRegClass); ++ ++ // f16 is a storage-only type, always promote it to f32. ++ setOperationAction(ISD::SETCC, MVT::f16, Promote); ++ setOperationAction(ISD::BR_CC, MVT::f16, Promote); ++ setOperationAction(ISD::SELECT_CC, MVT::f16, Promote); ++ setOperationAction(ISD::SELECT, MVT::f16, Promote); ++ setOperationAction(ISD::FADD, MVT::f16, Promote); ++ setOperationAction(ISD::FSUB, MVT::f16, Promote); ++ setOperationAction(ISD::FMUL, MVT::f16, Promote); ++ setOperationAction(ISD::FDIV, MVT::f16, Promote); ++ setOperationAction(ISD::FREM, MVT::f16, Promote); ++ setOperationAction(ISD::FMA, MVT::f16, Promote); ++ setOperationAction(ISD::FNEG, MVT::f16, Promote); ++ setOperationAction(ISD::FABS, MVT::f16, Promote); ++ setOperationAction(ISD::FCEIL, MVT::f16, Promote); ++ setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote); ++ setOperationAction(ISD::FCOS, MVT::f16, Promote); ++ setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote); ++ setOperationAction(ISD::FFLOOR, MVT::f16, Promote); ++ setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote); ++ setOperationAction(ISD::FPOW, MVT::f16, Promote); ++ setOperationAction(ISD::FPOWI, MVT::f16, Promote); ++ setOperationAction(ISD::FRINT, MVT::f16, Promote); ++ setOperationAction(ISD::FSIN, MVT::f16, Promote); ++ setOperationAction(ISD::FSINCOS, MVT::f16, Promote); ++ setOperationAction(ISD::FSQRT, MVT::f16, Promote); ++ setOperationAction(ISD::FEXP, MVT::f16, Promote); ++ setOperationAction(ISD::FEXP2, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG2, MVT::f16, Promote); ++ setOperationAction(ISD::FLOG10, MVT::f16, Promote); ++ setOperationAction(ISD::FROUND, MVT::f16, Promote); ++ setOperationAction(ISD::FTRUNC, MVT::f16, Promote); ++ setOperationAction(ISD::FMINNUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMAXNUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMINIMUM, MVT::f16, Promote); ++ setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote); ++ ++ setTargetDAGCombine(ISD::AND); ++ setTargetDAGCombine(ISD::OR); ++ setTargetDAGCombine(ISD::SRA); ++ setTargetDAGCombine(ISD::VSELECT); ++ setTargetDAGCombine(ISD::XOR); ++ } + +- SDLoc DL(Op); +- SDValue Op0 = Op.getOperand(0); ++ if (!Subtarget.useSoftFloat()) { ++ addRegisterClass(MVT::f32, &LoongArch::FGR32RegClass); + +- if (Op.getValueType() == MVT::f32 && Op0.getValueType() == MVT::i32 && +- Subtarget.is64Bit() && Subtarget.hasBasicF()) { +- SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0); +- return DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, NewOp0); ++ // When dealing with single precision only, use libcalls ++ if (!Subtarget.isSingleFloat()) { ++ if (Subtarget.isFP64bit()) ++ addRegisterClass(MVT::f64, &LoongArch::FGR64RegClass); ++ } + } +- return Op; +-} + +-SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, +- SelectionDAG &DAG) const { ++ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); ++ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); + +- SDLoc DL(Op); ++ if (Subtarget.is64Bit()) ++ setOperationAction(ISD::MUL, MVT::i64, Custom); ++ ++ if (Subtarget.is64Bit()) { ++ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); ++ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); ++ setOperationAction(ISD::SDIVREM, MVT::i64, Custom); ++ setOperationAction(ISD::UDIVREM, MVT::i64, Custom); ++ } + +- if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() && +- !Subtarget.hasBasicD()) { +- SDValue Dst = +- DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op.getOperand(0)); +- return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst); ++ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); ++ setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); ++ ++ setOperationAction(ISD::SDIVREM, MVT::i32, Custom); ++ setOperationAction(ISD::UDIVREM, MVT::i32, Custom); ++ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); ++ setOperationAction(ISD::LOAD, MVT::i32, Legal); ++ setOperationAction(ISD::STORE, MVT::i32, Legal); ++ ++ setTargetDAGCombine(ISD::MUL); ++ ++ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); ++ setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); ++ setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); ++ ++ // Replace the accumulator-based multiplies with a ++ // three register instruction. ++ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); ++ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); ++ setOperationAction(ISD::MUL, MVT::i32, Legal); ++ setOperationAction(ISD::MULHS, MVT::i32, Legal); ++ setOperationAction(ISD::MULHU, MVT::i32, Legal); ++ ++ // Replace the accumulator-based division/remainder with separate ++ // three register division and remainder instructions. ++ setOperationAction(ISD::SDIVREM, MVT::i32, Expand); ++ setOperationAction(ISD::UDIVREM, MVT::i32, Expand); ++ setOperationAction(ISD::SDIV, MVT::i32, Legal); ++ setOperationAction(ISD::UDIV, MVT::i32, Legal); ++ setOperationAction(ISD::SREM, MVT::i32, Legal); ++ setOperationAction(ISD::UREM, MVT::i32, Legal); ++ ++ // Replace the accumulator-based multiplies with a ++ // three register instruction. ++ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); ++ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); ++ setOperationAction(ISD::MUL, MVT::i64, Legal); ++ setOperationAction(ISD::MULHS, MVT::i64, Legal); ++ setOperationAction(ISD::MULHU, MVT::i64, Legal); ++ ++ // Replace the accumulator-based division/remainder with separate ++ // three register division and remainder instructions. ++ setOperationAction(ISD::SDIVREM, MVT::i64, Expand); ++ setOperationAction(ISD::UDIVREM, MVT::i64, Expand); ++ setOperationAction(ISD::SDIV, MVT::i64, Legal); ++ setOperationAction(ISD::UDIV, MVT::i64, Legal); ++ setOperationAction(ISD::SREM, MVT::i64, Legal); ++ setOperationAction(ISD::UREM, MVT::i64, Legal); ++ ++ MaxGluedStoresPerMemcpy = 4; ++ ++ setMinFunctionAlignment(Align(4)); ++ ++ // The arguments on the stack are defined in terms of 4-byte slots on LP32 ++ // and 8-byte slots on LPX32/LP64. ++ setMinStackArgumentAlignment((ABI.IsLPX32() || ABI.IsLP64()) ? Align(8) ++ : Align(4)); ++ ++ setStackPointerRegisterToSaveRestore(ABI.IsLP64() ? LoongArch::SP_64 : LoongArch::SP); ++ ++ if (Subtarget.hasLASX()) { ++ // = 16*32/2; the smallest memcpy; ++ MaxStoresPerMemcpy = 16; ++ } else if (Subtarget.hasLSX()) { ++ MaxStoresPerMemcpy = 65535; ++ } else { ++ MaxStoresPerMemcpy = 16; + } + +- EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); +- SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op.getOperand(0)); +- return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc); ++ computeRegisterProperties(Subtarget.getRegisterInfo()); + } + +-SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op, +- SelectionDAG &DAG) const { +- SDLoc DL(Op); +- EVT Ty = Op.getValueType(); +- ConstantPoolSDNode *N = cast(Op); ++// Enable LSX support for the given integer type and Register class. ++void LoongArchTargetLowering::addLSXIntType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC) { ++ addRegisterClass(Ty, RC); ++ ++ // Expand all builtin opcodes. ++ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) ++ setOperationAction(Opc, Ty, Expand); ++ ++ setOperationAction(ISD::BITCAST, Ty, Legal); ++ setOperationAction(ISD::LOAD, Ty, Legal); ++ setOperationAction(ISD::STORE, Ty, Legal); ++ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom); ++ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); ++ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); ++ setOperationAction(ISD::ABS, Ty, Legal); ++ setOperationAction(ISD::UNDEF, Ty, Legal); ++ setOperationAction(ISD::EXTRACT_SUBVECTOR, Ty, Legal); ++ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); ++ ++ if (Ty == MVT::v4i32 || Ty == MVT::v2i64) { ++ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); ++ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); ++ } + +- // FIXME: Only support PC-relative addressing to access the symbol. +- // Target flags will be added later. +- if (!isPositionIndependent()) { +- SDValue ConstantN = DAG.getTargetConstantPool( +- N->getConstVal(), Ty, N->getAlign(), N->getOffset()); +- SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN), +- 0); +- SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D +- : LoongArch::ADDI_W, +- DL, Ty, AddrHi, ConstantN), +- 0); +- return Addr; ++ setOperationAction(ISD::ADD, Ty, Legal); ++ setOperationAction(ISD::AND, Ty, Legal); ++ setOperationAction(ISD::CTLZ, Ty, Legal); ++ setOperationAction(ISD::CTPOP, Ty, Legal); ++ setOperationAction(ISD::MUL, Ty, Legal); ++ setOperationAction(ISD::OR, Ty, Legal); ++ setOperationAction(ISD::SDIV, Ty, Legal); ++ setOperationAction(ISD::SREM, Ty, Legal); ++ setOperationAction(ISD::SHL, Ty, Legal); ++ setOperationAction(ISD::SRA, Ty, Legal); ++ setOperationAction(ISD::SRL, Ty, Legal); ++ setOperationAction(ISD::SUB, Ty, Legal); ++ setOperationAction(ISD::SMAX, Ty, Legal); ++ setOperationAction(ISD::SMIN, Ty, Legal); ++ setOperationAction(ISD::UDIV, Ty, Legal); ++ setOperationAction(ISD::UREM, Ty, Legal); ++ setOperationAction(ISD::UMAX, Ty, Legal); ++ setOperationAction(ISD::UMIN, Ty, Legal); ++ setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); ++ setOperationAction(ISD::VSELECT, Ty, Legal); ++ setOperationAction(ISD::XOR, Ty, Legal); ++ setOperationAction(ISD::MULHS, Ty, Legal); ++ setOperationAction(ISD::MULHU, Ty, Legal); ++ ++ if (Ty == MVT::v4i32 || Ty == MVT::v2i64) { ++ setOperationAction(ISD::SINT_TO_FP, Ty, Custom); ++ setOperationAction(ISD::UINT_TO_FP, Ty, Custom); + } +- report_fatal_error("Unable to lower ConstantPool"); +-} + +-SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, +- SelectionDAG &DAG) const { +- SDLoc DL(Op); +- EVT Ty = getPointerTy(DAG.getDataLayout()); +- const GlobalValue *GV = cast(Op)->getGlobal(); +- unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ setOperationAction(ISD::SETCC, Ty, Legal); ++ setCondCodeAction(ISD::SETNE, Ty, Expand); ++ setCondCodeAction(ISD::SETGE, Ty, Expand); ++ setCondCodeAction(ISD::SETGT, Ty, Expand); ++ setCondCodeAction(ISD::SETUGE, Ty, Expand); ++ setCondCodeAction(ISD::SETUGT, Ty, Expand); ++} + +- // TODO: Support dso_preemptable and target flags. +- if (GV->isDSOLocal()) { +- SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty); +- SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0); +- SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0); +- return Addr; ++// Enable LASX support for the given integer type and Register class. ++void LoongArchTargetLowering::addLASXIntType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC) { ++ addRegisterClass(Ty, RC); ++ ++ // Expand all builtin opcodes. ++ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) ++ setOperationAction(Opc, Ty, Expand); ++ ++ // FIXME ++ setOperationAction(ISD::BITCAST, Ty, Legal); ++ setOperationAction(ISD::LOAD, Ty, Legal); ++ setOperationAction(ISD::STORE, Ty, Legal); ++ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom); ++ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Custom); ++ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); ++ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); ++ setOperationAction(ISD::UNDEF, Ty, Legal); ++ setOperationAction(ISD::UADDSAT, Ty, Legal); ++ setOperationAction(ISD::SADDSAT, Ty, Legal); ++ setOperationAction(ISD::USUBSAT, Ty, Legal); ++ setOperationAction(ISD::SSUBSAT, Ty, Legal); ++ setOperationAction(ISD::ABS, Ty, Legal); ++ ++ setOperationAction(ISD::ADD, Ty, Legal); ++ setOperationAction(ISD::AND, Ty, Legal); ++ setOperationAction(ISD::CTLZ, Ty, Legal); ++ setOperationAction(ISD::CTPOP, Ty, Legal); ++ setOperationAction(ISD::MUL, Ty, Legal); ++ setOperationAction(ISD::OR, Ty, Legal); ++ setOperationAction(ISD::SDIV, Ty, Legal); ++ setOperationAction(ISD::SREM, Ty, Legal); ++ setOperationAction(ISD::SHL, Ty, Legal); ++ setOperationAction(ISD::SRA, Ty, Legal); ++ setOperationAction(ISD::SRL, Ty, Legal); ++ setOperationAction(ISD::SUB, Ty, Legal); ++ setOperationAction(ISD::SMAX, Ty, Legal); ++ setOperationAction(ISD::SMIN, Ty, Legal); ++ setOperationAction(ISD::UDIV, Ty, Legal); ++ setOperationAction(ISD::UREM, Ty, Legal); ++ setOperationAction(ISD::UMAX, Ty, Legal); ++ setOperationAction(ISD::UMIN, Ty, Legal); ++ setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); ++ setOperationAction(ISD::VSELECT, Ty, Legal); ++ setOperationAction(ISD::XOR, Ty, Legal); ++ setOperationAction(ISD::INSERT_SUBVECTOR, Ty, Legal); ++ setOperationAction(ISD::MULHS, Ty, Legal); ++ setOperationAction(ISD::MULHU, Ty, Legal); ++ ++ setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, Ty, Legal); ++ setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, Ty, Legal); ++ ++ setOperationAction(ISD::SIGN_EXTEND, Ty, Legal); ++ setOperationAction(ISD::ZERO_EXTEND, Ty, Legal); ++ ++ if (Ty == MVT::v8i32 || Ty == MVT::v4i64) { ++ setOperationAction(ISD::SINT_TO_FP, Ty, Custom); ++ setOperationAction(ISD::UINT_TO_FP, Ty, Custom); + } +- report_fatal_error("Unable to lowerGlobalAddress"); ++ ++ setTargetDAGCombine(ISD::CONCAT_VECTORS); ++ ++ setOperationAction(ISD::SETCC, Ty, Legal); ++ setCondCodeAction(ISD::SETNE, Ty, Expand); ++ setCondCodeAction(ISD::SETGE, Ty, Expand); ++ setCondCodeAction(ISD::SETGT, Ty, Expand); ++ setCondCodeAction(ISD::SETUGE, Ty, Expand); ++ setCondCodeAction(ISD::SETUGT, Ty, Expand); + } + +-SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, +- SelectionDAG &DAG) const { +- SDLoc DL(Op); +- SDValue Lo = Op.getOperand(0); +- SDValue Hi = Op.getOperand(1); +- SDValue Shamt = Op.getOperand(2); +- EVT VT = Lo.getValueType(); ++// Enable LSX support for the given floating-point type and Register class. ++void LoongArchTargetLowering::addLSXFloatType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC) { ++ addRegisterClass(Ty, RC); ++ ++ // Expand all builtin opcodes. ++ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) ++ setOperationAction(Opc, Ty, Expand); ++ ++ setOperationAction(ISD::LOAD, Ty, Legal); ++ setOperationAction(ISD::STORE, Ty, Legal); ++ setOperationAction(ISD::BITCAST, Ty, Legal); ++ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal); ++ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); ++ setOperationAction(ISD::UNDEF, Ty, Legal); ++ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); ++ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); ++ ++ if (Ty == MVT::v4f32 || Ty == MVT::v2f64) { ++ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); ++ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); ++ } + +- // if Shamt-GRLen < 0: // Shamt < GRLen +- // Lo = Lo << Shamt +- // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt)) +- // else: +- // Lo = 0 +- // Hi = Lo << (Shamt-GRLen) +- +- SDValue Zero = DAG.getConstant(0, DL, VT); +- SDValue One = DAG.getConstant(1, DL, VT); +- SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); +- SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); +- SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); +- SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); +- +- SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); +- SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); +- SDValue ShiftRightLo = +- DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt); +- SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); +- SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); +- SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen); ++ setOperationAction(ISD::FADD, Ty, Legal); ++ setOperationAction(ISD::FDIV, Ty, Legal); ++ setOperationAction(ISD::FMA, Ty, Legal); ++ setOperationAction(ISD::FMUL, Ty, Legal); ++ setOperationAction(ISD::FSQRT, Ty, Legal); ++ setOperationAction(ISD::FSUB, Ty, Legal); ++ setOperationAction(ISD::VSELECT, Ty, Legal); ++ setOperationAction(ISD::FNEG, Ty, Legal); ++ setOperationAction(ISD::FRINT, Ty, Legal); ++ ++ setOperationAction(ISD::SETCC, Ty, Legal); ++ setCondCodeAction(ISD::SETOGE, Ty, Expand); ++ setCondCodeAction(ISD::SETOGT, Ty, Expand); ++ setCondCodeAction(ISD::SETUGE, Ty, Expand); ++ setCondCodeAction(ISD::SETUGT, Ty, Expand); ++ setCondCodeAction(ISD::SETGE, Ty, Expand); ++ setCondCodeAction(ISD::SETGT, Ty, Expand); ++} + +- SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); ++// Enable LASX support for the given floating-point type and Register class. ++void LoongArchTargetLowering::addLASXFloatType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC) { ++ addRegisterClass(Ty, RC); ++ ++ // Expand all builtin opcodes. ++ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) ++ setOperationAction(Opc, Ty, Expand); ++ ++ setOperationAction(ISD::LOAD, Ty, Legal); ++ setOperationAction(ISD::STORE, Ty, Legal); ++ setOperationAction(ISD::BITCAST, Ty, Legal); ++ setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal); ++ setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); ++ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); ++ setOperationAction(ISD::UNDEF, Ty, Legal); ++ setOperationAction(ISD::CONCAT_VECTORS, Ty, Legal); ++ ++ setOperationAction(ISD::FADD, Ty, Legal); ++ setOperationAction(ISD::FDIV, Ty, Legal); ++ setOperationAction(ISD::FMA, Ty, Legal); ++ setOperationAction(ISD::FMUL, Ty, Legal); ++ setOperationAction(ISD::FSQRT, Ty, Legal); ++ setOperationAction(ISD::FSUB, Ty, Legal); ++ setOperationAction(ISD::VSELECT, Ty, Legal); ++ setOperationAction(ISD::FNEG, Ty, Legal); ++ setOperationAction(ISD::FRINT, Ty, Legal); ++ ++ if (Ty == MVT::v8f32 || Ty == MVT::v4f64) { ++ setOperationAction(ISD::FP_TO_SINT, Ty, Custom); ++ setOperationAction(ISD::FP_TO_UINT, Ty, Custom); ++ } + +- Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); +- Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); ++ setOperationAction(ISD::SETCC, Ty, Legal); ++ setCondCodeAction(ISD::SETOGE, Ty, Expand); ++ setCondCodeAction(ISD::SETOGT, Ty, Expand); ++ setCondCodeAction(ISD::SETUGE, Ty, Expand); ++ setCondCodeAction(ISD::SETUGT, Ty, Expand); ++ setCondCodeAction(ISD::SETGE, Ty, Expand); ++ setCondCodeAction(ISD::SETGT, Ty, Expand); ++} + +- SDValue Parts[2] = {Lo, Hi}; +- return DAG.getMergeValues(Parts, DL); ++bool LoongArchTargetLowering::allowsMisalignedMemoryAccesses( ++ EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, ++ bool *Fast) const { ++ if (!Subtarget.allowUnalignedAccess()) ++ return false; ++ if (Fast) ++ *Fast = true; ++ return true; + } + +-SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, +- SelectionDAG &DAG, +- bool IsSRA) const { +- SDLoc DL(Op); +- SDValue Lo = Op.getOperand(0); +- SDValue Hi = Op.getOperand(1); +- SDValue Shamt = Op.getOperand(2); +- EVT VT = Lo.getValueType(); +- +- // SRA expansion: +- // if Shamt-GRLen < 0: // Shamt < GRLen +- // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) +- // Hi = Hi >>s Shamt +- // else: +- // Lo = Hi >>s (Shamt-GRLen); +- // Hi = Hi >>s (GRLen-1) +- // +- // SRL expansion: +- // if Shamt-GRLen < 0: // Shamt < GRLen +- // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) +- // Hi = Hi >>u Shamt +- // else: +- // Lo = Hi >>u (Shamt-GRLen); +- // Hi = 0; +- +- unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; +- +- SDValue Zero = DAG.getConstant(0, DL, VT); +- SDValue One = DAG.getConstant(1, DL, VT); +- SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); +- SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); +- SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); +- SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); ++EVT LoongArchTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, ++ EVT VT) const { ++ if (!VT.isVector()) ++ return MVT::i32; ++ return VT.changeVectorElementTypeToInteger(); ++} + +- SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); +- SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); +- SDValue ShiftLeftHi = +- DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt); +- SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); +- SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); +- SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen); +- SDValue HiFalse = +- IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero; ++static LoongArch::CondCode condCodeToFCC(ISD::CondCode CC) { ++ switch (CC) { ++ default: llvm_unreachable("Unknown fp condition code!"); ++ case ISD::SETEQ: ++ case ISD::SETOEQ: return LoongArch::FCOND_OEQ; ++ case ISD::SETUNE: return LoongArch::FCOND_UNE; ++ case ISD::SETLT: ++ case ISD::SETOLT: return LoongArch::FCOND_OLT; ++ case ISD::SETGT: ++ case ISD::SETOGT: return LoongArch::FCOND_OGT; ++ case ISD::SETLE: ++ case ISD::SETOLE: return LoongArch::FCOND_OLE; ++ case ISD::SETGE: ++ case ISD::SETOGE: return LoongArch::FCOND_OGE; ++ case ISD::SETULT: return LoongArch::FCOND_ULT; ++ case ISD::SETULE: return LoongArch::FCOND_ULE; ++ case ISD::SETUGT: return LoongArch::FCOND_UGT; ++ case ISD::SETUGE: return LoongArch::FCOND_UGE; ++ case ISD::SETUO: return LoongArch::FCOND_UN; ++ case ISD::SETO: return LoongArch::FCOND_OR; ++ case ISD::SETNE: ++ case ISD::SETONE: return LoongArch::FCOND_ONE; ++ case ISD::SETUEQ: return LoongArch::FCOND_UEQ; ++ } ++} + +- SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); ++/// This function returns true if the floating point conditional branches and ++/// conditional moves which use condition code CC should be inverted. ++static bool invertFPCondCodeUser(LoongArch::CondCode CC) { ++ if (CC >= LoongArch::FCOND_F && CC <= LoongArch::FCOND_SUNE) ++ return false; + +- Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); +- Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); ++ assert((CC >= LoongArch::FCOND_T && CC <= LoongArch::FCOND_GT) && ++ "Illegal Condition Code"); + +- SDValue Parts[2] = {Lo, Hi}; +- return DAG.getMergeValues(Parts, DL); ++ return true; + } + +-// Returns the opcode of the target-specific SDNode that implements the 32-bit +-// form of the given Opcode. +-static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { +- switch (Opcode) { +- default: +- llvm_unreachable("Unexpected opcode"); +- case ISD::SHL: +- return LoongArchISD::SLL_W; +- case ISD::SRA: +- return LoongArchISD::SRA_W; +- case ISD::SRL: +- return LoongArchISD::SRL_W; +- } ++// Creates and returns an FPCmp node from a setcc node. ++// Returns Op if setcc is not a floating point comparison. ++static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { ++ // must be a SETCC node ++ if (Op.getOpcode() != ISD::SETCC) ++ return Op; ++ ++ SDValue LHS = Op.getOperand(0); ++ ++ if (!LHS.getValueType().isFloatingPoint()) ++ return Op; ++ ++ SDValue RHS = Op.getOperand(1); ++ SDLoc DL(Op); ++ ++ // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of ++ // node if necessary. ++ ISD::CondCode CC = cast(Op.getOperand(2))->get(); ++ ++ return DAG.getNode(LoongArchISD::FPCmp, DL, MVT::Glue, LHS, RHS, ++ DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32)); + } + +-// Converts the given i8/i16/i32 operation to a target-specific SelectionDAG +-// node. Because i8/i16/i32 isn't a legal type for LA64, these operations would +-// otherwise be promoted to i64, making it difficult to select the +-// SLL_W/.../*W later one because the fact the operation was originally of +-// type i8/i16/i32 is lost. +-static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, +- unsigned ExtOpc = ISD::ANY_EXTEND) { +- SDLoc DL(N); +- LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode()); +- SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0)); +- SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1)); +- SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1); +- // ReplaceNodeResults requires we maintain the same type for the return value. +- return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes); ++// Creates and returns a CMovFPT/F node. ++static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, ++ SDValue False, const SDLoc &DL) { ++ ConstantSDNode *CC = cast(Cond.getOperand(2)); ++ bool invert = invertFPCondCodeUser((LoongArch::CondCode)CC->getSExtValue()); ++ SDValue FCC0 = DAG.getRegister(LoongArch::FCC0, MVT::i32); ++ ++ return DAG.getNode((invert ? LoongArchISD::CMovFP_F : LoongArchISD::CMovFP_T), DL, ++ True.getValueType(), True, FCC0, False, Cond); ++ + } + +-void LoongArchTargetLowering::ReplaceNodeResults( +- SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { +- SDLoc DL(N); +- switch (N->getOpcode()) { +- default: +- llvm_unreachable("Don't know how to legalize this operation"); +- case ISD::SHL: +- case ISD::SRA: +- case ISD::SRL: +- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && +- "Unexpected custom legalisation"); +- if (N->getOperand(1).getOpcode() != ISD::Constant) { +- Results.push_back(customLegalizeToWOp(N, DAG)); +- break; +- } +- break; +- case ISD::FP_TO_SINT: { +- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && +- "Unexpected custom legalisation"); +- SDValue Src = N->getOperand(0); +- EVT VT = EVT::getFloatingPointVT(N->getValueSizeInBits(0)); +- SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src); +- Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst)); +- break; +- } +- case ISD::BITCAST: { +- EVT VT = N->getValueType(0); +- SDValue Src = N->getOperand(0); +- EVT SrcVT = Src.getValueType(); +- if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() && +- Subtarget.hasBasicF()) { +- SDValue Dst = +- DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Src); +- Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Dst)); +- } +- break; +- } +- case ISD::FP_TO_UINT: { +- assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && +- "Unexpected custom legalisation"); +- auto &TLI = DAG.getTargetLoweringInfo(); +- SDValue Tmp1, Tmp2; +- TLI.expandFP_TO_UINT(N, Tmp1, Tmp2, DAG); +- Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Tmp1)); +- break; ++static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ if (DCI.isBeforeLegalizeOps()) ++ return SDValue(); ++ ++ SDValue SetCC = N->getOperand(0); ++ ++ if ((SetCC.getOpcode() != ISD::SETCC) || ++ !SetCC.getOperand(0).getValueType().isInteger()) ++ return SDValue(); ++ ++ SDValue False = N->getOperand(2); ++ EVT FalseTy = False.getValueType(); ++ ++ if (!FalseTy.isInteger()) ++ return SDValue(); ++ ++ ConstantSDNode *FalseC = dyn_cast(False); ++ ++ // If the RHS (False) is 0, we swap the order of the operands ++ // of ISD::SELECT (obviously also inverting the condition) so that we can ++ // take advantage of conditional moves using the $0 register. ++ // Example: ++ // return (a != 0) ? x : 0; ++ // load $reg, x ++ // movz $reg, $0, a ++ if (!FalseC) ++ return SDValue(); ++ ++ const SDLoc DL(N); ++ ++ if (!FalseC->getZExtValue()) { ++ ISD::CondCode CC = cast(SetCC.getOperand(2))->get(); ++ SDValue True = N->getOperand(1); ++ ++ SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), ++ SetCC.getOperand(1), ++ ISD::getSetCCInverse(CC, SetCC.getValueType())); ++ ++ return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); + } ++ ++ // If both operands are integer constants there's a possibility that we ++ // can do some interesting optimizations. ++ SDValue True = N->getOperand(1); ++ ConstantSDNode *TrueC = dyn_cast(True); ++ ++ if (!TrueC || !True.getValueType().isInteger()) ++ return SDValue(); ++ ++ // We'll also ignore MVT::i64 operands as this optimizations proves ++ // to be ineffective because of the required sign extensions as the result ++ // of a SETCC operator is always MVT::i32 for non-vector types. ++ if (True.getValueType() == MVT::i64) ++ return SDValue(); ++ ++ int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue(); ++ ++ // 1) (a < x) ? y : y-1 ++ // slti $reg1, a, x ++ // addiu $reg2, $reg1, y-1 ++ if (Diff == 1) ++ return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False); ++ ++ // 2) (a < x) ? y-1 : y ++ // slti $reg1, a, x ++ // xor $reg1, $reg1, 1 ++ // addiu $reg2, $reg1, y-1 ++ if (Diff == -1) { ++ ISD::CondCode CC = cast(SetCC.getOperand(2))->get(); ++ SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), ++ SetCC.getOperand(1), ++ ISD::getSetCCInverse(CC, SetCC.getValueType())); ++ return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); + } ++ ++ // Could not optimize. ++ return SDValue(); + } + + static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const LoongArchSubtarget &Subtarget) { ++ ++ if (Subtarget.hasLSX()) { ++ ++ // Fold zero extensions into LoongArchISD::VEXTRACT_[SZ]EXT_ELT ++ // ++ // Performs the following transformations: ++ // - Changes LoongArchISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its ++ // sign/zero-extension is completely overwritten by the new one performed ++ // by the ISD::AND. ++ // - Removes redundant zero extensions performed by an ISD::AND. ++ SDValue Op0 = N->getOperand(0); ++ SDValue Op1 = N->getOperand(1); ++ unsigned Op0Opcode = Op0->getOpcode(); ++ ++ // (and (LoongArchVExtract[SZ]Ext $a, $b, $c), imm:$d) ++ // where $d + 1 == 2^n and n == 32 ++ // or $d + 1 == 2^n and n <= 32 and ZExt ++ // -> (LoongArchVExtractZExt $a, $b, $c) ++ if (Op0Opcode == LoongArchISD::VEXTRACT_SEXT_ELT || ++ Op0Opcode == LoongArchISD::VEXTRACT_ZEXT_ELT) { ++ ConstantSDNode *Mask = dyn_cast(Op1); ++ ++ if (Mask) { ++ ++ int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2(); ++ ++ if (Log2IfPositive > 0) { ++ SDValue Op0Op2 = Op0->getOperand(2); ++ EVT ExtendTy = cast(Op0Op2)->getVT(); ++ unsigned ExtendTySize = ExtendTy.getSizeInBits(); ++ unsigned Log2 = Log2IfPositive; ++ ++ if ((Op0Opcode == LoongArchISD::VEXTRACT_ZEXT_ELT && ++ Log2 >= ExtendTySize) || ++ Log2 == ExtendTySize) { ++ SDValue Ops[] = {Op0->getOperand(0), Op0->getOperand(1), Op0Op2}; ++ return DAG.getNode(LoongArchISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0), ++ Op0->getVTList(), ++ makeArrayRef(Ops, Op0->getNumOperands())); ++ } ++ } ++ } ++ } ++ } ++ + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + SDValue FirstOperand = N->getOperand(0); +- SDValue SecondOperand = N->getOperand(1); + unsigned FirstOperandOpc = FirstOperand.getOpcode(); ++ SDValue Mask = N->getOperand(1); + EVT ValTy = N->getValueType(0); + SDLoc DL(N); +- uint64_t lsb, msb; +- unsigned SMIdx, SMLen; ++ ++ uint64_t Lsb = 0, SMLsb, SMSize; + ConstantSDNode *CN; + SDValue NewOperand; +- MVT GRLenVT = Subtarget.getGRLenVT(); ++ unsigned Opc; + + // Op's second operand must be a shifted mask. +- if (!(CN = dyn_cast(SecondOperand)) || +- !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen)) ++ if (!(CN = dyn_cast(Mask)) || ++ !isShiftedMask(CN->getZExtValue(), SMLsb, SMSize)) + return SDValue(); + + if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { + // Pattern match BSTRPICK. +- // $dst = and ((sra or srl) $src , lsb), (2**len - 1) +- // => BSTRPICK $dst, $src, msb, lsb +- // where msb = lsb + len - 1 ++ // $dst = and ((sra or srl) $src , lsb), (2**size - 1) ++ // => bstrpick $dst, $src, lsb+size-1, lsb + + // The second operand of the shift must be an immediate. + if (!(CN = dyn_cast(FirstOperand.getOperand(1)))) + return SDValue(); + +- lsb = CN->getZExtValue(); ++ Lsb = CN->getZExtValue(); + +- // Return if the shifted mask does not start at bit 0 or the sum of its +- // length and lsb exceeds the word's size. +- if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits()) ++ // Return if the shifted mask does not start at bit 0 or the sum of its size ++ // and Lsb exceeds the word's size. ++ if (SMLsb != 0 || Lsb + SMSize > ValTy.getSizeInBits()) + return SDValue(); + ++ Opc = LoongArchISD::BSTRPICK; + NewOperand = FirstOperand.getOperand(0); + } else { + // Pattern match BSTRPICK. +- // $dst = and $src, (2**len- 1) , if len > 12 +- // => BSTRPICK $dst, $src, msb, lsb +- // where lsb = 0 and msb = len - 1 ++ // $dst = and $src, (2**size - 1) , if size > 12 ++ // => bstrpick $dst, $src, lsb+size-1, lsb , lsb = 0 + + // If the mask is <= 0xfff, andi can be used instead. + if (CN->getZExtValue() <= 0xfff) + return SDValue(); +- + // Return if the mask doesn't start at position 0. +- if (SMIdx) ++ if (SMLsb) + return SDValue(); + +- lsb = 0; ++ Opc = LoongArchISD::BSTRPICK; + NewOperand = FirstOperand; + } +- msb = lsb + SMLen - 1; +- return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, +- DAG.getConstant(msb, DL, GRLenVT), +- DAG.getConstant(lsb, DL, GRLenVT)); ++ return DAG.getNode(Opc, DL, ValTy, NewOperand, ++ DAG.getConstant((Lsb + SMSize - 1), DL, MVT::i32), ++ DAG.getConstant(Lsb, DL, MVT::i32)); + } + +-static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, +- TargetLowering::DAGCombinerInfo &DCI, +- const LoongArchSubtarget &Subtarget) { +- if (DCI.isBeforeLegalizeOps()) +- return SDValue(); ++// Determine if the specified node is a constant vector splat. ++// ++// Returns true and sets Imm if: ++// * N is a ISD::BUILD_VECTOR representing a constant splat ++static bool isVSplat(SDValue N, APInt &Imm) { ++ BuildVectorSDNode *Node = dyn_cast(N.getNode()); + +- // $dst = srl (and $src, Mask), Shamt +- // => +- // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt +- // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1 +- // ++ if (!Node) ++ return false; + +- SDValue FirstOperand = N->getOperand(0); +- ConstantSDNode *CN; +- EVT ValTy = N->getValueType(0); +- SDLoc DL(N); +- MVT GRLenVT = Subtarget.getGRLenVT(); +- unsigned MaskIdx, MaskLen; +- uint64_t Shamt; ++ APInt SplatValue, SplatUndef; ++ unsigned SplatBitSize; ++ bool HasAnyUndefs; ++ ++ if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, ++ 8)) ++ return false; ++ ++ Imm = SplatValue; ++ ++ return true; ++} ++ ++// Test whether the given node is an all-ones build_vector. ++static bool isVectorAllOnes(SDValue N) { ++ // Look through bitcasts. Endianness doesn't matter because we are looking ++ // for an all-ones value. ++ if (N->getOpcode() == ISD::BITCAST) ++ N = N->getOperand(0); + +- // The first operand must be an AND and the second operand of the AND must be +- // a shifted mask. +- if (FirstOperand.getOpcode() != ISD::AND || +- !(CN = dyn_cast(FirstOperand.getOperand(1))) || +- !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen)) ++ BuildVectorSDNode *BVN = dyn_cast(N); ++ ++ if (!BVN) ++ return false; ++ ++ APInt SplatValue, SplatUndef; ++ unsigned SplatBitSize; ++ bool HasAnyUndefs; ++ ++ // Endianness doesn't matter in this context because we are looking for ++ // an all-ones value. ++ if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs)) ++ return SplatValue.isAllOnesValue(); ++ ++ return false; ++} ++ ++// Test whether N is the bitwise inverse of OfNode. ++static bool isBitwiseInverse(SDValue N, SDValue OfNode) { ++ if (N->getOpcode() != ISD::XOR) ++ return false; ++ ++ if (isVectorAllOnes(N->getOperand(0))) ++ return N->getOperand(1) == OfNode; ++ ++ if (isVectorAllOnes(N->getOperand(1))) ++ return N->getOperand(0) == OfNode; ++ ++ return false; ++} ++ ++static SDValue performSet(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ SDValue Op0 = N->getOperand(0); ++ SDValue Op1 = N->getOperand(1); ++ SDValue N1, N2; ++ if (Op0->getOpcode() == ISD::BUILD_VECTOR && ++ (Op1->getValueType(0).is128BitVector() || ++ Op1->getValueType(0).is256BitVector())) { ++ N1 = Op0; ++ N2 = Op1; ++ } else if (Op1->getOpcode() == ISD::BUILD_VECTOR && ++ (Op0->getValueType(0).is128BitVector() || ++ Op0->getValueType(0).is256BitVector())) { ++ N1 = Op1; ++ N2 = Op0; ++ } else + return SDValue(); + +- // The second operand (shift amount) must be an immediate. +- if (!(CN = dyn_cast(N->getOperand(1)))) ++ APInt Mask1, Mask2; ++ if (!isVSplat(N1, Mask1)) + return SDValue(); + +- Shamt = CN->getZExtValue(); +- if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1) +- return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, +- FirstOperand->getOperand(0), +- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), +- DAG.getConstant(Shamt, DL, GRLenVT)); ++ if (!N1->getValueType(0).isSimple()) ++ return SDValue(); + +- return SDValue(); ++ ConstantSDNode *C1; ++ uint64_t Imm; ++ unsigned ImmL; ++ if (!(C1 = dyn_cast(N1.getOperand(0))) || ++ !isPowerOf2_64(C1->getZExtValue())) ++ return SDValue(); ++ ++ Imm = C1->getZExtValue(); ++ ImmL = Log2_64(Imm); ++ MVT VT = N1->getSimpleValueType(0).SimpleTy; ++ ++ SDNode *Res; ++ ++ if (Subtarget.hasLASX() && N->getValueType(0).is256BitVector()) { ++ if (VT == MVT::v32i8 && ImmL < 8) ++ Res = DAG.getMachineNode(LoongArch::XVBITSETI_B, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v16i16 && ImmL < 16) ++ Res = DAG.getMachineNode(LoongArch::XVBITSETI_H, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v8i32 && ImmL < 32) ++ Res = DAG.getMachineNode(LoongArch::XVBITSETI_W, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v4i64 && ImmL < 64) ++ Res = DAG.getMachineNode(LoongArch::XVBITSETI_D, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else ++ return SDValue(); ++ } else if (N->getValueType(0).is128BitVector()) { ++ if (VT == MVT::v16i8 && ImmL < 8) ++ Res = DAG.getMachineNode(LoongArch::VBITSETI_B, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v8i16 && ImmL < 16) ++ Res = DAG.getMachineNode(LoongArch::VBITSETI_H, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v4i32 && ImmL < 32) ++ Res = DAG.getMachineNode(LoongArch::VBITSETI_W, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else if (VT == MVT::v2i64 && ImmL < 64) ++ Res = DAG.getMachineNode(LoongArch::VBITSETI_D, SDLoc(N), VT, N2, ++ DAG.getTargetConstant(ImmL, SDLoc(N), MVT::i32)); ++ else ++ return SDValue(); ++ ++ } else ++ return SDValue(); ++ ++ return SDValue(Res, 0); + } + + static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const LoongArchSubtarget &Subtarget) { +- MVT GRLenVT = Subtarget.getGRLenVT(); +- EVT ValTy = N->getValueType(0); +- SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); +- ConstantSDNode *CN0, *CN1; +- SDLoc DL(N); +- unsigned ValBits = ValTy.getSizeInBits(); +- unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1; +- unsigned Shamt; +- bool SwapAndRetried = false; + ++ SDValue Res; ++ if (Subtarget.hasLSX() && (N->getValueType(0).is128BitVector() || ++ N->getValueType(0).is256BitVector())) { ++ SDValue Op0 = N->getOperand(0); ++ SDValue Op1 = N->getOperand(1); ++ ++ if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) { ++ SDValue Op0Op0 = Op0->getOperand(0); ++ SDValue Op0Op1 = Op0->getOperand(1); ++ SDValue Op1Op0 = Op1->getOperand(0); ++ SDValue Op1Op1 = Op1->getOperand(1); ++ ++ SDValue IfSet, IfClr, Cond; ++ bool IsConstantMask = false; ++ APInt Mask, InvMask; ++ ++ // If Op0Op0 is an appropriate mask, try to find it's inverse in either ++ // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, ++ // while looking. IfClr will be set if we find a valid match. ++ if (isVSplat(Op0Op0, Mask)) { ++ Cond = Op0Op0; ++ IfSet = Op0Op1; ++ ++ if (isVSplat(Op1Op0, InvMask) && ++ Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) ++ IfClr = Op1Op1; ++ else if (isVSplat(Op1Op1, InvMask) && ++ Mask.getBitWidth() == InvMask.getBitWidth() && ++ Mask == ~InvMask) ++ IfClr = Op1Op0; ++ ++ IsConstantMask = true; ++ } ++ ++ // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the ++ // same thing again using this mask. IfClr will be set if we find a valid ++ // match. ++ if (!IfClr.getNode() && isVSplat(Op0Op1, Mask)) { ++ Cond = Op0Op1; ++ IfSet = Op0Op0; ++ ++ if (isVSplat(Op1Op0, InvMask) && ++ Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) ++ IfClr = Op1Op1; ++ else if (isVSplat(Op1Op1, InvMask) && ++ Mask.getBitWidth() == InvMask.getBitWidth() && ++ Mask == ~InvMask) ++ IfClr = Op1Op0; ++ ++ IsConstantMask = true; ++ } ++ ++ // If IfClr is not yet set, try looking for a non-constant match. ++ // IfClr will be set if we find a valid match amongst the eight ++ // possibilities. ++ if (!IfClr.getNode()) { ++ if (isBitwiseInverse(Op0Op0, Op1Op0)) { ++ Cond = Op1Op0; ++ IfSet = Op1Op1; ++ IfClr = Op0Op1; ++ } else if (isBitwiseInverse(Op0Op1, Op1Op0)) { ++ Cond = Op1Op0; ++ IfSet = Op1Op1; ++ IfClr = Op0Op0; ++ } else if (isBitwiseInverse(Op0Op0, Op1Op1)) { ++ Cond = Op1Op1; ++ IfSet = Op1Op0; ++ IfClr = Op0Op1; ++ } else if (isBitwiseInverse(Op0Op1, Op1Op1)) { ++ Cond = Op1Op1; ++ IfSet = Op1Op0; ++ IfClr = Op0Op0; ++ } else if (isBitwiseInverse(Op1Op0, Op0Op0)) { ++ Cond = Op0Op0; ++ IfSet = Op0Op1; ++ IfClr = Op1Op1; ++ } else if (isBitwiseInverse(Op1Op1, Op0Op0)) { ++ Cond = Op0Op0; ++ IfSet = Op0Op1; ++ IfClr = Op1Op0; ++ } else if (isBitwiseInverse(Op1Op0, Op0Op1)) { ++ Cond = Op0Op1; ++ IfSet = Op0Op0; ++ IfClr = Op1Op1; ++ } else if (isBitwiseInverse(Op1Op1, Op0Op1)) { ++ Cond = Op0Op1; ++ IfSet = Op0Op0; ++ IfClr = Op1Op0; ++ } ++ } ++ ++ // At this point, IfClr will be set if we have a valid match. ++ if (IfClr.getNode()) { ++ assert(Cond.getNode() && IfSet.getNode()); ++ ++ // Fold degenerate cases. ++ if (IsConstantMask) { ++ if (Mask.isAllOnesValue()) ++ return IfSet; ++ else if (Mask == 0) ++ return IfClr; ++ } ++ ++ // Transform the DAG into an equivalent VSELECT. ++ return DAG.getNode(ISD::VSELECT, SDLoc(N), N->getValueType(0), Cond, ++ IfSet, IfClr); ++ } ++ } ++ ++ if (Res = performSet(N, DAG, DCI, Subtarget)) ++ return Res; ++ } ++ ++ // Pattern match BSTRINS. ++ // $dst = or (and $src1 , mask0), (and (shl $src, lsb), mask1), ++ // where mask1 = (2**size - 1) << lsb, mask0 = ~mask1 ++ // => bstrins $dst, $src, lsb+size-1, lsb, $src1 + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + +- if (ValBits != 32 && ValBits != 64) ++ SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); ++ uint64_t SMLsb0, SMSize0, SMLsb1, SMSize1; ++ ConstantSDNode *CN, *CN1; ++ ++ // See if Op's first operand matches (and $src1 , mask0). ++ if (And0.getOpcode() != ISD::AND) + return SDValue(); + +-Retry: +- // 1st pattern to match BSTRINS: +- // R = or (and X, mask0), (and (shl Y, lsb), mask1) +- // where mask1 = (2**size - 1) << lsb, mask0 = ~mask1 +- // => +- // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) +- if (N0.getOpcode() == ISD::AND && +- (CN0 = dyn_cast(N0.getOperand(1))) && +- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && +- N1.getOpcode() == ISD::AND && N1.getOperand(0).getOpcode() == ISD::SHL && +- (CN1 = dyn_cast(N1.getOperand(1))) && +- isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && +- MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 && +- (CN1 = dyn_cast(N1.getOperand(0).getOperand(1))) && +- (Shamt = CN1->getZExtValue()) == MaskIdx0 && +- (MaskIdx0 + MaskLen0 <= ValBits)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 1\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), +- N1.getOperand(0).getOperand(0), +- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), +- DAG.getConstant(MaskIdx0, DL, GRLenVT)); +- } +- +- // 2nd pattern to match BSTRINS: +- // R = or (and X, mask0), (shl (and Y, mask1), lsb) +- // where mask1 = (2**size - 1), mask0 = ~(mask1 << lsb) +- // => +- // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) +- if (N0.getOpcode() == ISD::AND && +- (CN0 = dyn_cast(N0.getOperand(1))) && +- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && +- N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && +- (CN1 = dyn_cast(N1.getOperand(1))) && +- (Shamt = CN1->getZExtValue()) == MaskIdx0 && +- (CN1 = dyn_cast(N1.getOperand(0).getOperand(1))) && +- isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && +- MaskLen0 == MaskLen1 && MaskIdx1 == 0 && +- (MaskIdx0 + MaskLen0 <= ValBits)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 2\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), +- N1.getOperand(0).getOperand(0), +- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), +- DAG.getConstant(MaskIdx0, DL, GRLenVT)); +- } +- +- // 3rd pattern to match BSTRINS: +- // R = or (and X, mask0), (and Y, mask1) +- // where ~mask0 = (2**size - 1) << lsb, mask0 & mask1 = 0 +- // => +- // R = BSTRINS X, (shr (and Y, mask1), lsb), msb, lsb +- // where msb = lsb + size - 1 +- if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::AND && +- (CN0 = dyn_cast(N0.getOperand(1))) && +- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && +- (MaskIdx0 + MaskLen0 <= 64) && +- (CN1 = dyn_cast(N1->getOperand(1))) && +- (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 3\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), +- DAG.getNode(ISD::SRL, DL, N1->getValueType(0), N1, +- DAG.getConstant(MaskIdx0, DL, GRLenVT)), +- DAG.getConstant(ValBits == 32 +- ? (MaskIdx0 + (MaskLen0 & 31) - 1) +- : (MaskIdx0 + MaskLen0 - 1), +- DL, GRLenVT), +- DAG.getConstant(MaskIdx0, DL, GRLenVT)); +- } +- +- // 4th pattern to match BSTRINS: +- // R = or (and X, mask), (shl Y, shamt) +- // where mask = (2**shamt - 1) +- // => +- // R = BSTRINS X, Y, ValBits - 1, shamt +- // where ValBits = 32 or 64 +- if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::SHL && +- (CN0 = dyn_cast(N0.getOperand(1))) && +- isShiftedMask_64(CN0->getZExtValue(), MaskIdx0, MaskLen0) && +- MaskIdx0 == 0 && (CN1 = dyn_cast(N1.getOperand(1))) && +- (Shamt = CN1->getZExtValue()) == MaskLen0 && +- (MaskIdx0 + MaskLen0 <= ValBits)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 4\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), +- N1.getOperand(0), +- DAG.getConstant((ValBits - 1), DL, GRLenVT), +- DAG.getConstant(Shamt, DL, GRLenVT)); +- } +- +- // 5th pattern to match BSTRINS: +- // R = or (and X, mask), const +- // where ~mask = (2**size - 1) << lsb, mask & const = 0 +- // => +- // R = BSTRINS X, (const >> lsb), msb, lsb +- // where msb = lsb + size - 1 +- if (N0.getOpcode() == ISD::AND && +- (CN0 = dyn_cast(N0.getOperand(1))) && +- isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && +- (CN1 = dyn_cast(N1)) && +- (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n"); +- return DAG.getNode( +- LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), +- DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy), +- DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), +- DAG.getConstant(MaskIdx0, DL, GRLenVT)); +- } +- +- // 6th pattern. +- // a = b | ((c & mask) << shamt), where all positions in b to be overwritten +- // by the incoming bits are known to be zero. +- // => +- // a = BSTRINS b, c, shamt + MaskLen - 1, shamt +- // +- // Note that the 1st pattern is a special situation of the 6th, i.e. the 6th +- // pattern is more common than the 1st. So we put the 1st before the 6th in +- // order to match as many nodes as possible. +- ConstantSDNode *CNMask, *CNShamt; +- unsigned MaskIdx, MaskLen; +- if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && +- (CNMask = dyn_cast(N1.getOperand(0).getOperand(1))) && +- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && +- MaskIdx == 0 && (CNShamt = dyn_cast(N1.getOperand(1))) && +- CNShamt->getZExtValue() + MaskLen <= ValBits) { +- Shamt = CNShamt->getZExtValue(); +- APInt ShMask(ValBits, CNMask->getZExtValue() << Shamt); +- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 6\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, +- N1.getOperand(0).getOperand(0), +- DAG.getConstant(Shamt + MaskLen - 1, DL, GRLenVT), +- DAG.getConstant(Shamt, DL, GRLenVT)); ++ if (!(CN = dyn_cast(And0.getOperand(1))) || ++ !isShiftedMask(~CN->getSExtValue(), SMLsb0, SMSize0)) ++ return SDValue(); ++ ++ // See if Op's second operand matches (and (shl $src, lsb), mask1). ++ if (And1.getOpcode() == ISD::AND && ++ And1.getOperand(0).getOpcode() == ISD::SHL) { ++ ++ if (!(CN = dyn_cast(And1.getOperand(1))) || ++ !isShiftedMask(CN->getZExtValue(), SMLsb1, SMSize1)) ++ return SDValue(); ++ ++ // The shift masks must have the same least significant bit and size. ++ if (SMLsb0 != SMLsb1 || SMSize0 != SMSize1) ++ return SDValue(); ++ ++ SDValue Shl = And1.getOperand(0); ++ ++ if (!(CN = dyn_cast(Shl.getOperand(1)))) ++ return SDValue(); ++ ++ unsigned Shamt = CN->getZExtValue(); ++ ++ // Return if the shift amount and the first bit position of mask are not the ++ // same. ++ EVT ValTy = N->getValueType(0); ++ if ((Shamt != SMLsb0) || (SMLsb0 + SMSize0 > ValTy.getSizeInBits())) ++ return SDValue(); ++ ++ SDLoc DL(N); ++ return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, Shl.getOperand(0), ++ DAG.getConstant((SMLsb0 + SMSize0 - 1), DL, MVT::i32), ++ DAG.getConstant(SMLsb0, DL, MVT::i32), ++ And0.getOperand(0)); ++ } else { ++ // Pattern match BSTRINS. ++ // $dst = or (and $src, mask0), mask1 ++ // where mask0 = ((1 << SMSize0) -1) << SMLsb0 ++ // => bstrins $dst, $src, SMLsb0+SMSize0-1, SMLsb0 ++ if (~CN->getSExtValue() == ((((int64_t)1 << SMSize0) - 1) << SMLsb0) && ++ (SMSize0 + SMLsb0 <= 64)) { ++ // Check if AND instruction has constant as argument ++ bool isConstCase = And1.getOpcode() != ISD::AND; ++ if (And1.getOpcode() == ISD::AND) { ++ if (!(CN1 = dyn_cast(And1->getOperand(1)))) ++ return SDValue(); ++ } else { ++ if (!(CN1 = dyn_cast(N->getOperand(1)))) ++ return SDValue(); ++ } ++ // Don't generate BSTRINS if constant OR operand doesn't fit into bits ++ // cleared by constant AND operand. ++ if (CN->getSExtValue() & CN1->getSExtValue()) ++ return SDValue(); ++ ++ SDLoc DL(N); ++ EVT ValTy = N->getOperand(0)->getValueType(0); ++ SDValue Const1; ++ SDValue SrlX; ++ if (!isConstCase) { ++ Const1 = DAG.getConstant(SMLsb0, DL, MVT::i32); ++ SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1); ++ } ++ return DAG.getNode( ++ LoongArchISD::BSTRINS, DL, N->getValueType(0), ++ isConstCase ++ ? DAG.getConstant(CN1->getSExtValue() >> SMLsb0, DL, ValTy) ++ : SrlX, ++ DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? (SMLsb0 + (SMSize0 & 31) - 1) ++ : (SMLsb0 + SMSize0 - 1), ++ DL, MVT::i32), ++ DAG.getConstant(SMLsb0, DL, MVT::i32), ++ And0->getOperand(0)); ++ + } ++ return SDValue(); + } ++} + +- // 7th pattern. +- // a = b | ((c << shamt) & shifted_mask), where all positions in b to be +- // overwritten by the incoming bits are known to be zero. +- // => +- // a = BSTRINS b, c, MaskIdx + MaskLen - 1, MaskIdx ++static bool ++shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, ++ SelectionDAG &DAG, ++ const LoongArchSubtarget &Subtarget) { ++ // Estimate the number of operations the below transform will turn a ++ // constant multiply into. The number is approximately equal to the minimal ++ // number of powers of two that constant can be broken down to by adding ++ // or subtracting them. ++ // ++ // If we have taken more than 10[1] / 8[2] steps to attempt the ++ // optimization for a native sized value, it is more than likely that this ++ // optimization will make things worse. ++ // ++ // [1] LA64 requires 4 instructions at most to materialize any constant, ++ // multiplication requires at least 4 cycles, but another cycle (or two) ++ // to retrieve the result from corresponding registers. ++ // ++ // [2] LA32 requires 2 instructions at most to materialize any constant, ++ // multiplication requires at least 4 cycles, but another cycle (or two) ++ // to retrieve the result from corresponding registers. + // +- // Similarly, the 7th pattern is more common than the 2nd. So we put the 2nd +- // before the 7th in order to match as many nodes as possible. +- if (N1.getOpcode() == ISD::AND && +- (CNMask = dyn_cast(N1.getOperand(1))) && +- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && +- N1.getOperand(0).getOpcode() == ISD::SHL && +- (CNShamt = dyn_cast(N1.getOperand(0).getOperand(1))) && +- CNShamt->getZExtValue() == MaskIdx) { +- APInt ShMask(ValBits, CNMask->getZExtValue()); +- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 7\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, +- N1.getOperand(0).getOperand(0), +- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), +- DAG.getConstant(MaskIdx, DL, GRLenVT)); ++ // TODO: ++ // - MaxSteps needs to consider the `VT` of the constant for the current ++ // target. ++ // - Consider to perform this optimization after type legalization. ++ // That allows to remove a workaround for types not supported natively. ++ // - Take in account `-Os, -Oz` flags because this optimization ++ // increases code size. ++ unsigned MaxSteps = Subtarget.isABI_LP32() ? 8 : 10; ++ ++ SmallVector WorkStack(1, C); ++ unsigned Steps = 0; ++ unsigned BitWidth = C.getBitWidth(); ++ ++ while (!WorkStack.empty()) { ++ APInt Val = WorkStack.pop_back_val(); ++ ++ if (Val == 0 || Val == 1) ++ continue; ++ ++ if (Steps >= MaxSteps) ++ return false; ++ ++ if (Val.isPowerOf2()) { ++ ++Steps; ++ continue; + } +- } + +- // (or a, b) and (or b, a) are equivalent, so swap the operands and retry. +- if (!SwapAndRetried) { +- std::swap(N0, N1); +- SwapAndRetried = true; +- goto Retry; +- } ++ APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); ++ APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) ++ : APInt(BitWidth, 1) << C.ceilLogBase2(); + +- SwapAndRetried = false; +-Retry2: +- // 8th pattern. +- // a = b | (c & shifted_mask), where all positions in b to be overwritten by +- // the incoming bits are known to be zero. +- // => +- // a = BSTRINS b, c >> MaskIdx, MaskIdx + MaskLen - 1, MaskIdx +- // +- // Similarly, the 8th pattern is more common than the 4th and 5th patterns. So +- // we put it here in order to match as many nodes as possible or generate less +- // instructions. +- if (N1.getOpcode() == ISD::AND && +- (CNMask = dyn_cast(N1.getOperand(1))) && +- isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen)) { +- APInt ShMask(ValBits, CNMask->getZExtValue()); +- if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { +- LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 8\n"); +- return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, +- DAG.getNode(ISD::SRL, DL, N1->getValueType(0), +- N1->getOperand(0), +- DAG.getConstant(MaskIdx, DL, GRLenVT)), +- DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), +- DAG.getConstant(MaskIdx, DL, GRLenVT)); ++ if ((Val - Floor).ule(Ceil - Val)) { ++ WorkStack.push_back(Floor); ++ WorkStack.push_back(Val - Floor); ++ } else { ++ WorkStack.push_back(Ceil); ++ WorkStack.push_back(Ceil - Val); + } +- } +- // Swap N0/N1 and retry. +- if (!SwapAndRetried) { +- std::swap(N0, N1); +- SwapAndRetried = true; +- goto Retry2; ++ ++ ++Steps; + } + +- return SDValue(); +-} ++ // If the value being multiplied is not supported natively, we have to pay ++ // an additional legalization cost, conservatively assume an increase in the ++ // cost of 3 instructions per step. This values for this heuristic were ++ // determined experimentally. ++ unsigned RegisterSize = DAG.getTargetLoweringInfo() ++ .getRegisterType(*DAG.getContext(), VT) ++ .getSizeInBits(); ++ Steps *= (VT.getSizeInBits() != RegisterSize) * 3; ++ if (Steps > 27) ++ return false; + +-SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N, +- DAGCombinerInfo &DCI) const { +- SelectionDAG &DAG = DCI.DAG; +- switch (N->getOpcode()) { ++ return true; ++} ++ ++static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT, ++ EVT ShiftTy, SelectionDAG &DAG) { ++ // Return 0. ++ if (C == 0) ++ return DAG.getConstant(0, DL, VT); ++ ++ // Return x. ++ if (C == 1) ++ return X; ++ ++ // If c is power of 2, return (shl x, log2(c)). ++ if (C.isPowerOf2()) ++ return DAG.getNode(ISD::SHL, DL, VT, X, ++ DAG.getConstant(C.logBase2(), DL, ShiftTy)); ++ ++ unsigned BitWidth = C.getBitWidth(); ++ APInt Floor = APInt(BitWidth, 1) << C.logBase2(); ++ APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) : ++ APInt(BitWidth, 1) << C.ceilLogBase2(); ++ ++ // If |c - floor_c| <= |c - ceil_c|, ++ // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))), ++ // return (add constMult(x, floor_c), constMult(x, c - floor_c)). ++ if ((C - Floor).ule(Ceil - C)) { ++ SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG); ++ SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG); ++ return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1); ++ } ++ ++ // If |c - floor_c| > |c - ceil_c|, ++ // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)). ++ SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG); ++ SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG); ++ return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1); ++} ++ ++static SDValue performLogicCombine(SDNode *N, SelectionDAG &DAG, ++ const LoongArchSubtarget &Subtarget) { ++ ++ SDLoc DL(N); ++ SDValue N0 = N->getOperand(0); ++ SDValue N1 = N->getOperand(1); ++ ++ if (!(N0->getOpcode() == ISD::TRUNCATE && N1->getOpcode() == ISD::TRUNCATE)) ++ return SDValue(); ++ ++ if (!(N->getValueType(0).isSimple() && N0->getValueType(0).isSimple() && ++ N1->getValueType(0).isSimple() && ++ N0->getOperand(0)->getValueType(0).isSimple() && ++ N1->getOperand(0)->getValueType(0).isSimple())) ++ return SDValue(); ++ ++ if (!(N->getValueType(0).isSimple() && N0->getValueType(0).isSimple() && ++ N1->getValueType(0).isSimple() && ++ N0->getOperand(0)->getValueType(0).isSimple() && ++ N1->getOperand(0)->getValueType(0).isSimple())) ++ return SDValue(); ++ ++ if (!(N->getSimpleValueType(0).SimpleTy == MVT::i32 && ++ N0->getSimpleValueType(0).SimpleTy == MVT::i32 && ++ N1->getSimpleValueType(0).SimpleTy == MVT::i32)) ++ return SDValue(); ++ ++ if (!(N0->getOperand(0)->getSimpleValueType(0).SimpleTy == MVT::i64 && ++ N1->getOperand(0)->getSimpleValueType(0).SimpleTy == MVT::i64)) ++ return SDValue(); ++ ++ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); ++ SDValue Val0 = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, ++ N0->getValueType(0), ++ N0->getOperand(0), SubReg), ++ 0); ++ SDValue Val1 = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, ++ N1->getValueType(0), ++ N1->getOperand(0), SubReg), ++ 0); ++ ++ return DAG.getNode(N->getOpcode(), DL, N0->getValueType(0), Val0, Val1); ++} ++ ++static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, ++ const TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchTargetLowering *TL, ++ const LoongArchSubtarget &Subtarget) { ++ EVT VT = N->getValueType(0); ++ ++ SDValue Res; ++ if ((Res = performLogicCombine(N, DAG, Subtarget))) ++ return Res; ++ ++ if (ConstantSDNode *C = dyn_cast(N->getOperand(1))) ++ if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs( ++ C->getAPIntValue(), VT, DAG, Subtarget)) ++ return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT, ++ TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT), ++ DAG); ++ ++ return SDValue(N, 0); ++} ++ ++// Fold sign-extensions into LoongArchISD::VEXTRACT_[SZ]EXT_ELT for LSX. ++// ++// Performs the following transformations: ++// - Changes LoongArchISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its ++// sign/zero-extension is completely overwritten by the new one performed by ++// the ISD::SRA and ISD::SHL nodes. ++// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL ++// sequence. ++static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ SDValue Res; ++ if ((Res = performLogicCombine(N, DAG, Subtarget))) ++ return Res; ++ ++ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { ++ SDValue Op0 = N->getOperand(0); ++ SDValue Op1 = N->getOperand(1); ++ ++ // (sra (shl (LoongArchVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d) ++ // where $d + sizeof($c) == 32 ++ // or $d + sizeof($c) <= 32 and SExt ++ // -> (LoongArchVExtractSExt $a, $b, $c) ++ if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) { ++ SDValue Op0Op0 = Op0->getOperand(0); ++ ConstantSDNode *ShAmount = dyn_cast(Op1); ++ ++ if (!ShAmount) ++ return SDValue(); ++ ++ if (Op0Op0->getOpcode() != LoongArchISD::VEXTRACT_SEXT_ELT && ++ Op0Op0->getOpcode() != LoongArchISD::VEXTRACT_ZEXT_ELT) ++ return SDValue(); ++ ++ EVT ExtendTy = cast(Op0Op0->getOperand(2))->getVT(); ++ unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits(); ++ ++ if (TotalBits == 32 || ++ (Op0Op0->getOpcode() == LoongArchISD::VEXTRACT_SEXT_ELT && ++ TotalBits <= 32)) { ++ SDValue Ops[] = {Op0Op0->getOperand(0), Op0Op0->getOperand(1), ++ Op0Op0->getOperand(2)}; ++ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0), ++ Op0Op0->getVTList(), ++ makeArrayRef(Ops, Op0Op0->getNumOperands())); ++ } ++ } ++ } ++ ++ return SDValue(); ++} ++ ++// combine vsub/vslt/vbitsel.v to vabsd ++static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { ++ assert((N->getOpcode() == ISD::VSELECT) && "Need ISD::VSELECT"); ++ ++ SDLoc dl(N); ++ SDValue Cond = N->getOperand(0); ++ SDValue TrueOpnd = N->getOperand(1); ++ SDValue FalseOpnd = N->getOperand(2); ++ ++ if (Cond.getOpcode() != ISD::SETCC || TrueOpnd.getOpcode() != ISD::SUB || ++ FalseOpnd.getOpcode() != ISD::SUB) ++ return SDValue(); ++ ++ if (!(Cond.hasOneUse() || TrueOpnd.hasOneUse() || FalseOpnd.hasOneUse())) ++ return SDValue(); ++ ++ ISD::CondCode CC = cast(Cond.getOperand(2))->get(); ++ ++ switch (CC) { + default: ++ return SDValue(); ++ case ISD::SETUGT: ++ case ISD::SETUGE: ++ case ISD::SETGT: ++ case ISD::SETGE: ++ break; ++ case ISD::SETULT: ++ case ISD::SETULE: ++ case ISD::SETLT: ++ case ISD::SETLE: ++ std::swap(TrueOpnd, FalseOpnd); + break; ++ } ++ ++ SDValue Op1 = Cond.getOperand(0); ++ SDValue Op2 = Cond.getOperand(1); ++ ++ if (TrueOpnd.getOperand(0) == Op1 && TrueOpnd.getOperand(1) == Op2 && ++ FalseOpnd.getOperand(0) == Op2 && FalseOpnd.getOperand(1) == Op1) { ++ if (ISD::isSignedIntSetCC(CC)) { ++ return DAG.getNode(LoongArchISD::VABSD, dl, ++ N->getOperand(1).getValueType(), Op1, Op2, ++ DAG.getTargetConstant(0, dl, MVT::i32)); ++ } else { ++ return DAG.getNode(LoongArchISD::UVABSD, dl, ++ N->getOperand(1).getValueType(), Op1, Op2, ++ DAG.getTargetConstant(0, dl, MVT::i32)); ++ } ++ } ++ return SDValue(); ++} ++ ++static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, ++ const LoongArchSubtarget &Subtarget) { ++ ++ EVT Ty = N->getValueType(0); ++ ++ if ((Subtarget.hasLSX() && Ty.is128BitVector() && Ty.isInteger()) || ++ (Subtarget.hasLASX() && Ty.is256BitVector() && Ty.isInteger())) { ++ // Try the following combines: ++ // (xor (or $a, $b), (build_vector allones)) ++ // (xor (or $a, $b), (bitcast (build_vector allones))) ++ SDValue Op0 = N->getOperand(0); ++ SDValue Op1 = N->getOperand(1); ++ SDValue NotOp; ++ ++ if (ISD::isBuildVectorAllOnes(Op0.getNode())) ++ NotOp = Op1; ++ else if (ISD::isBuildVectorAllOnes(Op1.getNode())) ++ NotOp = Op0; ++ else ++ return SDValue(); ++ ++ if (NotOp->getOpcode() == ISD::OR) ++ return DAG.getNode(LoongArchISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0), ++ NotOp->getOperand(1)); ++ } ++ ++ return SDValue(); ++} ++ ++// When using a 256-bit vector is less expensive than using a 128-bit vector, ++// use this function to convert a 128-bit vector to a 256-bit vector. ++static SDValue ++performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ assert((N->getOpcode() == ISD::CONCAT_VECTORS) && "Need ISD::CONCAT_VECTORS"); ++ if (DCI.isAfterLegalizeDAG()) ++ return SDValue(); ++ ++ SDLoc DL(N); ++ SDValue Top0 = N->getOperand(0); ++ SDValue Top1 = N->getOperand(1); ++ ++ // Check for cheaper optimizations. ++ if (!((Top0->getOpcode() == ISD::SIGN_EXTEND) && ++ (Top1->getOpcode() == ISD::SIGN_EXTEND))) ++ return SDValue(); ++ if (!((Top0->getOperand(0)->getOpcode() == ISD::ADD) && ++ (Top1->getOperand(0)->getOpcode() == ISD::ADD))) ++ return SDValue(); ++ ++ SDValue Op_a0 = Top0->getOperand(0); ++ SDValue Op_a1 = Top1->getOperand(0); ++ for (int i = 0; i < 2; i++) { ++ if (!((Op_a0->getOperand(i)->getOpcode() == ISD::BUILD_VECTOR) && ++ (Op_a1->getOperand(i)->getOpcode() == ISD::BUILD_VECTOR))) ++ return SDValue(); ++ } ++ ++ SDValue Ops_b[] = {Op_a0->getOperand(0), Op_a0->getOperand(1), ++ Op_a1->getOperand(0), Op_a1->getOperand(1)}; ++ for (int i = 0; i < 4; i++) { ++ if (Ops_b[i]->getNumOperands() != 2) ++ return SDValue(); ++ } ++ ++ // Currently only a single case is handled, and more optimization scenarios ++ // will be added in the future. ++ SDValue Ops_e[] = {Ops_b[0]->getOperand(0), Ops_b[0]->getOperand(1), ++ Ops_b[2]->getOperand(0), Ops_b[2]->getOperand(1), ++ Ops_b[1]->getOperand(0), Ops_b[1]->getOperand(1), ++ Ops_b[3]->getOperand(0), Ops_b[3]->getOperand(1)}; ++ for (int i = 0; i < 8; i++) { ++ if (dyn_cast(Ops_e[i])) ++ return SDValue(); ++ if (i < 4) { ++ if (cast(Ops_e[i]->getOperand(1))->getSExtValue() != ++ (2 * i)) ++ return SDValue(); ++ } else { ++ if (cast(Ops_e[i]->getOperand(1))->getSExtValue() != ++ (2 * i - 7)) ++ return SDValue(); ++ } ++ } ++ ++ for (int i = 0; i < 5; i = i + 4) { ++ if (!((Ops_e[i]->getOperand(0) == Ops_e[i + 1]->getOperand(0)) && ++ (Ops_e[i + 1]->getOperand(0) == Ops_e[i + 2]->getOperand(0)) && ++ (Ops_e[i + 2]->getOperand(0) == Ops_e[i + 3]->getOperand(0)))) ++ return SDValue(); ++ } ++ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_D_W, DL, MVT::v4i64, ++ Ops_e[6]->getOperand(0), ++ Ops_e[0]->getOperand(0)), ++ 0); ++} ++ ++static SDValue performParity(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ SDLoc DL(N); ++ SDValue T = N->getOperand(0); ++ if (!(N->getValueType(0).isSimple() && T->getValueType(0).isSimple())) ++ return SDValue(); ++ ++ if (DCI.isAfterLegalizeDAG()) ++ return SDValue(); ++ ++ SDValue Ops[4]; ++ bool pos_e = false; ++ bool pos_o = false; ++ ++ for (int i = 0; i < 4; i++) { ++ Ops[i] = T->getOperand(i); ++ if (!Ops[i]->getValueType(0).isSimple()) ++ return SDValue(); ++ if (Ops[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT) ++ return SDValue(); ++ ++ if (!dyn_cast(Ops[i]->getOperand(1))) ++ return SDValue(); ++ ++ if (cast(Ops[i]->getOperand(1))->getSExtValue() == ++ (2 * i)) { ++ pos_e = true; ++ } else if (cast(Ops[i]->getOperand(1))->getSExtValue() == ++ (2 * i + 1)) { ++ pos_o = true; ++ } else ++ return SDValue(); ++ } ++ ++ if (!(N->getSimpleValueType(0).SimpleTy == MVT::v4i64 && ++ T->getSimpleValueType(0).SimpleTy == MVT::v4i32)) ++ return SDValue(); ++ ++ for (int j = 0; j < 3; j++) { ++ if (Ops[j]->getOperand(0) != Ops[j + 1]->getOperand(0)) ++ return SDValue(); ++ } ++ if (pos_e) { ++ if (N->getOpcode() == ISD::SIGN_EXTEND) { ++ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVADDWEV_D_W, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(1), ++ Ops[0]->getOperand(0)->getOperand(0)), ++ 0); ++ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWEV_D_W, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(0), ++ Ops[0]->getOperand(0)->getOperand(1)), ++ 0); ++ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { ++ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVADDWEV_D_WU, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(1), ++ Ops[0]->getOperand(0)->getOperand(0)), ++ 0); ++ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWEV_D_WU, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(0), ++ Ops[0]->getOperand(0)->getOperand(1)), ++ 0); ++ } ++ } else if (pos_o) { ++ if (N->getOpcode() == ISD::SIGN_EXTEND) { ++ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVADDWOD_D_W, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(1), ++ Ops[0]->getOperand(0)->getOperand(0)), ++ 0); ++ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWOD_D_W, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(0), ++ Ops[0]->getOperand(0)->getOperand(1)), ++ 0); ++ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { ++ if (Ops[0]->getOperand(0)->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVADDWOD_D_WU, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(1), ++ Ops[0]->getOperand(0)->getOperand(0)), ++ 0); ++ else if (Ops[0]->getOperand(0)->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVSUBWOD_D_WU, DL, ++ MVT::v4i64, ++ Ops[0]->getOperand(0)->getOperand(0), ++ Ops[0]->getOperand(0)->getOperand(1)), ++ 0); ++ } ++ } else ++ return SDValue(); ++ ++ return SDValue(); ++} ++ ++// Optimize zero extension and sign extension of data ++static SDValue performExtend(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ if (!Subtarget.hasLASX()) ++ return SDValue(); ++ ++ SDLoc DL(N); ++ SDValue T = N->getOperand(0); ++ ++ if (T->getOpcode() == ISD::BUILD_VECTOR) ++ return performParity(N, DAG, DCI, Subtarget); ++ ++ if (T->getOpcode() != ISD::ADD && T->getOpcode() != ISD::SUB) ++ return SDValue(); ++ ++ SDValue T0 = T->getOperand(0); ++ SDValue T1 = T->getOperand(1); ++ ++ if (!(T0->getOpcode() == ISD::BUILD_VECTOR && ++ T1->getOpcode() == ISD::BUILD_VECTOR)) ++ return SDValue(); ++ ++ if (DCI.isAfterLegalizeDAG()) ++ return SDValue(); ++ ++ if (!(T->getValueType(0).isSimple() && T0->getValueType(0).isSimple() && ++ T1->getValueType(0).isSimple() && N->getValueType(0).isSimple())) ++ return SDValue(); ++ ++ if (!(N->getSimpleValueType(0).SimpleTy == MVT::v4i64 && ++ T->getSimpleValueType(0).SimpleTy == MVT::v4i32 && ++ T0->getSimpleValueType(0).SimpleTy == MVT::v4i32 && ++ T1->getSimpleValueType(0).SimpleTy == MVT::v4i32)) ++ return SDValue(); ++ ++ SDValue Opse0[4]; ++ SDValue Opse1[4]; ++ ++ for (int i = 0; i < 4; i++) { ++ if (T->getOpcode() == ISD::ADD) { ++ Opse0[i] = T1->getOperand(i); ++ Opse1[i] = T0->getOperand(i); ++ } else if (T->getOpcode() == ISD::SUB) { ++ Opse0[i] = T0->getOperand(i); ++ Opse1[i] = T1->getOperand(i); ++ } ++ ++ if (Opse0[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT || ++ Opse1[i]->getOpcode() != ISD::EXTRACT_VECTOR_ELT) ++ return SDValue(); ++ ++ if (!(dyn_cast(Opse0[i]->getOperand(1)) && ++ dyn_cast(Opse1[i]->getOperand(1)))) ++ return SDValue(); ++ ++ if (cast(Opse0[i]->getOperand(1))->getSExtValue() != ++ (2 * i + 1) || ++ cast(Opse1[i]->getOperand(1))->getSExtValue() != ++ (2 * i)) ++ return SDValue(); ++ ++ if (i > 0 && (Opse0[i]->getOperand(0) != Opse0[i - 1]->getOperand(0) || ++ Opse1[i]->getOperand(0) != Opse1[i - 1]->getOperand(0))) ++ return SDValue(); ++ } ++ ++ if (N->getOpcode() == ISD::SIGN_EXTEND) { ++ if (T->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_D_W, DL, MVT::v4i64, ++ Opse0[0]->getOperand(0), ++ Opse1[0]->getOperand(0)), ++ 0); ++ else if (T->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVHSUBW_D_W, DL, MVT::v4i64, ++ Opse0[0]->getOperand(0), ++ Opse1[0]->getOperand(0)), ++ 0); ++ } else if (N->getOpcode() == ISD::ZERO_EXTEND) { ++ if (T->getOpcode() == ISD::ADD) ++ return SDValue(DAG.getMachineNode(LoongArch::XVHADDW_DU_WU, DL, ++ MVT::v4i64, Opse0[0]->getOperand(0), ++ Opse1[0]->getOperand(0)), ++ 0); ++ else if (T->getOpcode() == ISD::SUB) ++ return SDValue(DAG.getMachineNode(LoongArch::XVHSUBW_DU_WU, DL, ++ MVT::v4i64, Opse0[0]->getOperand(0), ++ Opse1[0]->getOperand(0)), ++ 0); ++ } ++ ++ return SDValue(); ++} ++ ++static SDValue performSIGN_EXTENDCombine(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ assert((N->getOpcode() == ISD::SIGN_EXTEND) && "Need ISD::SIGN_EXTEND"); ++ ++ SDLoc DL(N); ++ SDValue Top = N->getOperand(0); ++ ++ SDValue Res; ++ if (Res = performExtend(N, DAG, DCI, Subtarget)) ++ return Res; ++ ++ if (!(Top->getOpcode() == ISD::CopyFromReg)) ++ return SDValue(); ++ ++ if ((Top->getOperand(0)->getOpcode() == ISD::EntryToken) && ++ (N->getValueType(0) == MVT::i64)) { ++ ++ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); ++ SDNode *Res = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64); ++ ++ Res = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::i64, ++ SDValue(Res, 0), Top, SubReg); ++ ++ return SDValue(Res, 0); ++ } ++ ++ return SDValue(); ++} ++ ++static SDValue performZERO_EXTENDCombine(SDNode *N, SelectionDAG &DAG, ++ TargetLowering::DAGCombinerInfo &DCI, ++ const LoongArchSubtarget &Subtarget) { ++ ++ assert((N->getOpcode() == ISD::ZERO_EXTEND) && "Need ISD::ZERO_EXTEND"); ++ ++ SDLoc DL(N); ++ ++ SDValue Res; ++ if (Res = performExtend(N, DAG, DCI, Subtarget)) ++ return Res; ++ ++ return SDValue(); ++} ++ ++SDValue LoongArchTargetLowering:: ++PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { ++ SelectionDAG &DAG = DCI.DAG; ++ SDValue Val; ++ ++ switch (N->getOpcode()) { ++ default: break; + case ISD::AND: + return performANDCombine(N, DAG, DCI, Subtarget); + case ISD::OR: + return performORCombine(N, DAG, DCI, Subtarget); ++ case ISD::XOR: ++ return performXORCombine(N, DAG, Subtarget); ++ case ISD::MUL: ++ return performMULCombine(N, DAG, DCI, this, Subtarget); ++ case ISD::SRA: ++ return performSRACombine(N, DAG, DCI, Subtarget); ++ case ISD::SELECT: ++ return performSELECTCombine(N, DAG, DCI, Subtarget); ++ case ISD::VSELECT: ++ return performVSELECTCombine(N, DAG); ++ case ISD::CONCAT_VECTORS: ++ return performCONCAT_VECTORSCombine(N, DAG, DCI, Subtarget); ++ case ISD::SIGN_EXTEND: ++ return performSIGN_EXTENDCombine(N, DAG, DCI, Subtarget); ++ case ISD::ZERO_EXTEND: ++ return performZERO_EXTENDCombine(N, DAG, DCI, Subtarget); ++ case ISD::ADD: ++ case ISD::SUB: ++ case ISD::SHL: + case ISD::SRL: +- return performSRLCombine(N, DAG, DCI, Subtarget); ++ return performLogicCombine(N, DAG, Subtarget); ++ } ++ return SDValue(); ++} ++ ++static SDValue lowerLSXSplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { ++ EVT ResVecTy = Op->getValueType(0); ++ EVT ViaVecTy = ResVecTy; ++ SDLoc DL(Op); ++ ++ // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and ++ // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating ++ // lanes. ++ SDValue LaneA = Op->getOperand(OpNr); ++ SDValue LaneB; ++ ++ if (ResVecTy == MVT::v2i64) { ++ // In case of the index being passed as an immediate value, set the upper ++ // lane to 0 so that the splati.d instruction can be matched. ++ if (isa(LaneA)) ++ LaneB = DAG.getConstant(0, DL, MVT::i32); ++ // Having the index passed in a register, set the upper lane to the same ++ // value as the lower - this results in the BUILD_VECTOR node not being ++ // expanded through stack. This way we are able to pattern match the set of ++ // nodes created here to splat.d. ++ else ++ LaneB = LaneA; ++ ViaVecTy = MVT::v4i32; ++ } else ++ LaneB = LaneA; ++ ++ SDValue Ops[16] = {LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, ++ LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB}; ++ ++ SDValue Result = DAG.getBuildVector( ++ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); ++ ++ if (ViaVecTy != ResVecTy) { ++ SDValue One = DAG.getConstant(1, DL, ViaVecTy); ++ Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, ++ DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One)); ++ } ++ ++ return Result; ++} ++ ++static SDValue lowerLSXSplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, ++ bool IsSigned = false) { ++ return DAG.getConstant( ++ APInt(Op->getValueType(0).getScalarType().getSizeInBits(), ++ Op->getConstantOperandVal(ImmOp), IsSigned), ++ SDLoc(Op), Op->getValueType(0)); ++} ++ ++static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, ++ SelectionDAG &DAG) { ++ EVT ViaVecTy = VecTy; ++ SDValue SplatValueA = SplatValue; ++ SDValue SplatValueB = SplatValue; ++ SDLoc DL(SplatValue); ++ ++ if (VecTy == MVT::v2i64) { ++ // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's. ++ ViaVecTy = MVT::v4i32; ++ ++ SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue); ++ SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue, ++ DAG.getConstant(32, DL, MVT::i32)); ++ SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB); ++ } ++ ++ SDValue Ops[32] = {SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB, ++ SplatValueA, SplatValueB, SplatValueA, SplatValueB}; ++ ++ SDValue Result = DAG.getBuildVector( ++ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); ++ ++ if (VecTy != ViaVecTy) ++ Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result); ++ ++ return Result; ++} ++ ++static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) { ++ SDLoc DL(Op); ++ EVT ResTy = Op->getValueType(0); ++ SDValue Vec = Op->getOperand(2); ++ MVT ResEltTy = ++ (ResTy == MVT::v2i64 || ResTy == MVT::v4i64) ? MVT::i64 : MVT::i32; ++ SDValue ConstValue = ++ DAG.getConstant(Vec.getScalarValueSizeInBits() - 1, DL, ResEltTy); ++ SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, DAG); ++ ++ return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec); ++} ++ ++static SDValue lowerLSXBitClear(SDValue Op, SelectionDAG &DAG) { ++ EVT ResTy = Op->getValueType(0); ++ SDLoc DL(Op); ++ SDValue One = DAG.getConstant(1, DL, ResTy); ++ SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG)); ++ ++ return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), ++ DAG.getNOT(DL, Bit, ResTy)); ++} ++ ++static SDValue lowerLSXLoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Address = Op->getOperand(2); ++ SDValue Offset = Op->getOperand(3); ++ EVT ResTy = Op->getValueType(0); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), ++ /* Alignment = */ 16); ++} ++ ++static SDValue lowerLASXLoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Address = Op->getOperand(2); ++ SDValue Offset = Op->getOperand(3); ++ EVT ResTy = Op->getValueType(0); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), ++ /* Alignment = */ 32); ++} ++ ++static SDValue lowerLASXVLDRIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Address = Op->getOperand(2); ++ SDValue Offset = Op->getOperand(3); ++ EVT ResTy = Op->getValueType(0); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ SDValue Load = DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), ++ /* Alignment = */ 32); ++ return DAG.getNode(LoongArchISD::XVBROADCAST, DL, ++ DAG.getVTList(ResTy, MVT::Other), Load); ++} ++ ++static SDValue lowerLSXVLDRIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Address = Op->getOperand(2); ++ SDValue Offset = Op->getOperand(3); ++ EVT ResTy = Op->getValueType(0); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ SDValue Load = DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), ++ /* Alignment = */ 16); ++ return DAG.getNode(LoongArchISD::VBROADCAST, DL, ++ DAG.getVTList(ResTy, MVT::Other), Load); ++} ++ ++static SDValue lowerLSXStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Value = Op->getOperand(2); ++ SDValue Address = Op->getOperand(3); ++ SDValue Offset = Op->getOperand(4); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ ++ return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), ++ /* Alignment = */ 16); ++} ++ ++static SDValue lowerLASXStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, ++ const LoongArchSubtarget &Subtarget) { ++ SDLoc DL(Op); ++ SDValue ChainIn = Op->getOperand(0); ++ SDValue Value = Op->getOperand(2); ++ SDValue Address = Op->getOperand(3); ++ SDValue Offset = Op->getOperand(4); ++ EVT PtrTy = Address->getValueType(0); ++ ++ // For LP64 addresses have the underlying type MVT::i64. This intrinsic ++ // however takes an i32 signed constant offset. The actual type of the ++ // intrinsic is a scaled signed i12. ++ if (Subtarget.isABI_LP64()) ++ Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); ++ ++ Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); ++ ++ return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), ++ /* Alignment = */ 32); ++} ++ ++static SDValue LowerSUINT_TO_FP(unsigned ExtOpcode, SDValue Op, SelectionDAG &DAG) { ++ ++ EVT ResTy = Op->getValueType(0); ++ SDValue Op0 = Op->getOperand(0); ++ EVT ViaTy = Op0->getValueType(0); ++ SDLoc DL(Op); ++ ++ if (!ResTy.isVector()) { ++ if(ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) ++ return DAG.getNode(ISD::BITCAST, DL, ResTy, Op0); ++ else if(ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { ++ Op0 = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Op0); ++ return DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, Op0); ++ } else { ++ Op0 = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Op0); ++ return DAG.getNode(ISD::TRUNCATE, DL, MVT::f32, Op0); ++ } ++ ++ } ++ ++ if (ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) { ++ // v4i32 => v4f32 v8i32 => v8f32 ++ // v2i64 => v2f64 v4i64 => v4f64 ++ // do nothing ++ } else if (ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { ++ // v4i32 => v4i64 => v4f64 ++ Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i32, {Op0, Op0}); ++ Op0 = DAG.getNode(ExtOpcode, DL, MVT::v4i64, Op0); ++ } else { ++ // v4i64 => v4f32 ++ SDValue Ops[4]; ++ for (unsigned i = 0; i < 4; i++) { ++ SDValue I64 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op0, ++ DAG.getConstant(i, DL, MVT::i32)); ++ Ops[i] = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, I64); ++ } ++ Op0 = DAG.getBuildVector(MVT::v4i32, DL, makeArrayRef(Ops, 4)); ++ } ++ ++ return Op0; ++} ++ ++static SDValue LowerFP_TO_SUINT(unsigned FPToSUI, unsigned ExtOpcode, ++ SDValue Op, SelectionDAG &DAG) { ++ ++ EVT ResTy = Op->getValueType(0); ++ SDValue Op0 = Op->getOperand(0); ++ EVT ViaTy = Op0->getValueType(0); ++ SDLoc DL(Op); ++ ++ if (ResTy.getScalarSizeInBits() == ViaTy.getScalarSizeInBits()) { ++ // v4f32 => v4i32 v8f32 => v8i32 ++ // v2f64 => v2i64 v4f64 => v4i64 ++ // do nothing ++ Op0 = DAG.getNode(FPToSUI, DL, ResTy, Op0); ++ } else if (ResTy.getScalarSizeInBits() > ViaTy.getScalarSizeInBits()) { ++ // v4f32 => v4i32 => v4i64 ++ Op0 = DAG.getNode(FPToSUI, DL, MVT::v4i32, Op0); ++ Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i32, {Op0, Op0}); ++ Op0 = DAG.getNode(ExtOpcode, DL, MVT::v4i64, Op0); ++ } else { ++ SDValue Ops[4]; ++ Ops[0] = DAG.getNode(FPToSUI, DL, MVT::i32, ++ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, ++ DAG.getConstant(0, DL, MVT::i64))); ++ Ops[1] = DAG.getNode(FPToSUI, DL, MVT::i32, ++ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, ++ DAG.getConstant(1, DL, MVT::i64))); ++ Ops[2] = DAG.getNode(FPToSUI, DL, MVT::i32, ++ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, ++ DAG.getConstant(2, DL, MVT::i64))); ++ Ops[3] = DAG.getNode(FPToSUI, DL, MVT::i32, ++ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f64, Op0, ++ DAG.getConstant(3, DL, MVT::i64))); ++ ++ Op0 = DAG.getBuildVector(MVT::v4i32, DL, makeArrayRef(Ops, 4)); ++ } ++ ++ return Op0; ++} ++ ++// Lower VECTOR_SHUFFLE into SHF (if possible). ++// ++// SHF splits the vector into blocks of four elements, then shuffles these ++// elements according to a <4 x i2> constant (encoded as an integer immediate). ++// ++// It is therefore possible to lower into SHF when the mask takes the form: ++// ++// When undef's appear they are treated as if they were whatever value is ++// necessary in order to fit the above forms. ++// ++// For example: ++// %2 = shufflevector <8 x i16> %0, <8 x i16> undef, ++// <8 x i32> ++// is lowered to: ++// (VSHUF4I_H $v0, $v1, 27) ++// where the 27 comes from: ++// 3 + (2 << 2) + (1 << 4) + (0 << 6) ++static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ int SHFIndices[4] = {-1, -1, -1, -1}; ++ ++ if (Indices.size() < 4) ++ return SDValue(); ++ ++ for (unsigned i = 0; i < 4; ++i) { ++ for (unsigned j = i; j < Indices.size(); j += 4) { ++ int Idx = Indices[j]; ++ ++ // Convert from vector index to 4-element subvector index ++ // If an index refers to an element outside of the subvector then give up ++ if (Idx != -1) { ++ Idx -= 4 * (j / 4); ++ if (Idx < 0 || Idx >= 4) ++ return SDValue(); ++ } ++ ++ // If the mask has an undef, replace it with the current index. ++ // Note that it might still be undef if the current index is also undef ++ if (SHFIndices[i] == -1) ++ SHFIndices[i] = Idx; ++ ++ // Check that non-undef values are the same as in the mask. If they ++ // aren't then give up ++ if (!(Idx == -1 || Idx == SHFIndices[i])) ++ return SDValue(); ++ } ++ } ++ ++ // Calculate the immediate. Replace any remaining undefs with zero ++ APInt Imm(32, 0); ++ for (int i = 3; i >= 0; --i) { ++ int Idx = SHFIndices[i]; ++ ++ if (Idx == -1) ++ Idx = 0; ++ ++ Imm <<= 2; ++ Imm |= Idx & 0x3; ++ } ++ ++ SDLoc DL(Op); ++ return DAG.getNode(LoongArchISD::SHF, DL, ResTy, ++ DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); ++} ++ ++/// Determine whether a range fits a regular pattern of values. ++/// This function accounts for the possibility of jumping over the End iterator. ++template ++static bool ++fitsRegularPattern(typename SmallVectorImpl::const_iterator Begin, ++ unsigned CheckStride, ++ typename SmallVectorImpl::const_iterator End, ++ ValType ExpectedIndex, unsigned ExpectedIndexStride) { ++ auto &I = Begin; ++ ++ while (I != End) { ++ if (*I != -1 && *I != ExpectedIndex) ++ return false; ++ ExpectedIndex += ExpectedIndexStride; ++ ++ // Incrementing past End is undefined behaviour so we must increment one ++ // step at a time and check for End at each step. ++ for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I) ++ ; // Empty loop body. ++ } ++ return true; ++} ++ ++// Determine whether VECTOR_SHUFFLE is a VREPLVEI. ++// ++// It is a VREPLVEI when the mask is: ++// ++// where x is any valid index. ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above form. ++static bool isVECTOR_SHUFFLE_VREPLVEI(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ int SplatIndex = -1; ++ for (const auto &V : Indices) { ++ if (V != -1) { ++ SplatIndex = V; ++ break; ++ } ++ } ++ ++ return fitsRegularPattern(Indices.begin(), 1, Indices.end(), SplatIndex, ++ 0); ++} ++ ++// Lower VECTOR_SHUFFLE into VPACKEV (if possible). ++// ++// VPACKEV interleaves the even elements from each vector. ++// ++// It is possible to lower into VPACKEV when the mask consists of two of the ++// following forms interleaved: ++// <0, 2, 4, ...> ++// ++// where n is the number of elements in the vector. ++// For example: ++// <0, 0, 2, 2, 4, 4, ...> ++// <0, n, 2, n+2, 4, n+4, ...> ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VPACKEV(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ ++ // Check even elements are taken from the even elements of one half or the ++ // other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin, 2, End, 0, 2)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 2)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ // Check odd elements are taken from the even elements of one half or the ++ // other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin + 1, 2, End, 0, 2)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 2)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPACKEV, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VPACKOD (if possible). ++// ++// VPACKOD interleaves the odd elements from each vector. ++// ++// It is possible to lower into VPACKOD when the mask consists of two of the ++// following forms interleaved: ++// <1, 3, 5, ...> ++// ++// where n is the number of elements in the vector. ++// For example: ++// <1, 1, 3, 3, 5, 5, ...> ++// <1, n+1, 3, n+3, 5, n+5, ...> ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VPACKOD(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ ++ // Check even elements are taken from the odd elements of one half or the ++ // other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin, 2, End, 1, 2)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + 1, 2)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ // Check odd elements are taken from the odd elements of one half or the ++ // other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin + 1, 2, End, 1, 2)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + 1, 2)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPACKOD, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VILVL (if possible). ++// ++// VILVL interleaves consecutive elements from the right (lowest-indexed) half ++// of each vector. ++// ++// It is possible to lower into VILVL when the mask consists of two of the ++// following forms interleaved: ++// <0, 1, 2, ...> ++// ++// where n is the number of elements in the vector. ++// For example: ++// <0, 0, 1, 1, 2, 2, ...> ++// <0, n, 1, n+1, 2, n+2, ...> ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VILVL(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ ++ // Check even elements are taken from the right (lowest-indexed) elements of ++ // one half or the other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin, 2, End, 0, 1)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 1)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ // Check odd elements are taken from the right (lowest-indexed) elements of ++ // one half or the other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin + 1, 2, End, 0, 1)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 1)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VILVL, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VILVH (if possible). ++// ++// VILVH interleaves consecutive elements from the left (highest-indexed) half ++// of each vector. ++// ++// It is possible to lower into VILVH when the mask consists of two of the ++// following forms interleaved: ++// ++// ++// where n is the number of elements in the vector and x is half n. ++// For example: ++// ++// ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VILVH(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ unsigned HalfSize = Indices.size() / 2; ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ ++ // Check even elements are taken from the left (highest-indexed) elements of ++ // one half or the other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin, 2, End, HalfSize, 1)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + HalfSize, 1)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ // Check odd elements are taken from the left (highest-indexed) elements of ++ // one half or the other and pick an operand accordingly. ++ if (fitsRegularPattern(Begin + 1, 2, End, HalfSize, 1)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + HalfSize, ++ 1)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VILVH, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VPICKEV (if possible). ++// ++// VPICKEV copies the even elements of each vector into the result vector. ++// ++// It is possible to lower into VPICKEV when the mask consists of two of the ++// following forms concatenated: ++// <0, 2, 4, ...> ++// ++// where n is the number of elements in the vector. ++// For example: ++// <0, 2, 4, ..., 0, 2, 4, ...> ++// <0, 2, 4, ..., n, n+2, n+4, ...> ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VPICKEV(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &Mid = Indices.begin() + Indices.size() / 2; ++ const auto &End = Indices.end(); ++ ++ if (fitsRegularPattern(Begin, 1, Mid, 0, 2)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 1, Mid, Indices.size(), 2)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Mid, 1, End, 0, 2)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Mid, 1, End, Indices.size(), 2)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPICKEV, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VPICKOD (if possible). ++// ++// VPICKOD copies the odd elements of each vector into the result vector. ++// ++// It is possible to lower into VPICKOD when the mask consists of two of the ++// following forms concatenated: ++// <1, 3, 5, ...> ++// ++// where n is the number of elements in the vector. ++// For example: ++// <1, 3, 5, ..., 1, 3, 5, ...> ++// <1, 3, 5, ..., n+1, n+3, n+5, ...> ++// ++// When undef's appear in the mask they are treated as if they were whatever ++// value is necessary in order to fit the above forms. ++static SDValue lowerVECTOR_SHUFFLE_VPICKOD(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Vj; ++ SDValue Vk; ++ const auto &Begin = Indices.begin(); ++ const auto &Mid = Indices.begin() + Indices.size() / 2; ++ const auto &End = Indices.end(); ++ ++ if (fitsRegularPattern(Begin, 1, Mid, 1, 2)) ++ Vj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 1, Mid, Indices.size() + 1, 2)) ++ Vj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Mid, 1, End, 1, 2)) ++ Vk = Op->getOperand(0); ++ else if (fitsRegularPattern(Mid, 1, End, Indices.size() + 1, 2)) ++ Vk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPICKOD, SDLoc(Op), ResTy, Vk, Vj); ++} ++ ++// Lower VECTOR_SHUFFLE into VSHF. ++// ++// This mostly consists of converting the shuffle indices in Indices into a ++// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is ++// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example, ++// if the type is v8i16 and all the indices are less than 8 then the second ++// operand is unused and can be replaced with anything. We choose to replace it ++// with the used operand since this reduces the number of instructions overall. ++static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ SmallVector Ops; ++ SDValue Op0; ++ SDValue Op1; ++ EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger(); ++ EVT MaskEltTy = MaskVecTy.getVectorElementType(); ++ bool Using1stVec = false; ++ bool Using2ndVec = false; ++ SDLoc DL(Op); ++ int ResTyNumElts = ResTy.getVectorNumElements(); ++ ++ for (int i = 0; i < ResTyNumElts; ++i) { ++ // Idx == -1 means UNDEF ++ int Idx = Indices[i]; ++ ++ if (0 <= Idx && Idx < ResTyNumElts) ++ Using1stVec = true; ++ if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2) ++ Using2ndVec = true; ++ } ++ ++ for (SmallVector::iterator I = Indices.begin(); I != Indices.end(); ++ ++I) ++ Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy)); ++ ++ SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops); ++ ++ if (Using1stVec && Using2ndVec) { ++ Op0 = Op->getOperand(0); ++ Op1 = Op->getOperand(1); ++ } else if (Using1stVec) ++ Op0 = Op1 = Op->getOperand(0); ++ else if (Using2ndVec) ++ Op0 = Op1 = Op->getOperand(1); ++ else ++ llvm_unreachable("shuffle vector mask references neither vector operand?"); ++ ++ // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion. ++ // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11> ++ // VSHF concatenates the vectors in a bitwise fashion: ++ // <0b00, 0b01> + <0b10, 0b11> -> ++ // 0b0100 + 0b1110 -> 0b01001110 ++ // <0b10, 0b11, 0b00, 0b01> ++ // We must therefore swap the operands to get the correct result. ++ return DAG.getNode(LoongArchISD::VSHF, DL, ResTy, MaskVec, Op1, Op0); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVILVL(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ unsigned HalfSize = Indices.size() / 2; ++ ++ if (fitsRegularPattern(Begin, 2, End - HalfSize, 0, 1) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize, 1)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End - HalfSize, Indices.size(), ++ 1) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, ++ Indices.size() + HalfSize, 1)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, 0, 1) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize, 1)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, Indices.size(), ++ 1) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, ++ Indices.size() + HalfSize, 1)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VILVL, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVILVH(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ unsigned HalfSize = Indices.size() / 2; ++ unsigned LeftSize = HalfSize / 2; ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ ++ if (fitsRegularPattern(Begin, 2, End - HalfSize, HalfSize - LeftSize, ++ 1) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize + LeftSize, 1)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End - HalfSize, ++ Indices.size() + HalfSize - LeftSize, 1) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, ++ Indices.size() + HalfSize + LeftSize, 1)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, HalfSize - LeftSize, ++ 1) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize + LeftSize, ++ 1)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End - HalfSize, ++ Indices.size() + HalfSize - LeftSize, 1) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, ++ Indices.size() + HalfSize + LeftSize, 1)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VILVH, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ unsigned HalfSize = Indices.size() / 2; ++ ++ if (fitsRegularPattern(Begin, 2, End, 0, 2) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize, 2)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size(), 2) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, ++ Indices.size() + HalfSize, 2)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Begin + 1, 2, End, 0, 2) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize, 2)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size(), 2) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, ++ Indices.size() + HalfSize, 2)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPACKEV, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &End = Indices.end(); ++ unsigned HalfSize = Indices.size() / 2; ++ ++ if (fitsRegularPattern(Begin, 2, End, 1, 2) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, HalfSize + 1, 2)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 2, End, Indices.size() + 1, 2) && ++ fitsRegularPattern(Begin + HalfSize, 2, End, ++ Indices.size() + HalfSize + 1, 2)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(Begin + 1, 2, End, 1, 2) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, HalfSize + 1, 2)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin + 1, 2, End, Indices.size() + 1, 2) && ++ fitsRegularPattern(Begin + 1 + HalfSize, 2, End, ++ Indices.size() + HalfSize + 1, 2)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPACKOD, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static bool isVECTOR_SHUFFLE_XVREPLVEI(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ unsigned HalfSize = Indices.size() / 2; ++ ++ for (unsigned i = 0; i < HalfSize; i++) { ++ if (Indices[i] == -1 || Indices[HalfSize + i] == -1) ++ return false; ++ if (Indices[0] != Indices[i] || Indices[HalfSize] != Indices[HalfSize + i]) ++ return false; ++ } ++ return true; ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &LeftMid = Indices.begin() + Indices.size() / 4; ++ const auto &End = Indices.end(); ++ const auto &RightMid = Indices.end() - Indices.size() / 4; ++ const auto &Mid = Indices.begin() + Indices.size() / 2; ++ unsigned HalfSize = Indices.size() / 2; ++ ++ if (fitsRegularPattern(Begin, 1, LeftMid, 0, 2) && ++ fitsRegularPattern(Mid, 1, RightMid, HalfSize, 2)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 1, LeftMid, Indices.size(), 2) && ++ fitsRegularPattern(Mid, 1, RightMid, Indices.size() + HalfSize, ++ 2)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(LeftMid, 1, Mid, 0, 2) && ++ fitsRegularPattern(RightMid, 1, End, HalfSize, 2)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(LeftMid, 1, Mid, Indices.size(), 2) && ++ fitsRegularPattern(RightMid, 1, End, Indices.size() + HalfSize, ++ 2)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPICKEV, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ assert((Indices.size() % 2) == 0); ++ ++ SDValue Xj; ++ SDValue Xk; ++ const auto &Begin = Indices.begin(); ++ const auto &LeftMid = Indices.begin() + Indices.size() / 4; ++ const auto &Mid = Indices.begin() + Indices.size() / 2; ++ const auto &RightMid = Indices.end() - Indices.size() / 4; ++ const auto &End = Indices.end(); ++ unsigned HalfSize = Indices.size() / 2; ++ ++ if (fitsRegularPattern(Begin, 1, LeftMid, 1, 2) && ++ fitsRegularPattern(Mid, 1, RightMid, HalfSize + 1, 2)) ++ Xj = Op->getOperand(0); ++ else if (fitsRegularPattern(Begin, 1, LeftMid, Indices.size() + 1, 2) && ++ fitsRegularPattern(Mid, 1, RightMid, ++ Indices.size() + HalfSize + 1, 2)) ++ Xj = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ if (fitsRegularPattern(LeftMid, 1, Mid, 1, 2) && ++ fitsRegularPattern(RightMid, 1, End, HalfSize + 1, 2)) ++ Xk = Op->getOperand(0); ++ else if (fitsRegularPattern(LeftMid, 1, Mid, Indices.size() + 1, 2) && ++ fitsRegularPattern(RightMid, 1, End, ++ Indices.size() + HalfSize + 1, 2)) ++ Xk = Op->getOperand(1); ++ else ++ return SDValue(); ++ ++ return DAG.getNode(LoongArchISD::VPICKOD, SDLoc(Op), ResTy, Xk, Xj); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XSHF(SDValue Op, EVT ResTy, ++ SmallVector Indices, ++ SelectionDAG &DAG) { ++ int SHFIndices[4] = {-1, -1, -1, -1}; ++ ++ // If the size of the mask is 4, it should not be converted to SHF node, ++ // because SHF only corresponds to type b/h/w instruction but no type d. ++ if (Indices.size() <= 4) ++ return SDValue(); ++ ++ int HalfSize = Indices.size() / 2; ++ for (int i = 0; i < 4; ++i) { ++ for (int j = i; j < HalfSize; j += 4) { ++ int Idx = Indices[j]; ++ // check mxshf ++ if (Idx + HalfSize != Indices[j + HalfSize]) ++ return SDValue(); ++ ++ // Convert from vector index to 4-element subvector index ++ // If an index refers to an element outside of the subvector then give up ++ if (Idx != -1) { ++ Idx -= 4 * (j / 4); ++ if (Idx < 0 || Idx >= 4) ++ return SDValue(); ++ } ++ ++ // If the mask has an undef, replace it with the current index. ++ // Note that it might still be undef if the current index is also undef ++ if (SHFIndices[i] == -1) ++ SHFIndices[i] = Idx; ++ ++ // Check that non-undef values are the same as in the mask. If they ++ // aren't then give up ++ if (!(Idx == -1 || Idx == SHFIndices[i])) ++ return SDValue(); ++ } ++ } ++ ++ // Calculate the immediate. Replace any remaining undefs with zero ++ APInt Imm(32, 0); ++ for (int i = 3; i >= 0; --i) { ++ int Idx = SHFIndices[i]; ++ ++ if (Idx == -1) ++ Idx = 0; ++ ++ Imm <<= 2; ++ Imm |= Idx & 0x3; ++ } ++ SDLoc DL(Op); ++ return DAG.getNode(LoongArchISD::SHF, DL, ResTy, ++ DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); ++} ++ ++static bool isConstantOrUndef(const SDValue Op) { ++ if (Op->isUndef()) ++ return true; ++ if (isa(Op)) ++ return true; ++ if (isa(Op)) ++ return true; ++ return false; ++} ++ ++static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) { ++ for (unsigned i = 0; i < Op->getNumOperands(); ++i) ++ if (isConstantOrUndef(Op->getOperand(i))) ++ return true; ++ return false; ++} ++ ++static bool isLASXBySplatBitSize(unsigned SplatBitSize, EVT &ViaVecTy) { ++ switch (SplatBitSize) { ++ default: ++ return false; ++ case 8: ++ ViaVecTy = MVT::v32i8; ++ break; ++ case 16: ++ ViaVecTy = MVT::v16i16; ++ break; ++ case 32: ++ ViaVecTy = MVT::v8i32; ++ break; ++ case 64: ++ ViaVecTy = MVT::v4i64; ++ break; ++ case 128: ++ // There's no fill.q to fall back on for 64-bit values ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool isLSXBySplatBitSize(unsigned SplatBitSize, EVT &ViaVecTy) { ++ switch (SplatBitSize) { ++ default: ++ return false; ++ case 8: ++ ViaVecTy = MVT::v16i8; ++ break; ++ case 16: ++ ViaVecTy = MVT::v8i16; ++ break; ++ case 32: ++ ViaVecTy = MVT::v4i32; ++ break; ++ case 64: ++ // There's no fill.d to fall back on for 64-bit values ++ return false; ++ } ++ ++ return true; ++} ++ ++bool LoongArchTargetLowering::isCheapToSpeculateCttz() const { return true; } ++ ++bool LoongArchTargetLowering::isCheapToSpeculateCtlz() const { return true; } ++ ++void LoongArchTargetLowering::LowerOperationWrapper( ++ SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { ++ SDValue Res = LowerOperation(SDValue(N, 0), DAG); ++ ++ for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) ++ Results.push_back(Res.getValue(I)); ++} ++ ++void LoongArchTargetLowering::ReplaceNodeResults( ++ SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { ++ return LowerOperationWrapper(N, Results, DAG); ++} ++ ++SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, ++ SelectionDAG &DAG) const { ++ switch (Op.getOpcode()) { ++ case ISD::STORE: ++ return lowerSTORE(Op, DAG); ++ case ISD::INTRINSIC_WO_CHAIN: ++ return lowerINTRINSIC_WO_CHAIN(Op, DAG); ++ case ISD::INTRINSIC_W_CHAIN: ++ return lowerINTRINSIC_W_CHAIN(Op, DAG); ++ case ISD::INTRINSIC_VOID: ++ return lowerINTRINSIC_VOID(Op, DAG); ++ case ISD::EXTRACT_VECTOR_ELT: ++ return lowerEXTRACT_VECTOR_ELT(Op, DAG); ++ case ISD::INSERT_VECTOR_ELT: ++ return lowerINSERT_VECTOR_ELT(Op, DAG); ++ case ISD::BUILD_VECTOR: ++ return lowerBUILD_VECTOR(Op, DAG); ++ case ISD::VECTOR_SHUFFLE: ++ return lowerVECTOR_SHUFFLE(Op, DAG); ++ case ISD::UINT_TO_FP: ++ return lowerUINT_TO_FP(Op, DAG); ++ case ISD::SINT_TO_FP: ++ return lowerSINT_TO_FP(Op, DAG); ++ case ISD::FP_TO_UINT: ++ return lowerFP_TO_UINT(Op, DAG); ++ case ISD::FP_TO_SINT: ++ return lowerFP_TO_SINT(Op, DAG); ++ case ISD::BRCOND: ++ return lowerBRCOND(Op, DAG); ++ case ISD::ConstantPool: ++ return lowerConstantPool(Op, DAG); ++ case ISD::GlobalAddress: ++ return lowerGlobalAddress(Op, DAG); ++ case ISD::BlockAddress: ++ return lowerBlockAddress(Op, DAG); ++ case ISD::GlobalTLSAddress: ++ return lowerGlobalTLSAddress(Op, DAG); ++ case ISD::JumpTable: ++ return lowerJumpTable(Op, DAG); ++ case ISD::SELECT: ++ return lowerSELECT(Op, DAG); ++ case ISD::SETCC: ++ return lowerSETCC(Op, DAG); ++ case ISD::VASTART: ++ return lowerVASTART(Op, DAG); ++ case ISD::VAARG: ++ return lowerVAARG(Op, DAG); ++ case ISD::FRAMEADDR: ++ return lowerFRAMEADDR(Op, DAG); ++ case ISD::RETURNADDR: ++ return lowerRETURNADDR(Op, DAG); ++ case ISD::EH_RETURN: ++ return lowerEH_RETURN(Op, DAG); ++ case ISD::ATOMIC_FENCE: ++ return lowerATOMIC_FENCE(Op, DAG); ++ case ISD::SHL_PARTS: ++ return lowerShiftLeftParts(Op, DAG); ++ case ISD::SRA_PARTS: ++ return lowerShiftRightParts(Op, DAG, true); ++ case ISD::SRL_PARTS: ++ return lowerShiftRightParts(Op, DAG, false); ++ case ISD::EH_DWARF_CFA: ++ return lowerEH_DWARF_CFA(Op, DAG); ++ } ++ return SDValue(); ++} ++ ++//===----------------------------------------------------------------------===// ++// Lower helper functions ++//===----------------------------------------------------------------------===// ++ ++template ++SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG, ++ bool IsLocal) const { ++ SDLoc DL(N); ++ EVT Ty = getPointerTy(DAG.getDataLayout()); ++ ++ if (isPositionIndependent()) { ++ SDValue Addr = getTargetNode(N, Ty, DAG, 0U); ++ if (IsLocal) ++ // Use PC-relative addressing to access the symbol. ++ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrLocal, DL, Ty, Addr), ++ 0); ++ ++ // Use PC-relative addressing to access the GOT for this symbol, then load ++ // the address from the GOT. ++ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrGlobal, DL, Ty, Addr), ++ 0); ++ } ++ ++ SDValue Addr = getTargetNode(N, Ty, DAG, 0U); ++ return SDValue(DAG.getMachineNode(LoongArch::LoadAddrLocal, DL, Ty, Addr), 0); ++} ++ ++// addLiveIn - This helper function adds the specified physical register to the ++// MachineFunction as a live in value. It also creates a corresponding ++// virtual register for it. ++static unsigned addLiveIn(MachineFunction &MF, unsigned PReg, ++ const TargetRegisterClass *RC) { ++ unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); ++ MF.getRegInfo().addLiveIn(PReg, VReg); ++ return VReg; ++} ++ ++static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, ++ MachineBasicBlock &MBB, ++ const TargetInstrInfo &TII, ++ bool Is64Bit) { ++ if (NoZeroDivCheck) ++ return &MBB; ++ ++ // Insert pseudo instruction(PseudoTEQ), will expand: ++ // beq $divisor_reg, $zero, 8 ++ // break 7 ++ MachineBasicBlock::iterator I(MI); ++ MachineInstrBuilder MIB; ++ MachineOperand &Divisor = MI.getOperand(2); ++ unsigned TeqOp = LoongArch::PseudoTEQ; ++ ++ MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(), TII.get(TeqOp)) ++ .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())); ++ ++ // Use the 32-bit sub-register if this is a 64-bit division. ++ //if (Is64Bit) ++ // MIB->getOperand(0).setSubReg(LoongArch::sub_32); ++ ++ // Clear Divisor's kill flag. ++ Divisor.setIsKill(false); ++ ++ // We would normally delete the original instruction here but in this case ++ // we only needed to inject an additional instruction rather than replace it. ++ ++ return &MBB; ++} ++ ++MachineBasicBlock * ++LoongArchTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ switch (MI.getOpcode()) { ++ default: ++ llvm_unreachable("Unexpected instr type to insert"); ++ case LoongArch::FILL_FW_PSEUDO: ++ return emitFILL_FW(MI, BB); ++ case LoongArch::FILL_FD_PSEUDO: ++ return emitFILL_FD(MI, BB); ++ case LoongArch::SNZ_B_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_B); ++ case LoongArch::SNZ_H_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_H); ++ case LoongArch::SNZ_W_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_W); ++ case LoongArch::SNZ_D_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETALLNEZ_D); ++ case LoongArch::SNZ_V_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETNEZ_V); ++ case LoongArch::SZ_B_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_B); ++ case LoongArch::SZ_H_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_H); ++ case LoongArch::SZ_W_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_W); ++ case LoongArch::SZ_D_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETANYEQZ_D); ++ case LoongArch::SZ_V_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::VSETEQZ_V); ++ case LoongArch::XSNZ_B_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_B); ++ case LoongArch::XSNZ_H_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_H); ++ case LoongArch::XSNZ_W_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_W); ++ case LoongArch::XSNZ_D_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETALLNEZ_D); ++ case LoongArch::XSNZ_V_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETNEZ_V); ++ case LoongArch::XSZ_B_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_B); ++ case LoongArch::XSZ_H_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_H); ++ case LoongArch::XSZ_W_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_W); ++ case LoongArch::XSZ_D_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETANYEQZ_D); ++ case LoongArch::XSZ_V_PSEUDO: ++ return emitLSXCBranchPseudo(MI, BB, LoongArch::XVSETEQZ_V); ++ case LoongArch::INSERT_FW_PSEUDO: ++ return emitINSERT_FW(MI, BB); ++ case LoongArch::INSERT_FD_PSEUDO: ++ return emitINSERT_FD(MI, BB); ++ case LoongArch::XINSERT_H_PSEUDO: ++ return emitXINSERT_BH(MI, BB, 2); ++ case LoongArch::XCOPY_FW_PSEUDO: ++ return emitXCOPY_FW(MI, BB); ++ case LoongArch::XCOPY_FD_PSEUDO: ++ return emitXCOPY_FD(MI, BB); ++ case LoongArch::XINSERT_FW_PSEUDO: ++ return emitXINSERT_FW(MI, BB); ++ case LoongArch::COPY_FW_PSEUDO: ++ return emitCOPY_FW(MI, BB); ++ case LoongArch::XFILL_FW_PSEUDO: ++ return emitXFILL_FW(MI, BB); ++ case LoongArch::XFILL_FD_PSEUDO: ++ return emitXFILL_FD(MI, BB); ++ case LoongArch::COPY_FD_PSEUDO: ++ return emitCOPY_FD(MI, BB); ++ case LoongArch::XINSERT_FD_PSEUDO: ++ return emitXINSERT_FD(MI, BB); ++ case LoongArch::XINSERT_B_PSEUDO: ++ return emitXINSERT_BH(MI, BB, 1); ++ case LoongArch::CONCAT_VECTORS_B_PSEUDO: ++ return emitCONCAT_VECTORS(MI, BB, 1); ++ case LoongArch::CONCAT_VECTORS_H_PSEUDO: ++ return emitCONCAT_VECTORS(MI, BB, 2); ++ case LoongArch::CONCAT_VECTORS_W_PSEUDO: ++ case LoongArch::CONCAT_VECTORS_FW_PSEUDO: ++ return emitCONCAT_VECTORS(MI, BB, 4); ++ case LoongArch::CONCAT_VECTORS_D_PSEUDO: ++ case LoongArch::CONCAT_VECTORS_FD_PSEUDO: ++ return emitCONCAT_VECTORS(MI, BB, 8); ++ case LoongArch::XCOPY_FW_GPR_PSEUDO: ++ return emitXCOPY_FW_GPR(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_ADD_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_ADD_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_ADD_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_ADD_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_AND_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_AND_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_AND_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_AND_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_OR_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_OR_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_OR_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_OR_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_XOR_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_XOR_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_XOR_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_XOR_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_NAND_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_NAND_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_NAND_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_NAND_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_SUB_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_SUB_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_SUB_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_SUB_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_SWAP_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_SWAP_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_SWAP_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_SWAP_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::XINSERT_B_VIDX_PSEUDO: ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO: ++ return emitXINSERT_B(MI, BB); ++ case LoongArch::INSERT_H_VIDX64_PSEUDO: ++ return emitINSERT_H_VIDX(MI, BB); ++ case LoongArch::XINSERT_FW_VIDX_PSEUDO: ++ return emitXINSERT_DF_VIDX(MI, BB, false); ++ case LoongArch::XINSERT_FW_VIDX64_PSEUDO: ++ return emitXINSERT_DF_VIDX(MI, BB, true); ++ ++ case LoongArch::ATOMIC_LOAD_MAX_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_MAX_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_MAX_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_MAX_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_MIN_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_MIN_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_MIN_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_MIN_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_UMAX_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_UMAX_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_UMAX_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_UMAX_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_LOAD_UMIN_I8: ++ return emitAtomicBinaryPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_LOAD_UMIN_I16: ++ return emitAtomicBinaryPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_LOAD_UMIN_I32: ++ return emitAtomicBinary(MI, BB); ++ case LoongArch::ATOMIC_LOAD_UMIN_I64: ++ return emitAtomicBinary(MI, BB); ++ ++ case LoongArch::ATOMIC_CMP_SWAP_I8: ++ return emitAtomicCmpSwapPartword(MI, BB, 1); ++ case LoongArch::ATOMIC_CMP_SWAP_I16: ++ return emitAtomicCmpSwapPartword(MI, BB, 2); ++ case LoongArch::ATOMIC_CMP_SWAP_I32: ++ return emitAtomicCmpSwap(MI, BB); ++ case LoongArch::ATOMIC_CMP_SWAP_I64: ++ return emitAtomicCmpSwap(MI, BB); ++ ++ case LoongArch::PseudoSELECT_I: ++ case LoongArch::PseudoSELECT_I64: ++ case LoongArch::PseudoSELECT_S: ++ case LoongArch::PseudoSELECT_D64: ++ return emitPseudoSELECT(MI, BB, false, LoongArch::BNE32); ++ ++ case LoongArch::PseudoSELECTFP_T_I: ++ case LoongArch::PseudoSELECTFP_T_I64: ++ return emitPseudoSELECT(MI, BB, true, LoongArch::BCNEZ); ++ ++ case LoongArch::PseudoSELECTFP_F_I: ++ case LoongArch::PseudoSELECTFP_F_I64: ++ return emitPseudoSELECT(MI, BB, true, LoongArch::BCEQZ); ++ case LoongArch::DIV_W: ++ case LoongArch::DIV_WU: ++ case LoongArch::MOD_W: ++ case LoongArch::MOD_WU: ++ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); ++ case LoongArch::DIV_D: ++ case LoongArch::DIV_DU: ++ case LoongArch::MOD_D: ++ case LoongArch::MOD_DU: ++ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); ++ } ++} ++ ++MachineBasicBlock *LoongArchTargetLowering::emitXINSERT_DF_VIDX( ++ MachineInstr &MI, MachineBasicBlock *BB, bool IsGPR64) const { ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned insertOp; ++ insertOp = IsGPR64 ? LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA ++ : LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA; ++ ++ unsigned DstReg = MI.getOperand(0).getReg(); ++ unsigned SrcVecReg = MI.getOperand(1).getReg(); ++ unsigned LaneReg = MI.getOperand(2).getReg(); ++ unsigned SrcValReg = MI.getOperand(3).getReg(); ++ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); ++ ++ MachineBasicBlock::iterator II(MI); ++ ++ unsigned VecCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); ++ unsigned LaneCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); ++ unsigned ValCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); ++ ++ const TargetRegisterClass *RC = ++ IsGPR64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ unsigned RI = RegInfo.createVirtualRegister(RC); ++ ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) ++ .addImm(0) ++ .addReg(SrcValReg) ++ .addImm(LoongArch::sub_lo); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::XVPICKVE2GR_W), Rj) ++ .addReg(Xj) ++ .addImm(0); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); ++ ++ BuildMI(*BB, II, DL, TII->get(insertOp)) ++ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) ++ .addReg(VecCopy) ++ .addReg(LaneCopy) ++ .addReg(ValCopy) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(RI, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(Rj, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead); ++ ++ MI.eraseFromParent(); ++ ++ return BB; ++} ++ ++MachineBasicBlock * ++LoongArchTargetLowering::emitINSERT_H_VIDX(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned insertOp; ++ unsigned isGP64 = 0; ++ switch (MI.getOpcode()) { ++ case LoongArch::INSERT_H_VIDX64_PSEUDO: ++ isGP64 = 1; ++ insertOp = LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA; ++ break; ++ default: ++ llvm_unreachable("Unknown pseudo vector for replacement!"); ++ } ++ ++ unsigned DstReg = MI.getOperand(0).getReg(); ++ unsigned SrcVecReg = MI.getOperand(1).getReg(); ++ unsigned LaneReg = MI.getOperand(2).getReg(); ++ unsigned SrcValReg = MI.getOperand(3).getReg(); ++ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); ++ ++ MachineBasicBlock::iterator II(MI); ++ ++ unsigned VecCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); ++ unsigned LaneCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); ++ unsigned ValCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); ++ ++ const TargetRegisterClass *RC = ++ isGP64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ unsigned RI = RegInfo.createVirtualRegister(RC); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); ++ ++ BuildMI(*BB, II, DL, TII->get(insertOp)) ++ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) ++ .addReg(VecCopy) ++ .addReg(LaneCopy) ++ .addReg(ValCopy) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(RI, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead); ++ ++ MI.eraseFromParent(); ++ ++ return BB; ++} ++ ++MachineBasicBlock * ++LoongArchTargetLowering::emitXINSERT_B(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned insertOp; ++ unsigned isGP64 = 0; ++ switch (MI.getOpcode()) { ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO: ++ isGP64 = 1; ++ insertOp = LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA; ++ break; ++ case LoongArch::XINSERT_B_VIDX_PSEUDO: ++ insertOp = LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA; ++ break; ++ default: ++ llvm_unreachable("Unknown pseudo vector for replacement!"); ++ } ++ ++ unsigned DstReg = MI.getOperand(0).getReg(); ++ unsigned SrcVecReg = MI.getOperand(1).getReg(); ++ unsigned LaneReg = MI.getOperand(2).getReg(); ++ unsigned SrcValReg = MI.getOperand(3).getReg(); ++ unsigned Dest = RegInfo.createVirtualRegister(RegInfo.getRegClass(DstReg)); ++ ++ MachineBasicBlock::iterator II(MI); ++ ++ unsigned VecCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcVecReg)); ++ unsigned LaneCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(LaneReg)); ++ unsigned ValCopy = ++ RegInfo.createVirtualRegister(RegInfo.getRegClass(SrcValReg)); ++ const TargetRegisterClass *RC = ++ isGP64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ unsigned Rimm = RegInfo.createVirtualRegister(RC); ++ unsigned R4r = RegInfo.createVirtualRegister(RC); ++ unsigned Rib = RegInfo.createVirtualRegister(RC); ++ unsigned Ris = RegInfo.createVirtualRegister(RC); ++ unsigned R7b1 = RegInfo.createVirtualRegister(RC); ++ unsigned R7b2 = RegInfo.createVirtualRegister(RC); ++ unsigned R7b3 = RegInfo.createVirtualRegister(RC); ++ unsigned RI = RegInfo.createVirtualRegister(RC); ++ ++ unsigned R7r80_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R7r80l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R7r81_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R7r81l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R7r82_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R7r82l_3 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned R70 = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned tmp_Dst73 = ++ RegInfo.createVirtualRegister(&LoongArch::LASX256BRegClass); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), VecCopy).addReg(SrcVecReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), LaneCopy).addReg(LaneReg); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), ValCopy).addReg(SrcValReg); ++ ++ BuildMI(*BB, II, DL, TII->get(insertOp)) ++ .addReg(DstReg, RegState::Define | RegState::EarlyClobber) ++ .addReg(VecCopy) ++ .addReg(LaneCopy) ++ .addReg(ValCopy) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R4r, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(Rib, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(Ris, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7b1, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7b2, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7b3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r80_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r80l_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r81_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r81l_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r82_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R7r82l_3, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(RI, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(tmp_Dst73, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(Rimm, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead) ++ .addReg(R70, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead); ++ ++ MI.eraseFromParent(); ++ ++ return BB; ++} ++ ++const TargetRegisterClass * ++LoongArchTargetLowering::getRepRegClassFor(MVT VT) const { ++ return TargetLowering::getRepRegClassFor(VT); ++} ++ ++// This function also handles LoongArch::ATOMIC_SWAP_I32 (when BinOpcode == 0), and ++// LoongArch::ATOMIC_LOAD_NAND_I32 (when Nand == true) ++MachineBasicBlock * ++LoongArchTargetLowering::emitAtomicBinary(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned AtomicOp; ++ switch (MI.getOpcode()) { ++ case LoongArch::ATOMIC_LOAD_ADD_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_NAND_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_SWAP_I32: ++ AtomicOp = LoongArch::ATOMIC_SWAP_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I32: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I32_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_ADD_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_NAND_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_SWAP_I64: ++ AtomicOp = LoongArch::ATOMIC_SWAP_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I64_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I64: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I64_POSTRA; ++ break; ++ default: ++ llvm_unreachable("Unknown pseudo atomic for replacement!"); ++ } ++ ++ unsigned OldVal = MI.getOperand(0).getReg(); ++ unsigned Ptr = MI.getOperand(1).getReg(); ++ unsigned Incr = MI.getOperand(2).getReg(); ++ unsigned Scratch = RegInfo.createVirtualRegister(RegInfo.getRegClass(OldVal)); ++ ++ MachineBasicBlock::iterator II(MI); ++ ++ // The scratch registers here with the EarlyClobber | Define | Implicit ++ // flags is used to persuade the register allocator and the machine ++ // verifier to accept the usage of this register. This has to be a real ++ // register which has an UNDEF value but is dead after the instruction which ++ // is unique among the registers chosen for the instruction. ++ ++ // The EarlyClobber flag has the semantic properties that the operand it is ++ // attached to is clobbered before the rest of the inputs are read. Hence it ++ // must be unique among the operands to the instruction. ++ // The Define flag is needed to coerce the machine verifier that an Undef ++ // value isn't a problem. ++ // The Dead flag is needed as the value in scratch isn't used by any other ++ // instruction. Kill isn't used as Dead is more precise. ++ // The implicit flag is here due to the interaction between the other flags ++ // and the machine verifier. ++ ++ // For correctness purpose, a new pseudo is introduced here. We need this ++ // new pseudo, so that FastRegisterAllocator does not see an ll/sc sequence ++ // that is spread over >1 basic blocks. A register allocator which ++ // introduces (or any codegen infact) a store, can violate the expectations ++ // of the hardware. ++ // ++ // An atomic read-modify-write sequence starts with a linked load ++ // instruction and ends with a store conditional instruction. The atomic ++ // read-modify-write sequence fails if any of the following conditions ++ // occur between the execution of ll and sc: ++ // * A coherent store is completed by another process or coherent I/O ++ // module into the block of synchronizable physical memory containing ++ // the word. The size and alignment of the block is ++ // implementation-dependent. ++ // * A coherent store is executed between an LL and SC sequence on the ++ // same processor to the block of synchornizable physical memory ++ // containing the word. ++ // ++ ++ unsigned PtrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Ptr)); ++ unsigned IncrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Incr)); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), IncrCopy).addReg(Incr); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), PtrCopy).addReg(Ptr); ++ ++ BuildMI(*BB, II, DL, TII->get(AtomicOp)) ++ .addReg(OldVal, RegState::Define | RegState::EarlyClobber) ++ .addReg(PtrCopy) ++ .addReg(IncrCopy) ++ .addReg(Scratch, RegState::Define | RegState::EarlyClobber | ++ RegState::Implicit | RegState::Dead); ++ ++ if(MI.getOpcode() == LoongArch::ATOMIC_LOAD_NAND_I32 ++ || MI.getOpcode() == LoongArch::ATOMIC_LOAD_NAND_I64){ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); ++ } ++ ++ MI.eraseFromParent(); ++ ++ return BB; ++} ++ ++MachineBasicBlock *LoongArchTargetLowering::emitSignExtendToI32InReg( ++ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, ++ unsigned SrcReg) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ const DebugLoc &DL = MI.getDebugLoc(); ++ if (Size == 1) { ++ BuildMI(BB, DL, TII->get(LoongArch::EXT_W_B32), DstReg).addReg(SrcReg); ++ return BB; ++ } ++ ++ if (Size == 2) { ++ BuildMI(BB, DL, TII->get(LoongArch::EXT_W_H32), DstReg).addReg(SrcReg); ++ return BB; ++ } ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); ++ unsigned ScrReg = RegInfo.createVirtualRegister(RC); ++ ++ assert(Size < 32); ++ int64_t ShiftImm = 32 - (Size * 8); ++ ++ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ScrReg).addReg(SrcReg).addImm(ShiftImm); ++ BuildMI(BB, DL, TII->get(LoongArch::SRAI_W), DstReg).addReg(ScrReg).addImm(ShiftImm); ++ ++ return BB; ++} ++ ++MachineBasicBlock *LoongArchTargetLowering::emitAtomicBinaryPartword( ++ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { ++ assert((Size == 1 || Size == 2) && ++ "Unsupported size for EmitAtomicBinaryPartial."); ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); ++ const bool ArePtrs64bit = ABI.ArePtrs64bit(); ++ const TargetRegisterClass *RCp = ++ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned Dest = MI.getOperand(0).getReg(); ++ unsigned Ptr = MI.getOperand(1).getReg(); ++ unsigned Incr = MI.getOperand(2).getReg(); ++ ++ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); ++ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); ++ unsigned Mask = RegInfo.createVirtualRegister(RC); ++ unsigned Mask2 = RegInfo.createVirtualRegister(RC); ++ unsigned Incr2 = RegInfo.createVirtualRegister(RC); ++ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); ++ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); ++ unsigned MaskUpper = RegInfo.createVirtualRegister(RC); ++ unsigned MaskUppest = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch2 = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch3 = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch4 = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch5 = RegInfo.createVirtualRegister(RC); ++ ++ unsigned AtomicOp = 0; ++ switch (MI.getOpcode()) { ++ case LoongArch::ATOMIC_LOAD_NAND_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_NAND_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_NAND_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_SWAP_I8: ++ AtomicOp = LoongArch::ATOMIC_SWAP_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_SWAP_I16: ++ AtomicOp = LoongArch::ATOMIC_SWAP_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MAX_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MAX_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_MIN_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_MIN_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMAX_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMAX_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_UMIN_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_ADD_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_ADD_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_ADD_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_SUB_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_SUB_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_AND_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_AND_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_OR_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_OR_I16_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I8: ++ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I8_POSTRA; ++ break; ++ case LoongArch::ATOMIC_LOAD_XOR_I16: ++ AtomicOp = LoongArch::ATOMIC_LOAD_XOR_I16_POSTRA; ++ break; ++ default: ++ llvm_unreachable("Unknown subword atomic pseudo for expansion!"); ++ } ++ ++ // insert new blocks after the current block ++ const BasicBlock *LLVM_BB = BB->getBasicBlock(); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB->getIterator(); ++ MF->insert(It, exitMBB); ++ ++ // Transfer the remainder of BB and its successor edges to exitMBB. ++ exitMBB->splice(exitMBB->begin(), BB, ++ std::next(MachineBasicBlock::iterator(MI)), BB->end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(BB); ++ ++ BB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ // thisMBB: ++ // addiu masklsb2,$0,-4 # 0xfffffffc ++ // and alignedaddr,ptr,masklsb2 ++ // andi ptrlsb2,ptr,3 ++ // sll shiftamt,ptrlsb2,3 ++ // ori maskupper,$0,255 # 0xff ++ // sll mask,maskupper,shiftamt ++ // nor mask2,$0,mask ++ // sll incr2,incr,shiftamt ++ ++ int64_t MaskImm = (Size == 1) ? 255 : 4095; ++ BuildMI(BB, DL, TII->get(ABI.GetPtrAddiOp()), MaskLSB2) ++ .addReg(ABI.GetNullPtr()).addImm(-4); ++ BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr) ++ .addReg(Ptr).addReg(MaskLSB2); ++ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), PtrLSB2) ++ .addReg(Ptr, 0, ArePtrs64bit ? LoongArch::sub_32 : 0).addImm(3); ++ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ShiftAmt).addReg(PtrLSB2).addImm(3); ++ ++ if(MaskImm==4095){ ++ BuildMI(BB, DL, TII->get(LoongArch::LU12I_W32), MaskUppest).addImm(0xf); ++ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) ++ .addReg(MaskUppest).addImm(MaskImm); ++ } ++ else{ ++ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) ++ .addReg(LoongArch::ZERO).addImm(MaskImm); ++ } ++ ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Mask) ++ .addReg(MaskUpper).addReg(ShiftAmt); ++ BuildMI(BB, DL, TII->get(LoongArch::NOR32), Mask2).addReg(LoongArch::ZERO).addReg(Mask); ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Incr2).addReg(Incr).addReg(ShiftAmt); ++ ++ ++ // The purposes of the flags on the scratch registers is explained in ++ // emitAtomicBinary. In summary, we need a scratch register which is going to ++ // be undef, that is unique among registers chosen for the instruction. ++ ++ BuildMI(BB, DL, TII->get(LoongArch::DBAR)).addImm(0); ++ BuildMI(BB, DL, TII->get(AtomicOp)) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber) ++ .addReg(AlignedAddr) ++ .addReg(Incr2) ++ .addReg(Mask) ++ .addReg(Mask2) ++ .addReg(ShiftAmt) ++ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit) ++ .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit) ++ .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit) ++ .addReg(Scratch4, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit) ++ .addReg(Scratch5, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit); ++ ++ MI.eraseFromParent(); // The instruction is gone now. ++ ++ return exitMBB; ++} ++ ++// Lower atomic compare and swap to a pseudo instruction, taking care to ++// define a scratch register for the pseudo instruction's expansion. The ++// instruction is expanded after the register allocator as to prevent ++// the insertion of stores between the linked load and the store conditional. ++ ++MachineBasicBlock * ++LoongArchTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert((MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 || ++ MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I64) && ++ "Unsupported atomic psseudo for EmitAtomicCmpSwap."); ++ ++ const unsigned Size = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 ? 4 : 8; ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &MRI = MF->getRegInfo(); ++ const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned AtomicOp = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I32 ++ ? LoongArch::ATOMIC_CMP_SWAP_I32_POSTRA ++ : LoongArch::ATOMIC_CMP_SWAP_I64_POSTRA; ++ unsigned Dest = MI.getOperand(0).getReg(); ++ unsigned Ptr = MI.getOperand(1).getReg(); ++ unsigned OldVal = MI.getOperand(2).getReg(); ++ unsigned NewVal = MI.getOperand(3).getReg(); ++ ++ unsigned Scratch = MRI.createVirtualRegister(RC); ++ MachineBasicBlock::iterator II(MI); ++ ++ // We need to create copies of the various registers and kill them at the ++ // atomic pseudo. If the copies are not made, when the atomic is expanded ++ // after fast register allocation, the spills will end up outside of the ++ // blocks that their values are defined in, causing livein errors. ++ ++ unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); ++ unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); ++ unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), PtrCopy).addReg(Ptr); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), OldValCopy).addReg(OldVal); ++ BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), NewValCopy).addReg(NewVal); ++ ++ // The purposes of the flags on the scratch registers is explained in ++ // emitAtomicBinary. In summary, we need a scratch register which is going to ++ // be undef, that is unique among registers chosen for the instruction. ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(0); ++ BuildMI(*BB, II, DL, TII->get(AtomicOp)) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber) ++ .addReg(PtrCopy, RegState::Kill) ++ .addReg(OldValCopy, RegState::Kill) ++ .addReg(NewValCopy, RegState::Kill) ++ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit); ++ ++ BuildMI(*BB, II, DL, TII->get(LoongArch::DBAR)).addImm(DBAR_HINT); ++ ++ MI.eraseFromParent(); // The instruction is gone now. ++ ++ return BB; ++} ++ ++MachineBasicBlock *LoongArchTargetLowering::emitAtomicCmpSwapPartword( ++ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { ++ assert((Size == 1 || Size == 2) && ++ "Unsupported size for EmitAtomicCmpSwapPartial."); ++ ++ MachineFunction *MF = BB->getParent(); ++ MachineRegisterInfo &RegInfo = MF->getRegInfo(); ++ const TargetRegisterClass *RC = getRegClassFor(MVT::i32); ++ const bool ArePtrs64bit = ABI.ArePtrs64bit(); ++ const TargetRegisterClass *RCp = ++ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned Dest = MI.getOperand(0).getReg(); ++ unsigned Ptr = MI.getOperand(1).getReg(); ++ unsigned CmpVal = MI.getOperand(2).getReg(); ++ unsigned NewVal = MI.getOperand(3).getReg(); ++ ++ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); ++ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); ++ unsigned Mask = RegInfo.createVirtualRegister(RC); ++ unsigned Mask2 = RegInfo.createVirtualRegister(RC); ++ unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); ++ unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); ++ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); ++ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); ++ unsigned MaskUpper = RegInfo.createVirtualRegister(RC); ++ unsigned MaskUppest = RegInfo.createVirtualRegister(RC); ++ unsigned Mask3 = RegInfo.createVirtualRegister(RC); ++ unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); ++ unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); ++ unsigned AtomicOp = MI.getOpcode() == LoongArch::ATOMIC_CMP_SWAP_I8 ++ ? LoongArch::ATOMIC_CMP_SWAP_I8_POSTRA ++ : LoongArch::ATOMIC_CMP_SWAP_I16_POSTRA; ++ ++ // The scratch registers here with the EarlyClobber | Define | Dead | Implicit ++ // flags are used to coerce the register allocator and the machine verifier to ++ // accept the usage of these registers. ++ // The EarlyClobber flag has the semantic properties that the operand it is ++ // attached to is clobbered before the rest of the inputs are read. Hence it ++ // must be unique among the operands to the instruction. ++ // The Define flag is needed to coerce the machine verifier that an Undef ++ // value isn't a problem. ++ // The Dead flag is needed as the value in scratch isn't used by any other ++ // instruction. Kill isn't used as Dead is more precise. ++ unsigned Scratch = RegInfo.createVirtualRegister(RC); ++ unsigned Scratch2 = RegInfo.createVirtualRegister(RC); ++ ++ // insert new blocks after the current block ++ const BasicBlock *LLVM_BB = BB->getBasicBlock(); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB->getIterator(); ++ MF->insert(It, exitMBB); ++ ++ // Transfer the remainder of BB and its successor edges to exitMBB. ++ exitMBB->splice(exitMBB->begin(), BB, ++ std::next(MachineBasicBlock::iterator(MI)), BB->end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(BB); ++ ++ BB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ // thisMBB: ++ // addiu masklsb2,$0,-4 # 0xfffffffc ++ // and alignedaddr,ptr,masklsb2 ++ // andi ptrlsb2,ptr,3 ++ // xori ptrlsb2,ptrlsb2,3 # Only for BE ++ // sll shiftamt,ptrlsb2,3 ++ // ori maskupper,$0,255 # 0xff ++ // sll mask,maskupper,shiftamt ++ // nor mask2,$0,mask ++ // andi maskedcmpval,cmpval,255 ++ // sll shiftedcmpval,maskedcmpval,shiftamt ++ // andi maskednewval,newval,255 ++ // sll shiftednewval,maskednewval,shiftamt ++ ++ int64_t MaskImm = (Size == 1) ? 255 : 4095; ++ BuildMI(BB, DL, TII->get(ArePtrs64bit ? LoongArch::ADDI_D : LoongArch::ADDI_W), MaskLSB2) ++ .addReg(ABI.GetNullPtr()).addImm(-4); ++ BuildMI(BB, DL, TII->get(ArePtrs64bit ? LoongArch::AND : LoongArch::AND32), AlignedAddr) ++ .addReg(Ptr).addReg(MaskLSB2); ++ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), PtrLSB2) ++ .addReg(Ptr, 0, ArePtrs64bit ? LoongArch::sub_32 : 0).addImm(3); ++ BuildMI(BB, DL, TII->get(LoongArch::SLLI_W), ShiftAmt).addReg(PtrLSB2).addImm(3); ++ ++ if(MaskImm==4095){ ++ BuildMI(BB, DL, TII->get(LoongArch::LU12I_W32), MaskUppest).addImm(0xf); ++ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) ++ .addReg(MaskUppest).addImm(MaskImm); ++ } ++ else{ ++ BuildMI(BB, DL, TII->get(LoongArch::ORI32), MaskUpper) ++ .addReg(LoongArch::ZERO).addImm(MaskImm); ++ } ++ ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), Mask) ++ .addReg(MaskUpper).addReg(ShiftAmt); ++ BuildMI(BB, DL, TII->get(LoongArch::NOR32), Mask2).addReg(LoongArch::ZERO).addReg(Mask); ++ if(MaskImm==4095){ ++ BuildMI(BB, DL, TII->get(LoongArch::ORI32), Mask3) ++ .addReg(MaskUppest).addImm(MaskImm); ++ BuildMI(BB, DL, TII->get(LoongArch::AND32), MaskedCmpVal) ++ .addReg(CmpVal).addReg(Mask3); ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedCmpVal) ++ .addReg(MaskedCmpVal).addReg(ShiftAmt); ++ BuildMI(BB, DL, TII->get(LoongArch::AND32), MaskedNewVal) ++ .addReg(NewVal).addReg(Mask3); ++ } ++ else{ ++ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), MaskedCmpVal) ++ .addReg(CmpVal).addImm(MaskImm); ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedCmpVal) ++ .addReg(MaskedCmpVal).addReg(ShiftAmt); ++ BuildMI(BB, DL, TII->get(LoongArch::ANDI32), MaskedNewVal) ++ .addReg(NewVal).addImm(MaskImm); ++ } ++ BuildMI(BB, DL, TII->get(LoongArch::SLL_W), ShiftedNewVal) ++ .addReg(MaskedNewVal).addReg(ShiftAmt); ++ ++ // The purposes of the flags on the scratch registers are explained in ++ // emitAtomicBinary. In summary, we need a scratch register which is going to ++ // be undef, that is unique among the register chosen for the instruction. ++ ++ BuildMI(BB, DL, TII->get(LoongArch::DBAR)).addImm(0); ++ BuildMI(BB, DL, TII->get(AtomicOp)) ++ .addReg(Dest, RegState::Define | RegState::EarlyClobber) ++ .addReg(AlignedAddr) ++ .addReg(Mask) ++ .addReg(ShiftedCmpVal) ++ .addReg(Mask2) ++ .addReg(ShiftedNewVal) ++ .addReg(ShiftAmt) ++ .addReg(Scratch, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit) ++ .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | ++ RegState::Dead | RegState::Implicit); ++ ++ MI.eraseFromParent(); // The instruction is gone now. ++ ++ return exitMBB; ++} ++ ++SDValue LoongArchTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { ++ // The first operand is the chain, the second is the condition, the third is ++ // the block to branch to if the condition is true. ++ SDValue Chain = Op.getOperand(0); ++ SDValue Dest = Op.getOperand(2); ++ SDLoc DL(Op); ++ ++ SDValue CondRes = createFPCmp(DAG, Op.getOperand(1)); ++ ++ // Return if flag is not set by a floating point comparison. ++ if (CondRes.getOpcode() != LoongArchISD::FPCmp) ++ return Op; ++ ++ SDValue CCNode = CondRes.getOperand(2); ++ LoongArch::CondCode CC = ++ (LoongArch::CondCode)cast(CCNode)->getZExtValue(); ++ unsigned Opc = invertFPCondCodeUser(CC) ? LoongArch::BRANCH_F : LoongArch::BRANCH_T; ++ SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32); ++ SDValue FCC0 = DAG.getRegister(LoongArch::FCC0, MVT::i32); ++ return DAG.getNode(LoongArchISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, ++ FCC0, Dest, CondRes); ++} ++ ++SDValue LoongArchTargetLowering::lowerSELECT(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDValue Cond = createFPCmp(DAG, Op.getOperand(0)); ++ ++ // Return if flag is not set by a floating point comparison. ++ if (Cond.getOpcode() != LoongArchISD::FPCmp) ++ return Op; ++ ++ SDValue N1 = Op.getOperand(1); ++ SDValue N2 = Op.getOperand(2); ++ SDLoc DL(Op); ++ ++ ConstantSDNode *CC = cast(Cond.getOperand(2)); ++ bool invert = invertFPCondCodeUser((LoongArch::CondCode)CC->getSExtValue()); ++ SDValue FCC = DAG.getRegister(LoongArch::FCC0, MVT::i32); ++ ++ if (Op->getSimpleValueType(0).SimpleTy == MVT::f64 || ++ Op->getSimpleValueType(0).SimpleTy == MVT::f32) { ++ if (invert) ++ return DAG.getNode(LoongArchISD::FSEL, DL, N1.getValueType(), N1, FCC, N2, ++ Cond); ++ else ++ return DAG.getNode(LoongArchISD::FSEL, DL, N1.getValueType(), N2, FCC, N1, ++ Cond); ++ ++ } else ++ return Op; ++} ++ ++SDValue LoongArchTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { ++ SDValue Cond = createFPCmp(DAG, Op); ++ ++ assert(Cond.getOpcode() == LoongArchISD::FPCmp && ++ "Floating point operand expected."); ++ ++ SDLoc DL(Op); ++ SDValue True = DAG.getConstant(1, DL, MVT::i32); ++ SDValue False = DAG.getConstant(0, DL, MVT::i32); ++ ++ return createCMovFP(DAG, Cond, True, False, DL); ++} ++ ++SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, ++ SelectionDAG &DAG) const { ++ GlobalAddressSDNode *N = cast(Op); ++ ++ const GlobalValue *GV = N->getGlobal(); ++ bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); ++ SDValue Addr = getAddr(N, DAG, IsLocal); ++ ++ return Addr; ++} ++ ++SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op, ++ SelectionDAG &DAG) const { ++ BlockAddressSDNode *N = cast(Op); ++ ++ return getAddr(N, DAG); ++} ++ ++SDValue LoongArchTargetLowering:: ++lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const ++{ ++ GlobalAddressSDNode *GA = cast(Op); ++ if (DAG.getTarget().useEmulatedTLS()) ++ return LowerToTLSEmulatedModel(GA, DAG); ++ ++ SDLoc DL(GA); ++ const GlobalValue *GV = GA->getGlobal(); ++ EVT PtrVT = getPointerTy(DAG.getDataLayout()); ++ ++ TLSModel::Model model = getTargetMachine().getTLSModel(GV); ++ ++ if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { ++ // General Dynamic TLS Model && Local Dynamic TLS Model ++ unsigned PtrSize = PtrVT.getSizeInBits(); ++ IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); ++ // SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrTy, 0, 0); ++ SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0U); ++ SDValue Load = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_GD , ++ DL, PtrVT, Addr), 0); ++ SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); ++ ++ ArgListTy Args; ++ ArgListEntry Entry; ++ Entry.Node = Load; ++ Entry.Ty = PtrTy; ++ Args.push_back(Entry); ++ ++ TargetLowering::CallLoweringInfo CLI(DAG); ++ CLI.setDebugLoc(DL) ++ .setChain(DAG.getEntryNode()) ++ .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); ++ std::pair CallResult = LowerCallTo(CLI); ++ ++ SDValue Ret = CallResult.first; ++ ++ return Ret; ++ } ++ ++ SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0U); ++ SDValue Offset; ++ if (model == TLSModel::InitialExec) { ++ // Initial Exec TLS Model ++ Offset = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_IE, DL, ++ PtrVT, Addr), 0); ++ } else { ++ // Local Exec TLS Model ++ assert(model == TLSModel::LocalExec); ++ Offset = SDValue(DAG.getMachineNode(LoongArch::LoadAddrTLS_LE, DL, ++ PtrVT, Addr), 0); ++ } ++ ++ SDValue ThreadPointer = DAG.getRegister((PtrVT == MVT::i32) ++ ? LoongArch::TP ++ : LoongArch::TP_64, PtrVT); ++ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Offset); ++} ++ ++SDValue LoongArchTargetLowering:: ++lowerJumpTable(SDValue Op, SelectionDAG &DAG) const ++{ ++ JumpTableSDNode *N = cast(Op); ++ ++ return getAddr(N, DAG); ++} ++ ++SDValue LoongArchTargetLowering:: ++lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ++{ ++ ConstantPoolSDNode *N = cast(Op); ++ ++ return getAddr(N, DAG); ++} ++ ++SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { ++ MachineFunction &MF = DAG.getMachineFunction(); ++ LoongArchFunctionInfo *FuncInfo = MF.getInfo(); ++ ++ SDLoc DL(Op); ++ SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), ++ getPointerTy(MF.getDataLayout())); ++ ++ // vastart just stores the address of the VarArgsFrameIndex slot into the ++ // memory location argument. ++ const Value *SV = cast(Op.getOperand(2))->getValue(); ++ return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), ++ MachinePointerInfo(SV)); ++} ++ ++SDValue LoongArchTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { ++ SDNode *Node = Op.getNode(); ++ EVT VT = Node->getValueType(0); ++ SDValue Chain = Node->getOperand(0); ++ SDValue VAListPtr = Node->getOperand(1); ++ const Align Align = ++ llvm::MaybeAlign(Node->getConstantOperandVal(3)).valueOrOne(); ++ const Value *SV = cast(Node->getOperand(2))->getValue(); ++ SDLoc DL(Node); ++ unsigned ArgSlotSizeInBytes = (ABI.IsLPX32() || ABI.IsLP64()) ? 8 : 4; ++ ++ SDValue VAListLoad = DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, ++ VAListPtr, MachinePointerInfo(SV)); ++ SDValue VAList = VAListLoad; ++ ++ // Re-align the pointer if necessary. ++ // It should only ever be necessary for 64-bit types on LP32 since the minimum ++ // argument alignment is the same as the maximum type alignment for LPX32/LP64. ++ // ++ // FIXME: We currently align too often. The code generator doesn't notice ++ // when the pointer is still aligned from the last va_arg (or pair of ++ // va_args for the i64 on LP32 case). ++ if (Align > getMinStackArgumentAlignment()) { ++ VAList = DAG.getNode( ++ ISD::ADD, DL, VAList.getValueType(), VAList, ++ DAG.getConstant(Align.value() - 1, DL, VAList.getValueType())); ++ ++ VAList = DAG.getNode( ++ ISD::AND, DL, VAList.getValueType(), VAList, ++ DAG.getConstant(-(int64_t)Align.value(), DL, VAList.getValueType())); ++ } ++ ++ // Increment the pointer, VAList, to the next vaarg. ++ auto &TD = DAG.getDataLayout(); ++ unsigned ArgSizeInBytes = ++ TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); ++ SDValue Tmp3 = ++ DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, ++ DAG.getConstant(alignTo(ArgSizeInBytes, ArgSlotSizeInBytes), ++ DL, VAList.getValueType())); ++ // Store the incremented VAList to the legalized pointer ++ Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, ++ MachinePointerInfo(SV)); ++ ++ // Load the actual argument out of the pointer VAList ++ return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo()); ++} ++ ++SDValue LoongArchTargetLowering:: ++lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { ++ // check the depth ++ assert((cast(Op.getOperand(0))->getZExtValue() == 0) && ++ "Frame address can only be determined for current frame."); ++ ++ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); ++ MFI.setFrameAddressIsTaken(true); ++ EVT VT = Op.getValueType(); ++ SDLoc DL(Op); ++ SDValue FrameAddr = DAG.getCopyFromReg( ++ DAG.getEntryNode(), DL, ABI.IsLP64() ? LoongArch::FP_64 : LoongArch::FP, VT); ++ return FrameAddr; ++} ++ ++SDValue LoongArchTargetLowering::lowerRETURNADDR(SDValue Op, ++ SelectionDAG &DAG) const { ++ if (verifyReturnAddressArgumentIsConstant(Op, DAG)) ++ return SDValue(); ++ ++ // check the depth ++ assert((cast(Op.getOperand(0))->getZExtValue() == 0) && ++ "Return address can be determined only for current frame."); ++ ++ MachineFunction &MF = DAG.getMachineFunction(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ MVT VT = Op.getSimpleValueType(); ++ unsigned RA = ABI.IsLP64() ? LoongArch::RA_64 : LoongArch::RA; ++ MFI.setReturnAddressIsTaken(true); ++ ++ // Return RA, which contains the return address. Mark it an implicit live-in. ++ unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); ++ return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT); ++} ++ ++// An EH_RETURN is the result of lowering llvm.eh.return which in turn is ++// generated from __builtin_eh_return (offset, handler) ++// The effect of this is to adjust the stack pointer by "offset" ++// and then branch to "handler". ++SDValue LoongArchTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) ++ const { ++ MachineFunction &MF = DAG.getMachineFunction(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); ++ ++ LoongArchFI->setCallsEhReturn(); ++ SDValue Chain = Op.getOperand(0); ++ SDValue Offset = Op.getOperand(1); ++ SDValue Handler = Op.getOperand(2); ++ SDLoc DL(Op); ++ EVT Ty = ABI.IsLP64() ? MVT::i64 : MVT::i32; ++ ++ // Store stack offset in A1, store jump target in A0. Glue CopyToReg and ++ // EH_RETURN nodes, so that instructions are emitted back-to-back. ++ unsigned OffsetReg = ABI.IsLP64() ? LoongArch::A1_64 : LoongArch::A1; ++ unsigned AddrReg = ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; ++ Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); ++ Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); ++ return DAG.getNode(LoongArchISD::EH_RETURN, DL, MVT::Other, Chain, ++ DAG.getRegister(OffsetReg, Ty), ++ DAG.getRegister(AddrReg, getPointerTy(MF.getDataLayout())), ++ Chain.getValue(1)); ++} ++ ++SDValue LoongArchTargetLowering::lowerATOMIC_FENCE(SDValue Op, ++ SelectionDAG &DAG) const { ++ // FIXME: Need pseudo-fence for 'singlethread' fences ++ // FIXME: Set SType for weaker fences where supported/appropriate. ++ unsigned SType = 0; ++ SDLoc DL(Op); ++ return DAG.getNode(LoongArchISD::DBAR, DL, MVT::Other, Op.getOperand(0), ++ DAG.getConstant(SType, DL, MVT::i32)); ++} ++ ++SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ MVT VT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32; ++ ++ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); ++ SDValue Shamt = Op.getOperand(2); ++ // if shamt < (VT.bits): ++ // lo = (shl lo, shamt) ++ // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) ++ // else: ++ // lo = 0 ++ // hi = (shl lo, shamt[4:0]) ++ SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, ++ DAG.getConstant(-1, DL, MVT::i32)); ++ SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, ++ DAG.getConstant(1, DL, VT)); ++ SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); ++ SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); ++ SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); ++ SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); ++ SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, ++ DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); ++ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ++ DAG.getConstant(0, DL, VT), ShiftLeftLo); ++ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); ++ ++ SDValue Ops[2] = {Lo, Hi}; ++ return DAG.getMergeValues(Ops, DL); ++} ++ ++SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, ++ bool IsSRA) const { ++ SDLoc DL(Op); ++ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); ++ SDValue Shamt = Op.getOperand(2); ++ MVT VT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32; ++ ++ // if shamt < (VT.bits): ++ // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) ++ // if isSRA: ++ // hi = (sra hi, shamt) ++ // else: ++ // hi = (srl hi, shamt) ++ // else: ++ // if isSRA: ++ // lo = (sra hi, shamt[4:0]) ++ // hi = (sra hi, 31) ++ // else: ++ // lo = (srl hi, shamt[4:0]) ++ // hi = 0 ++ SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, ++ DAG.getConstant(-1, DL, MVT::i32)); ++ SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, ++ DAG.getConstant(1, DL, VT)); ++ SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); ++ SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); ++ SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); ++ SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, ++ DL, VT, Hi, Shamt); ++ SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, ++ DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); ++ SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi, ++ DAG.getConstant(VT.getSizeInBits() - 1, DL, VT)); ++ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); ++ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ++ IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi); ++ ++ SDValue Ops[2] = {Lo, Hi}; ++ return DAG.getMergeValues(Ops, DL); ++} ++ ++// Lower (store (fp_to_sint $fp) $ptr) to (store (TruncIntFP $fp), $ptr). ++static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG, ++ bool SingleFloat) { ++ SDValue Val = SD->getValue(); ++ ++ if (Val.getOpcode() != ISD::FP_TO_SINT || ++ (Val.getValueSizeInBits() > 32 && SingleFloat)) ++ return SDValue(); ++ ++ EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits()); ++ SDValue Tr = DAG.getNode(LoongArchISD::TruncIntFP, SDLoc(Val), FPTy, ++ Val.getOperand(0)); ++ return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(), ++ SD->getPointerInfo(), SD->getAlignment(), ++ SD->getMemOperand()->getFlags()); ++} ++ ++SDValue LoongArchTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { ++ StoreSDNode *SD = cast(Op); ++ return lowerFP_TO_SINT_STORE(SD, DAG, Subtarget.isSingleFloat()); ++} ++ ++SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ unsigned Intrinsic = cast(Op->getOperand(0))->getZExtValue(); ++ switch (Intrinsic) { ++ default: ++ return SDValue(); ++ case Intrinsic::loongarch_lsx_vaddi_bu: ++ case Intrinsic::loongarch_lsx_vaddi_hu: ++ case Intrinsic::loongarch_lsx_vaddi_wu: ++ case Intrinsic::loongarch_lsx_vaddi_du: ++ return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1), ++ lowerLSXSplatImm(Op, 2, DAG)); ++ case Intrinsic::loongarch_lsx_vand_v: ++ case Intrinsic::loongarch_lasx_xvand_v: ++ return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vbitclr_b: ++ case Intrinsic::loongarch_lsx_vbitclr_h: ++ case Intrinsic::loongarch_lsx_vbitclr_w: ++ case Intrinsic::loongarch_lsx_vbitclr_d: ++ return lowerLSXBitClear(Op, DAG); ++ case Intrinsic::loongarch_lsx_vdiv_b: ++ case Intrinsic::loongarch_lsx_vdiv_h: ++ case Intrinsic::loongarch_lsx_vdiv_w: ++ case Intrinsic::loongarch_lsx_vdiv_d: ++ return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vdiv_bu: ++ case Intrinsic::loongarch_lsx_vdiv_hu: ++ case Intrinsic::loongarch_lsx_vdiv_wu: ++ case Intrinsic::loongarch_lsx_vdiv_du: ++ return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vfdiv_s: ++ case Intrinsic::loongarch_lsx_vfdiv_d: ++ return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vffint_s_wu: ++ case Intrinsic::loongarch_lsx_vffint_d_lu: ++ return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0), ++ Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vffint_s_w: ++ case Intrinsic::loongarch_lsx_vffint_d_l: ++ return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0), ++ Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vfmul_s: ++ case Intrinsic::loongarch_lsx_vfmul_d: ++ return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vfrint_s: ++ case Intrinsic::loongarch_lsx_vfrint_d: ++ return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vfsqrt_s: ++ case Intrinsic::loongarch_lsx_vfsqrt_d: ++ return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vftintrz_wu_s: ++ case Intrinsic::loongarch_lsx_vftintrz_lu_d: ++ return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0), ++ Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vpackev_b: ++ case Intrinsic::loongarch_lsx_vpackev_h: ++ case Intrinsic::loongarch_lsx_vpackev_w: ++ case Intrinsic::loongarch_lsx_vpackev_d: ++ return DAG.getNode(LoongArchISD::VPACKEV, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vilvh_b: ++ case Intrinsic::loongarch_lsx_vilvh_h: ++ case Intrinsic::loongarch_lsx_vilvh_w: ++ case Intrinsic::loongarch_lsx_vilvh_d: ++ return DAG.getNode(LoongArchISD::VILVH, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vpackod_b: ++ case Intrinsic::loongarch_lsx_vpackod_h: ++ case Intrinsic::loongarch_lsx_vpackod_w: ++ case Intrinsic::loongarch_lsx_vpackod_d: ++ return DAG.getNode(LoongArchISD::VPACKOD, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vilvl_b: ++ case Intrinsic::loongarch_lsx_vilvl_h: ++ case Intrinsic::loongarch_lsx_vilvl_w: ++ case Intrinsic::loongarch_lsx_vilvl_d: ++ return DAG.getNode(LoongArchISD::VILVL, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmadd_b: ++ case Intrinsic::loongarch_lsx_vmadd_h: ++ case Intrinsic::loongarch_lsx_vmadd_w: ++ case Intrinsic::loongarch_lsx_vmadd_d: { ++ EVT ResTy = Op->getValueType(0); ++ return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1), ++ DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, ++ Op->getOperand(2), Op->getOperand(3))); ++ } ++ case Intrinsic::loongarch_lsx_vmax_b: ++ case Intrinsic::loongarch_lsx_vmax_h: ++ case Intrinsic::loongarch_lsx_vmax_w: ++ case Intrinsic::loongarch_lsx_vmax_d: ++ return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmax_bu: ++ case Intrinsic::loongarch_lsx_vmax_hu: ++ case Intrinsic::loongarch_lsx_vmax_wu: ++ case Intrinsic::loongarch_lsx_vmax_du: ++ return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmin_b: ++ case Intrinsic::loongarch_lsx_vmin_h: ++ case Intrinsic::loongarch_lsx_vmin_w: ++ case Intrinsic::loongarch_lsx_vmin_d: ++ return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmin_bu: ++ case Intrinsic::loongarch_lsx_vmin_hu: ++ case Intrinsic::loongarch_lsx_vmin_wu: ++ case Intrinsic::loongarch_lsx_vmin_du: ++ return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmini_bu: ++ case Intrinsic::loongarch_lsx_vmini_hu: ++ case Intrinsic::loongarch_lsx_vmini_wu: ++ case Intrinsic::loongarch_lsx_vmini_du: ++ return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), ++ lowerLSXSplatImm(Op, 2, DAG)); ++ case Intrinsic::loongarch_lsx_vmod_b: ++ case Intrinsic::loongarch_lsx_vmod_h: ++ case Intrinsic::loongarch_lsx_vmod_w: ++ case Intrinsic::loongarch_lsx_vmod_d: ++ return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmod_bu: ++ case Intrinsic::loongarch_lsx_vmod_hu: ++ case Intrinsic::loongarch_lsx_vmod_wu: ++ case Intrinsic::loongarch_lsx_vmod_du: ++ return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmul_b: ++ case Intrinsic::loongarch_lsx_vmul_h: ++ case Intrinsic::loongarch_lsx_vmul_w: ++ case Intrinsic::loongarch_lsx_vmul_d: ++ return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vmsub_b: ++ case Intrinsic::loongarch_lsx_vmsub_h: ++ case Intrinsic::loongarch_lsx_vmsub_w: ++ case Intrinsic::loongarch_lsx_vmsub_d: { ++ EVT ResTy = Op->getValueType(0); ++ return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1), ++ DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, ++ Op->getOperand(2), Op->getOperand(3))); ++ } ++ case Intrinsic::loongarch_lsx_vclz_b: ++ case Intrinsic::loongarch_lsx_vclz_h: ++ case Intrinsic::loongarch_lsx_vclz_w: ++ case Intrinsic::loongarch_lsx_vclz_d: ++ return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vnor_v: ++ case Intrinsic::loongarch_lasx_xvnor_v: { ++ SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ return DAG.getNOT(DL, Res, Res->getValueType(0)); ++ } ++ case Intrinsic::loongarch_lsx_vor_v: ++ case Intrinsic::loongarch_lasx_xvor_v: ++ return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vpickev_b: ++ case Intrinsic::loongarch_lsx_vpickev_h: ++ case Intrinsic::loongarch_lsx_vpickev_w: ++ case Intrinsic::loongarch_lsx_vpickev_d: ++ return DAG.getNode(LoongArchISD::VPICKEV, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vpickod_b: ++ case Intrinsic::loongarch_lsx_vpickod_h: ++ case Intrinsic::loongarch_lsx_vpickod_w: ++ case Intrinsic::loongarch_lsx_vpickod_d: ++ return DAG.getNode(LoongArchISD::VPICKOD, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vpcnt_b: ++ case Intrinsic::loongarch_lsx_vpcnt_h: ++ case Intrinsic::loongarch_lsx_vpcnt_w: ++ case Intrinsic::loongarch_lsx_vpcnt_d: ++ return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vsat_b: ++ case Intrinsic::loongarch_lsx_vsat_h: ++ case Intrinsic::loongarch_lsx_vsat_w: ++ case Intrinsic::loongarch_lsx_vsat_d: ++ case Intrinsic::loongarch_lsx_vsat_bu: ++ case Intrinsic::loongarch_lsx_vsat_hu: ++ case Intrinsic::loongarch_lsx_vsat_wu: ++ case Intrinsic::loongarch_lsx_vsat_du: { ++ // Report an error for out of range values. ++ int64_t Max; ++ switch (Intrinsic) { ++ case Intrinsic::loongarch_lsx_vsat_b: ++ case Intrinsic::loongarch_lsx_vsat_bu: ++ Max = 7; ++ break; ++ case Intrinsic::loongarch_lsx_vsat_h: ++ case Intrinsic::loongarch_lsx_vsat_hu: ++ Max = 15; ++ break; ++ case Intrinsic::loongarch_lsx_vsat_w: ++ case Intrinsic::loongarch_lsx_vsat_wu: ++ Max = 31; ++ break; ++ case Intrinsic::loongarch_lsx_vsat_d: ++ case Intrinsic::loongarch_lsx_vsat_du: ++ Max = 63; ++ break; ++ default: ++ llvm_unreachable("Unmatched intrinsic"); ++ } ++ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); ++ if (Value < 0 || Value > Max) ++ report_fatal_error("Immediate out of range"); ++ return SDValue(); ++ } ++ case Intrinsic::loongarch_lsx_vshuf4i_b: ++ case Intrinsic::loongarch_lsx_vshuf4i_h: ++ case Intrinsic::loongarch_lsx_vshuf4i_w: ++ // case Intrinsic::loongarch_lsx_vshuf4i_d: ++ { ++ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); ++ if (Value < 0 || Value > 255) ++ report_fatal_error("Immediate out of range"); ++ return DAG.getNode(LoongArchISD::SHF, DL, Op->getValueType(0), ++ Op->getOperand(2), Op->getOperand(1)); ++ } ++ case Intrinsic::loongarch_lsx_vsll_b: ++ case Intrinsic::loongarch_lsx_vsll_h: ++ case Intrinsic::loongarch_lsx_vsll_w: ++ case Intrinsic::loongarch_lsx_vsll_d: ++ return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), ++ truncateVecElts(Op, DAG)); ++ case Intrinsic::loongarch_lsx_vslli_b: ++ case Intrinsic::loongarch_lsx_vslli_h: ++ case Intrinsic::loongarch_lsx_vslli_w: ++ case Intrinsic::loongarch_lsx_vslli_d: ++ return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), ++ lowerLSXSplatImm(Op, 2, DAG)); ++ case Intrinsic::loongarch_lsx_vreplve_b: ++ case Intrinsic::loongarch_lsx_vreplve_h: ++ case Intrinsic::loongarch_lsx_vreplve_w: ++ case Intrinsic::loongarch_lsx_vreplve_d: ++ // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle ++ // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because ++ // EXTRACT_VECTOR_ELT can't extract i64's on LoongArch32. ++ // Instead we lower to LoongArchISD::VSHF and match from there. ++ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), ++ lowerLSXSplatZExt(Op, 2, DAG), Op->getOperand(1), ++ Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vreplvei_b: ++ case Intrinsic::loongarch_lsx_vreplvei_h: ++ case Intrinsic::loongarch_lsx_vreplvei_w: ++ case Intrinsic::loongarch_lsx_vreplvei_d: ++ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), ++ lowerLSXSplatImm(Op, 2, DAG), Op->getOperand(1), ++ Op->getOperand(1)); ++ case Intrinsic::loongarch_lsx_vsra_b: ++ case Intrinsic::loongarch_lsx_vsra_h: ++ case Intrinsic::loongarch_lsx_vsra_w: ++ case Intrinsic::loongarch_lsx_vsra_d: ++ return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1), ++ truncateVecElts(Op, DAG)); ++ case Intrinsic::loongarch_lsx_vsrari_b: ++ case Intrinsic::loongarch_lsx_vsrari_h: ++ case Intrinsic::loongarch_lsx_vsrari_w: ++ case Intrinsic::loongarch_lsx_vsrari_d: { ++ // Report an error for out of range values. ++ int64_t Max; ++ switch (Intrinsic) { ++ case Intrinsic::loongarch_lsx_vsrari_b: ++ Max = 7; ++ break; ++ case Intrinsic::loongarch_lsx_vsrari_h: ++ Max = 15; ++ break; ++ case Intrinsic::loongarch_lsx_vsrari_w: ++ Max = 31; ++ break; ++ case Intrinsic::loongarch_lsx_vsrari_d: ++ Max = 63; ++ break; ++ default: ++ llvm_unreachable("Unmatched intrinsic"); ++ } ++ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); ++ if (Value < 0 || Value > Max) ++ report_fatal_error("Immediate out of range"); ++ return SDValue(); ++ } ++ case Intrinsic::loongarch_lsx_vsrl_b: ++ case Intrinsic::loongarch_lsx_vsrl_h: ++ case Intrinsic::loongarch_lsx_vsrl_w: ++ case Intrinsic::loongarch_lsx_vsrl_d: ++ return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), ++ truncateVecElts(Op, DAG)); ++ case Intrinsic::loongarch_lsx_vsrli_b: ++ case Intrinsic::loongarch_lsx_vsrli_h: ++ case Intrinsic::loongarch_lsx_vsrli_w: ++ case Intrinsic::loongarch_lsx_vsrli_d: ++ return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), ++ lowerLSXSplatImm(Op, 2, DAG)); ++ case Intrinsic::loongarch_lsx_vsrlri_b: ++ case Intrinsic::loongarch_lsx_vsrlri_h: ++ case Intrinsic::loongarch_lsx_vsrlri_w: ++ case Intrinsic::loongarch_lsx_vsrlri_d: { ++ // Report an error for out of range values. ++ int64_t Max; ++ switch (Intrinsic) { ++ case Intrinsic::loongarch_lsx_vsrlri_b: ++ Max = 7; ++ break; ++ case Intrinsic::loongarch_lsx_vsrlri_h: ++ Max = 15; ++ break; ++ case Intrinsic::loongarch_lsx_vsrlri_w: ++ Max = 31; ++ break; ++ case Intrinsic::loongarch_lsx_vsrlri_d: ++ Max = 63; ++ break; ++ default: ++ llvm_unreachable("Unmatched intrinsic"); ++ } ++ int64_t Value = cast(Op->getOperand(2))->getSExtValue(); ++ if (Value < 0 || Value > Max) ++ report_fatal_error("Immediate out of range"); ++ return SDValue(); ++ } ++ case Intrinsic::loongarch_lsx_vsubi_bu: ++ case Intrinsic::loongarch_lsx_vsubi_hu: ++ case Intrinsic::loongarch_lsx_vsubi_wu: ++ case Intrinsic::loongarch_lsx_vsubi_du: ++ return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1), ++ lowerLSXSplatImm(Op, 2, DAG)); ++ case Intrinsic::loongarch_lsx_vshuf_h: ++ case Intrinsic::loongarch_lsx_vshuf_w: ++ case Intrinsic::loongarch_lsx_vshuf_d: ++ case Intrinsic::loongarch_lasx_xvshuf_h: ++ case Intrinsic::loongarch_lasx_xvshuf_w: ++ case Intrinsic::loongarch_lasx_xvshuf_d: ++ return DAG.getNode(LoongArchISD::VSHF, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); ++ case Intrinsic::loongarch_lsx_vxor_v: ++ case Intrinsic::loongarch_lasx_xvxor_v: ++ return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1), ++ Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vrotr_b: ++ case Intrinsic::loongarch_lsx_vrotr_h: ++ case Intrinsic::loongarch_lsx_vrotr_w: ++ case Intrinsic::loongarch_lsx_vrotr_d: ++ return DAG.getNode(LoongArchISD::VROR, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::loongarch_lsx_vrotri_b: ++ case Intrinsic::loongarch_lsx_vrotri_h: ++ case Intrinsic::loongarch_lsx_vrotri_w: ++ case Intrinsic::loongarch_lsx_vrotri_d: ++ return DAG.getNode(LoongArchISD::VRORI, DL, Op->getValueType(0), ++ Op->getOperand(1), Op->getOperand(2)); ++ case Intrinsic::thread_pointer: { ++ EVT PtrVT = getPointerTy(DAG.getDataLayout()); ++ if (PtrVT == MVT::i64) ++ return DAG.getRegister(LoongArch::TP_64, MVT::i64); ++ return DAG.getRegister(LoongArch::TP, MVT::i32); ++ } ++ } ++} ++ ++SDValue ++LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, ++ SelectionDAG &DAG) const { ++ unsigned Intr = cast(Op->getOperand(1))->getZExtValue(); ++ switch (Intr) { ++ default: ++ return SDValue(); ++ case Intrinsic::loongarch_lsx_vld: ++ return lowerLSXLoadIntr(Op, DAG, Intr, Subtarget); ++ case Intrinsic::loongarch_lasx_xvld: ++ return lowerLASXLoadIntr(Op, DAG, Intr, Subtarget); ++ case Intrinsic::loongarch_lasx_xvldrepl_b: ++ case Intrinsic::loongarch_lasx_xvldrepl_h: ++ case Intrinsic::loongarch_lasx_xvldrepl_w: ++ case Intrinsic::loongarch_lasx_xvldrepl_d: ++ return lowerLASXVLDRIntr(Op, DAG, Intr, Subtarget); ++ case Intrinsic::loongarch_lsx_vldrepl_b: ++ case Intrinsic::loongarch_lsx_vldrepl_h: ++ case Intrinsic::loongarch_lsx_vldrepl_w: ++ case Intrinsic::loongarch_lsx_vldrepl_d: ++ return lowerLSXVLDRIntr(Op, DAG, Intr, Subtarget); ++ } ++} ++ ++SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op, ++ SelectionDAG &DAG) const { ++ unsigned Intr = cast(Op->getOperand(1))->getZExtValue(); ++ switch (Intr) { ++ default: ++ return SDValue(); ++ case Intrinsic::loongarch_lsx_vst: ++ return lowerLSXStoreIntr(Op, DAG, Intr, Subtarget); ++ case Intrinsic::loongarch_lasx_xvst: ++ return lowerLASXStoreIntr(Op, DAG, Intr, Subtarget); ++ } ++} ++ ++// Lower ISD::EXTRACT_VECTOR_ELT into LoongArchISD::VEXTRACT_SEXT_ELT. ++// ++// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We ++// choose to sign-extend but we could have equally chosen zero-extend. The ++// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT ++// result into this node later (possibly changing it to a zero-extend in the ++// process). ++SDValue ++LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ EVT ResTy = Op->getValueType(0); ++ SDValue Op0 = Op->getOperand(0); ++ EVT VecTy = Op0->getValueType(0); ++ ++ if (!VecTy.is128BitVector() && !VecTy.is256BitVector()) ++ return SDValue(); ++ ++ if (ResTy.isInteger()) { ++ SDValue Op1 = Op->getOperand(1); ++ EVT EltTy = VecTy.getVectorElementType(); ++ if (VecTy.is128BitVector()) ++ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1, ++ DAG.getValueType(EltTy)); ++ ++ ConstantSDNode *cn = dyn_cast(Op1); ++ if (!cn) ++ return SDValue(); ++ ++ if (EltTy == MVT::i32 || EltTy == MVT::i64) ++ return DAG.getNode(LoongArchISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1, ++ DAG.getValueType(EltTy)); ++ } ++ ++ return SDValue(); ++} ++ ++SDValue ++LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op, ++ SelectionDAG &DAG) const { ++ ++ MVT VT = Op.getSimpleValueType(); ++ MVT EltVT = VT.getVectorElementType(); ++ ++ SDLoc DL(Op); ++ SDValue Op0 = Op.getOperand(0); ++ SDValue Op1 = Op.getOperand(1); ++ SDValue Op2 = Op.getOperand(2); ++ ++ if (!EltVT.isInteger()) ++ return Op; ++ ++ if (!isa(Op2)) { ++ if (EltVT == MVT::i8 || EltVT == MVT::i16) { ++ return Op; // ==> pseudo ++ // use stack ++ return SDValue(); ++ } else { ++ return Op; ++ } ++ } ++ ++ if (VT.is128BitVector()) ++ return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Op0, Op1, Op2); ++ ++ if (VT.is256BitVector()) { ++ ++ if (EltVT == MVT::i32 || EltVT == MVT::i64) ++ return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Op0, Op1, Op2); ++ ++ return Op; ++ } ++ ++ return SDValue(); ++} ++ ++// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the ++// backend. ++// ++// Lowers according to the following rules: ++// - Constant splats are legal as-is as long as the SplatBitSize is a power of ++// 2 less than or equal to 64 and the value fits into a signed 10-bit ++// immediate ++// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize ++// is a power of 2 less than or equal to 64 and the value does not fit into a ++// signed 10-bit immediate ++// - Non-constant splats are legal as-is. ++// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT. ++// - All others are illegal and must be expanded. ++SDValue LoongArchTargetLowering::lowerBUILD_VECTOR(SDValue Op, ++ SelectionDAG &DAG) const { ++ BuildVectorSDNode *Node = cast(Op); ++ EVT ResTy = Op->getValueType(0); ++ SDLoc DL(Op); ++ APInt SplatValue, SplatUndef; ++ unsigned SplatBitSize; ++ bool HasAnyUndefs; ++ ++ if ((!Subtarget.hasLSX() || !ResTy.is128BitVector()) && ++ (!Subtarget.hasLASX() || !ResTy.is256BitVector())) ++ return SDValue(); ++ ++ if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, ++ 8) && ++ SplatBitSize <= 64) { ++ // We can only cope with 8, 16, 32, or 64-bit elements ++ if ((ResTy.is128BitVector() && SplatBitSize != 8 && SplatBitSize != 16 && ++ SplatBitSize != 32 && SplatBitSize != 64) || ++ (ResTy.is256BitVector() && SplatBitSize != 8 && SplatBitSize != 16 && ++ SplatBitSize != 32 && SplatBitSize != 64)) ++ return SDValue(); ++ ++ // If the value isn't an integer type we will have to bitcast ++ // from an integer type first. Also, if there are any undefs, we must ++ // lower them to defined values first. ++ if (ResTy.isInteger() && !HasAnyUndefs) ++ return Op; ++ ++ EVT ViaVecTy; ++ ++ if ((ResTy.is128BitVector() && ++ !isLSXBySplatBitSize(SplatBitSize, ViaVecTy)) || ++ (ResTy.is256BitVector() && ++ !isLASXBySplatBitSize(SplatBitSize, ViaVecTy))) ++ return SDValue(); ++ ++ // SelectionDAG::getConstant will promote SplatValue appropriately. ++ SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy); ++ ++ // Bitcast to the type we originally wanted ++ if (ViaVecTy != ResTy) ++ Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result); ++ ++ return Result; ++ } else if (DAG.isSplatValue(Op, /* AllowUndefs */ false)) ++ return Op; ++ else if (!isConstantOrUndefBUILD_VECTOR(Node)) { ++ // Use INSERT_VECTOR_ELT operations rather than expand to stores. ++ // The resulting code is the same length as the expansion, but it doesn't ++ // use memory operations ++ EVT ResTy = Node->getValueType(0); ++ ++ assert(ResTy.isVector()); ++ ++ unsigned NumElts = ResTy.getVectorNumElements(); ++ SDValue Vector = DAG.getUNDEF(ResTy); ++ for (unsigned i = 0; i < NumElts; ++i) { ++ Vector = ++ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector, ++ Node->getOperand(i), DAG.getConstant(i, DL, MVT::i32)); ++ } ++ return Vector; ++ } ++ ++ return SDValue(); ++} ++ ++SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ EVT ResTy = Op->getValueType(0); ++ Op = LowerSUINT_TO_FP(ISD::ZERO_EXTEND_VECTOR_INREG, Op, DAG); ++ if (!ResTy.isVector()) ++ return Op; ++ return DAG.getNode(ISD::UINT_TO_FP, DL, ResTy, Op); ++} ++ ++SDValue LoongArchTargetLowering::lowerSINT_TO_FP(SDValue Op, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ EVT ResTy = Op->getValueType(0); ++ Op = LowerSUINT_TO_FP(ISD::SIGN_EXTEND_VECTOR_INREG, Op, DAG); ++ if (!ResTy.isVector()) ++ return Op; ++ return DAG.getNode(ISD::SINT_TO_FP, DL, ResTy, Op); ++} ++ ++SDValue LoongArchTargetLowering::lowerFP_TO_UINT(SDValue Op, ++ SelectionDAG &DAG) const { ++ if (!Op->getValueType(0).isVector()) ++ return SDValue(); ++ return LowerFP_TO_SUINT(ISD::FP_TO_UINT, ISD::ZERO_EXTEND_VECTOR_INREG, Op, ++ DAG); ++} ++ ++SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, ++ SelectionDAG &DAG) const { ++ if (Op->getValueType(0).isVector()) ++ return LowerFP_TO_SUINT(ISD::FP_TO_SINT, ISD::SIGN_EXTEND_VECTOR_INREG, Op, ++ DAG); ++ ++ if (Op.getValueSizeInBits() > 32 && Subtarget.isSingleFloat()) ++ return SDValue(); ++ ++ EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); ++ SDValue Trunc = ++ DAG.getNode(LoongArchISD::TruncIntFP, SDLoc(Op), FPTy, Op.getOperand(0)); ++ return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); ++} ++ ++static bool checkUndef(ArrayRef Mask, int Lo, int Hi) { ++ ++ for (int i = Lo, end = Hi; i != end; i++, Hi++) ++ if (!((Mask[i] == -1) || (Mask[i] == Hi))) ++ return false; ++ return true; ++} ++ ++static bool CheckRev(ArrayRef Mask) { ++ ++ int Num = Mask.size() - 1; ++ for (long unsigned int i = 0; i < Mask.size(); i++, Num--) ++ if (Mask[i] != Num) ++ return false; ++ return true; ++} ++ ++static bool checkHalf(ArrayRef Mask, int Lo, int Hi, int base) { ++ ++ for (int i = Lo; i < Hi; i++) ++ if (Mask[i] != (base + i)) ++ return false; ++ return true; ++} ++ ++static SDValue lowerHalfHalf(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, ++ ArrayRef Mask, SelectionDAG &DAG) { ++ ++ int Num = VT.getVectorNumElements(); ++ int HalfNum = Num / 2; ++ ++ if (Op1->isUndef() || Op2->isUndef() || Mask.size() > (long unsigned int)Num) ++ return SDValue(); ++ ++ if (checkHalf(Mask, HalfNum, Num, Num) && checkHalf(Mask, 0, HalfNum, 0)) { ++ return SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, ++ DAG.getTargetConstant(48, DL, MVT::i32)), ++ 0); ++ } ++ ++ return SDValue(); ++} ++ ++static bool checkHalfUndef(ArrayRef Mask, int Lo, int Hi) { ++ ++ for (int i = Lo; i < Hi; i++) ++ if (Mask[i] != -1) ++ return false; ++ return true; ++} ++ ++// Lowering vectors with half undef data, ++// use EXTRACT_SUBVECTOR and INSERT_SUBVECTOR instead of VECTOR_SHUFFLE ++static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, ++ ArrayRef Mask, SelectionDAG &DAG) { ++ ++ int Num = VT.getVectorNumElements(); ++ int HalfNum = Num / 2; ++ MVT HalfVT = MVT::getVectorVT(VT.getVectorElementType(), HalfNum); ++ MVT VT1 = Op1.getSimpleValueType(); ++ SDValue Op; ++ ++ bool check1 = Op1->isUndef() && (!Op2->isUndef()); ++ bool check2 = Op2->isUndef() && (!Op1->isUndef()); ++ ++ if ((check1 || check2) && (VT1 == VT)) { ++ if (check1) { ++ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op2); ++ } else if (check2) { ++ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op1); ++ } ++ ++ if (VT == MVT::v32i8 && CheckRev(Mask)) { ++ SDValue Vector; ++ SDValue Rev[4]; ++ SDValue Ext[4]; ++ for (int i = 0; i < 4; i++) { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op, ++ DAG.getConstant(i, DL, MVT::i32)); ++ Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]); ++ } ++ ++ Vector = ++ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, DAG.getUNDEF(VT), ++ Rev[3], DAG.getConstant(3, DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, ++ Rev[2], DAG.getConstant(2, DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, ++ Rev[1], DAG.getConstant(1, DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector, ++ Rev[0], DAG.getConstant(0, DL, MVT::i32)); ++ ++ Vector = DAG.getNode(ISD::BITCAST, DL, MVT::v32i8, Vector); ++ ++ return Vector; ++ } ++ } ++ ++ if (checkHalfUndef(Mask, HalfNum, Num) && checkUndef(Mask, 0, HalfNum)) { ++ SDValue High = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Op1, ++ DAG.getConstant(HalfNum, DL, MVT::i64)); ++ return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), High, ++ DAG.getConstant(0, DL, MVT::i64)); ++ } ++ ++ if (checkHalfUndef(Mask, HalfNum, Num) && (VT == MVT::v8i32) && ++ (Mask[0] == 0) && (Mask[1] == 1) && (Mask[2] == (Num + 2)) && ++ (Mask[3] == (Num + 3))) { ++ ++ SDValue Val1 = ++ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, ++ DAG.getTargetConstant(32, DL, MVT::i32)), ++ 0); ++ ++ SDValue Val2 = ++ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_D, DL, VT, Val1, ++ DAG.getTargetConstant(12, DL, MVT::i32)), ++ 0); ++ ++ SDValue Val3 = SDValue( ++ DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Val2, DAG.getUNDEF(VT), ++ DAG.getTargetConstant(2, DL, MVT::i32)), ++ 0); ++ return Val3; ++ } ++ ++ if (checkHalfUndef(Mask, 0, HalfNum) && checkUndef(Mask, HalfNum, Num)) { ++ SDValue Low = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Op1, ++ DAG.getConstant(0, DL, MVT::i32)); ++ return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), Low, ++ DAG.getConstant(HalfNum, DL, MVT::i32)); ++ } ++ ++ if (checkHalfUndef(Mask, 0, HalfNum) && (VT == MVT::v8i32) && ++ (Mask[HalfNum] == HalfNum) && (Mask[HalfNum + 1] == (HalfNum + 1)) && ++ (Mask[HalfNum + 2] == (2 * Num - 2)) && ++ (Mask[HalfNum + 3] == (2 * Num - 1))) { ++ ++ SDValue Val1 = ++ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Op2, Op1, ++ DAG.getTargetConstant(49, DL, MVT::i32)), ++ 0); ++ ++ SDValue Val2 = ++ SDValue(DAG.getMachineNode(LoongArch::XVPERMI_D, DL, VT, Val1, ++ DAG.getTargetConstant(12, DL, MVT::i32)), ++ 0); ++ ++ SDValue Val3 = SDValue( ++ DAG.getMachineNode(LoongArch::XVPERMI_Q, DL, VT, Val2, DAG.getUNDEF(VT), ++ DAG.getTargetConstant(32, DL, MVT::i32)), ++ 0); ++ return Val3; ++ } ++ ++ if ((VT == MVT::v8i32) || (VT == MVT::v4i64)) { ++ int def = 0; ++ int j = 0; ++ int ext[3]; ++ int ins[3]; ++ bool useOp1[3] = {true, true, true}; ++ bool checkdef = true; ++ ++ for (int i = 0; i < Num; i++) { ++ if (def > 2) { ++ checkdef = false; ++ break; ++ } ++ if (Mask[i] != -1) { ++ def++; ++ ins[j] = i; ++ if (Mask[i] >= Num) { ++ ext[j] = Mask[i] - Num; ++ useOp1[j] = false; ++ } else { ++ ext[j] = Mask[i]; ++ } ++ j++; ++ } ++ } ++ ++ if (checkdef) { ++ SDValue Vector = DAG.getUNDEF(VT); ++ EVT EltTy = VT.getVectorElementType(); ++ SDValue Ext[2]; ++ ++ if (check1 || check2) { ++ for (int i = 0; i < def; i++) { ++ if (check1) { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2, ++ DAG.getConstant(ext[i], DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], ++ DAG.getConstant(ins[i], DL, MVT::i32)); ++ } else if (check2) { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1, ++ DAG.getConstant(ext[i], DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], ++ DAG.getConstant(ins[i], DL, MVT::i32)); ++ } ++ } ++ return Vector; ++ } else { ++ for (int i = 0; i < def; i++) { ++ if (!useOp1[i]) { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2, ++ DAG.getConstant(ext[i], DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], ++ DAG.getConstant(ins[i], DL, MVT::i32)); ++ } else { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1, ++ DAG.getConstant(ext[i], DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i], ++ DAG.getConstant(ins[i], DL, MVT::i32)); ++ } ++ } ++ return Vector; ++ } ++ } ++ } ++ ++ return SDValue(); ++} ++ ++static SDValue lowerHalfUndef_LSX(const SDLoc &DL, EVT ResTy, MVT VT, ++ SDValue Op1, SDValue Op2, ArrayRef Mask, ++ SelectionDAG &DAG) { ++ ++ MVT VT1 = Op1.getSimpleValueType(); ++ ++ bool check1 = Op1->isUndef() && (!Op2->isUndef()); ++ bool check2 = Op2->isUndef() && (!Op1->isUndef()); ++ ++ if ((check1 || check2) && (VT1 == VT)) { ++ SDValue Op; ++ ++ if (VT == MVT::v16i8 && CheckRev(Mask)) { ++ ++ if (check1) { ++ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op2); ++ } else if (check2) { ++ Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op1); ++ } ++ ++ SDValue Vector; ++ SDValue Rev[2]; ++ SDValue Ext[2]; ++ for (int i = 0; i < 2; i++) { ++ Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op, ++ DAG.getConstant(i, DL, MVT::i32)); ++ Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]); ++ } ++ ++ Vector = ++ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, DAG.getUNDEF(VT), ++ Rev[1], DAG.getConstant(1, DL, MVT::i32)); ++ Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, Vector, ++ Rev[0], DAG.getConstant(0, DL, MVT::i32)); ++ ++ Vector = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, Vector); ++ ++ return Vector; ++ } ++ } ++ ++ return SDValue(); ++} ++ ++// Use SDNode of LoongArchINSVE instead of ++// a series of EXTRACT_VECTOR_ELT and INSERT_VECTOR_ELT ++static SDValue lowerVECTOR_SHUFFLE_INSVE(const SDLoc &DL, MVT VT, EVT ResTy, ++ SDValue Op1, SDValue Op2, ++ ArrayRef Mask, ++ SelectionDAG &DAG) { ++ ++ int Num = VT.getVectorNumElements(); ++ if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8) ++ return SDValue(); ++ ++ int CheckOne = 0; ++ int CheckOther = 0; ++ int Idx; ++ ++ for (int i = 0; i < Num; i++) { ++ if ((Mask[i] == i) || (Mask[i] == -1)) { ++ CheckOther++; ++ } else if (Mask[i] == Num) { ++ CheckOne++; ++ Idx = i; ++ } else ++ return SDValue(); ++ } ++ ++ if ((CheckOne != 1) || (CheckOther != (Num - 1))) ++ return SDValue(); ++ else { ++ return DAG.getNode(LoongArchISD::INSVE, DL, ResTy, Op1, Op2, ++ DAG.getConstant(Idx, DL, MVT::i32)); ++ } ++ ++ return SDValue(); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVPICKVE(const SDLoc &DL, MVT VT, EVT ResTy, ++ SDValue Op1, SDValue Op2, ++ ArrayRef Mask, ++ SelectionDAG &DAG) { ++ ++ int Num = VT.getVectorNumElements(); ++ if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8 || ++ (!ISD::isBuildVectorAllZeros(Op1.getNode()))) ++ return SDValue(); ++ ++ bool CheckV = true; ++ ++ if ((Mask[0] < Num) || (Mask[0] > (2 * Num - 1))) ++ CheckV = false; ++ ++ for (int i = 1; i < Num; i++) { ++ if (Mask[i] != 0) { ++ CheckV = false; ++ break; ++ } ++ } ++ ++ if (!CheckV) ++ return SDValue(); ++ else { ++ return DAG.getNode(LoongArchISD::XVPICKVE, DL, ResTy, Op1, Op2, ++ DAG.getConstant(Mask[0] - Num, DL, MVT::i32)); ++ } ++ ++ return SDValue(); ++} ++ ++static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, MVT VT, EVT ResTy, ++ SDValue Op1, SDValue Op2, ++ ArrayRef Mask, ++ SelectionDAG &DAG) { ++ ++ if (VT == MVT::v4i64) { ++ int Num = VT.getVectorNumElements(); ++ ++ bool CheckV = true; ++ for (int i = 0; i < Num; i++) { ++ if (Mask[i] != (i * 2)) { ++ CheckV = false; ++ break; ++ } ++ } ++ ++ if (!CheckV) ++ return SDValue(); ++ else { ++ SDValue Res = DAG.getNode(LoongArchISD::XVSHUF4I, DL, ResTy, Op1, Op2, ++ DAG.getConstant(8, DL, MVT::i32)); ++ return DAG.getNode(LoongArchISD::XVPERMI, DL, ResTy, Res, ++ DAG.getConstant(0xD8, DL, MVT::i32)); ++ } ++ } else ++ return SDValue(); ++} ++ ++// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the ++// indices in the shuffle. ++SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, ++ SelectionDAG &DAG) const { ++ ShuffleVectorSDNode *Node = cast(Op); ++ EVT ResTy = Op->getValueType(0); ++ ArrayRef Mask = Node->getMask(); ++ SDValue Op1 = Op.getOperand(0); ++ SDValue Op2 = Op.getOperand(1); ++ MVT VT = Op.getSimpleValueType(); ++ SDLoc DL(Op); ++ ++ if (ResTy.is128BitVector()) { ++ ++ int ResTyNumElts = ResTy.getVectorNumElements(); ++ SmallVector Indices; ++ ++ for (int i = 0; i < ResTyNumElts; ++i) ++ Indices.push_back(Node->getMaskElt(i)); ++ ++ SDValue Result; ++ if (isVECTOR_SHUFFLE_VREPLVEI(Op, ResTy, Indices, DAG)) ++ return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); ++ if ((Result = lowerVECTOR_SHUFFLE_VPACKEV(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_VPACKOD(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_VILVH(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_VILVL(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_VPICKEV(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_VPICKOD(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerHalfUndef_LSX(DL, ResTy, VT, Op1, Op2, Mask, DAG))) ++ return Result; ++ return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); ++ ++ } else if (ResTy.is256BitVector()) { ++ int ResTyNumElts = ResTy.getVectorNumElements(); ++ SmallVector Indices; ++ ++ for (int i = 0; i < ResTyNumElts; ++i) ++ Indices.push_back(Node->getMaskElt(i)); ++ ++ SDValue Result; ++ if ((Result = lowerHalfHalf(DL, VT, Op1, Op2, Mask, DAG))) ++ return Result; ++ if ((Result = lowerHalfUndef(DL, VT, Op1, Op2, Mask, DAG))) ++ return Result; ++ if (isVECTOR_SHUFFLE_XVREPLVEI(Op, ResTy, Indices, DAG)) ++ return SDValue(); ++ if ((Result = lowerVECTOR_SHUFFLE_XVPACKEV(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XVPACKOD(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XVILVH(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XVILVL(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XVPICKEV(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XVPICKOD(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = lowerVECTOR_SHUFFLE_XSHF(Op, ResTy, Indices, DAG))) ++ return Result; ++ if ((Result = ++ lowerVECTOR_SHUFFLE_INSVE(DL, VT, ResTy, Op1, Op2, Mask, DAG))) ++ return Result; ++ if ((Result = ++ lowerVECTOR_SHUFFLE_XVPICKVE(DL, VT, ResTy, Op1, Op2, Mask, DAG))) ++ return Result; ++ if ((Result = ++ lowerVECTOR_SHUFFLE_XVSHUF(DL, VT, ResTy, Op1, Op2, Mask, DAG))) ++ return Result; ++ } ++ ++ return SDValue(); ++} ++ ++SDValue LoongArchTargetLowering::lowerEH_DWARF_CFA(SDValue Op, ++ SelectionDAG &DAG) const { ++ ++ // Return a fixed StackObject with offset 0 which points to the old stack ++ // pointer. ++ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); ++ EVT ValTy = Op->getValueType(0); ++ int FI = MFI.CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); ++ return DAG.getFrameIndex(FI, ValTy); ++} ++ ++// Check whether the tail call optimization conditions are met ++bool LoongArchTargetLowering::isEligibleForTailCallOptimization( ++ const CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, ++ unsigned NextStackOffset, const LoongArchFunctionInfo &FI) const { ++ ++ auto CalleeCC = CLI.CallConv; ++ auto IsVarArg = CLI.IsVarArg; ++ auto &Outs = CLI.Outs; ++ auto &Caller = MF.getFunction(); ++ auto CallerCC = Caller.getCallingConv(); ++ ++ if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true") ++ return false; ++ ++ if (Caller.hasFnAttribute("interrupt")) ++ return false; ++ ++ if (IsVarArg) ++ return false; ++ ++ if (getTargetMachine().getCodeModel() == CodeModel::Large) ++ return false; ++ ++ if (getTargetMachine().getRelocationModel() == Reloc::Static) ++ return false; ++ ++ // Do not tail call optimize if the stack is used to pass parameters. ++ if (CCInfo.getNextStackOffset() != 0) ++ return false; ++ ++ // Do not tail call optimize functions with byval parameters. ++ for (auto &Arg : Outs) ++ if (Arg.Flags.isByVal()) ++ return false; ++ ++ // Do not tail call optimize if either caller or callee uses structret ++ // semantics. ++ auto IsCallerStructRet = Caller.hasStructRetAttr(); ++ auto IsCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet(); ++ if (IsCallerStructRet || IsCalleeStructRet) ++ return false; ++ ++ // The callee has to preserve all registers the caller needs to preserve. ++ const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo(); ++ const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC); ++ if (CalleeCC != CallerCC) { ++ const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC); ++ if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) ++ return false; ++ } ++ ++ // Return false if either the callee or caller has a byval argument. ++ if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg()) ++ return false; ++ ++ // Return true if the callee's argument area is no larger than the ++ // caller's. ++ return NextStackOffset <= FI.getIncomingArgSize(); ++} ++ ++//===----------------------------------------------------------------------===// ++// Calling Convention Implementation ++//===----------------------------------------------------------------------===// ++ ++//===----------------------------------------------------------------------===// ++// TODO: Implement a generic logic using tblgen that can support this. ++// LoongArch LP32 ABI rules: ++// --- ++// i32 - Passed in A0, A1, A2, A3 and stack ++// f32 - Only passed in f32 registers if no int reg has been used yet to hold ++// an argument. Otherwise, passed in A1, A2, A3 and stack. ++// f64 - Only passed in two aliased f32 registers if no int reg has been used ++// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is ++// not used, it must be shadowed. If only A3 is available, shadow it and ++// go to stack. ++// vXiX - Received as scalarized i32s, passed in A0 - A3 and the stack. ++// vXf32 - Passed in either a pair of registers {A0, A1}, {A2, A3} or {A0 - A3} ++// with the remainder spilled to the stack. ++// vXf64 - Passed in either {A0, A1, A2, A3} or {A2, A3} and in both cases ++// spilling the remainder to the stack. ++// ++// For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. ++//===----------------------------------------------------------------------===// ++ ++static bool CC_LoongArchLP32(unsigned ValNo, MVT ValVT, MVT LocVT, ++ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, ++ CCState &State, ArrayRef F64Regs) { ++ static const MCPhysReg IntRegs[] = { LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3 }; ++ ++ const LoongArchCCState * LoongArchState = static_cast(&State); ++ ++ static const MCPhysReg F32Regs[] = { LoongArch::F12, LoongArch::F14 }; ++ ++ static const MCPhysReg FloatVectorIntRegs[] = { LoongArch::A0, LoongArch::A2 }; ++ ++ // Do not process byval args here. ++ if (ArgFlags.isByVal()) ++ return true; ++ ++ ++ // Promote i8 and i16 ++ if (LocVT == MVT::i8 || LocVT == MVT::i16) { ++ LocVT = MVT::i32; ++ if (ArgFlags.isSExt()) ++ LocInfo = CCValAssign::SExt; ++ else if (ArgFlags.isZExt()) ++ LocInfo = CCValAssign::ZExt; ++ else ++ LocInfo = CCValAssign::AExt; ++ } ++ ++ unsigned Reg; ++ ++ // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following ++ // is true: function is vararg, argument is 3rd or higher, there is previous ++ // argument which is not f32 or f64. ++ bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || ++ State.getFirstUnallocated(F32Regs) != ValNo; ++ Align OrigAlign = ArgFlags.getNonZeroOrigAlign(); ++ bool isI64 = (ValVT == MVT::i32 && OrigAlign == Align(8)); ++ bool isVectorFloat = LoongArchState->WasOriginalArgVectorFloat(ValNo); ++ ++ // The LoongArch vector ABI for floats passes them in a pair of registers ++ if (ValVT == MVT::i32 && isVectorFloat) { ++ // This is the start of an vector that was scalarized into an unknown number ++ // of components. It doesn't matter how many there are. Allocate one of the ++ // notional 8 byte aligned registers which map onto the argument stack, and ++ // shadow the register lost to alignment requirements. ++ if (ArgFlags.isSplit()) { ++ Reg = State.AllocateReg(FloatVectorIntRegs); ++ if (Reg == LoongArch::A2) ++ State.AllocateReg(LoongArch::A1); ++ else if (Reg == 0) ++ State.AllocateReg(LoongArch::A3); ++ } else { ++ // If we're an intermediate component of the split, we can just attempt to ++ // allocate a register directly. ++ Reg = State.AllocateReg(IntRegs); ++ } ++ } else if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { ++ Reg = State.AllocateReg(IntRegs); ++ // If this is the first part of an i64 arg, ++ // the allocated register must be either A0 or A2. ++ if (isI64 && (Reg == LoongArch::A1 || Reg == LoongArch::A3)) ++ Reg = State.AllocateReg(IntRegs); ++ LocVT = MVT::i32; ++ } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { ++ // Allocate int register and shadow next int register. If first ++ // available register is LoongArch::A1 or LoongArch::A3, shadow it too. ++ Reg = State.AllocateReg(IntRegs); ++ if (Reg == LoongArch::A1 || Reg == LoongArch::A3) ++ Reg = State.AllocateReg(IntRegs); ++ State.AllocateReg(IntRegs); ++ LocVT = MVT::i32; ++ } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { ++ // we are guaranteed to find an available float register ++ if (ValVT == MVT::f32) { ++ Reg = State.AllocateReg(F32Regs); ++ // Shadow int register ++ State.AllocateReg(IntRegs); ++ } else { ++ Reg = State.AllocateReg(F64Regs); ++ // Shadow int registers ++ unsigned Reg2 = State.AllocateReg(IntRegs); ++ if (Reg2 == LoongArch::A1 || Reg2 == LoongArch::A3) ++ State.AllocateReg(IntRegs); ++ State.AllocateReg(IntRegs); ++ } ++ } else ++ llvm_unreachable("Cannot handle this ValVT."); ++ ++ if (!Reg) { ++ unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign); ++ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); ++ } else ++ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); ++ ++ return false; ++} ++ ++static bool CC_LoongArchLP32_FP32(unsigned ValNo, MVT ValVT, ++ MVT LocVT, CCValAssign::LocInfo LocInfo, ++ ISD::ArgFlagsTy ArgFlags, CCState &State) { ++ static const MCPhysReg F64Regs[] = {LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, \ ++ LoongArch::F3_64, LoongArch::F4_64, LoongArch::F5_64, \ ++ LoongArch::F6_64, LoongArch::F7_64 }; ++ ++ return CC_LoongArchLP32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); ++} ++ ++static bool CC_LoongArchLP32_FP64(unsigned ValNo, MVT ValVT, ++ MVT LocVT, CCValAssign::LocInfo LocInfo, ++ ISD::ArgFlagsTy ArgFlags, CCState &State) { ++ static const MCPhysReg F64Regs[] = {LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, \ ++ LoongArch::F3_64, LoongArch::F4_64, LoongArch::F5_64, \ ++ LoongArch::F6_64, LoongArch::F7_64 }; ++ ++ return CC_LoongArchLP32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); ++} ++ ++static bool CC_LoongArch_F128(unsigned ValNo, MVT ValVT, ++ MVT LocVT, CCValAssign::LocInfo LocInfo, ++ ISD::ArgFlagsTy ArgFlags, CCState &State) LLVM_ATTRIBUTE_UNUSED; ++ ++static bool CC_LoongArch_F128(unsigned ValNo, MVT ValVT, ++ MVT LocVT, CCValAssign::LocInfo LocInfo, ++ ISD::ArgFlagsTy ArgFlags, CCState &State) { ++ ++ static const MCPhysReg ArgRegs[8] = { ++ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64, ++ LoongArch::A4_64, LoongArch::A5_64, LoongArch::A6_64, LoongArch::A7_64}; ++ ++ unsigned Idx = State.getFirstUnallocated(ArgRegs); ++ // Skip 'odd' register if necessary. ++ if (!ArgFlags.isSplitEnd() && Idx != array_lengthof(ArgRegs) && Idx % 2 == 1) ++ State.AllocateReg(ArgRegs); ++ return true; ++} ++ ++static bool CC_LoongArchLP32(unsigned ValNo, MVT ValVT, MVT LocVT, ++ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, ++ CCState &State) LLVM_ATTRIBUTE_UNUSED; ++ ++#include "LoongArchGenCallingConv.inc" ++ ++ CCAssignFn *LoongArchTargetLowering::CCAssignFnForCall() const{ ++ return CC_LoongArch; ++ } ++ ++ CCAssignFn *LoongArchTargetLowering::CCAssignFnForReturn() const{ ++ return RetCC_LoongArch; ++ } ++ ++//===----------------------------------------------------------------------===// ++// Call Calling Convention Implementation ++//===----------------------------------------------------------------------===// ++SDValue LoongArchTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, ++ SDValue Chain, SDValue Arg, ++ const SDLoc &DL, bool IsTailCall, ++ SelectionDAG &DAG) const { ++ if (!IsTailCall) { ++ SDValue PtrOff = ++ DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr, ++ DAG.getIntPtrConstant(Offset, DL)); ++ return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()); ++ } ++ ++ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); ++ int FI = MFI.CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); ++ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); ++ return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), ++ /* Alignment = */ 0, MachineMemOperand::MOVolatile); ++} ++ ++void LoongArchTargetLowering::getOpndList( ++ SmallVectorImpl &Ops, ++ std::deque> &RegsToPass, bool IsPICCall, ++ bool GlobalOrExternal, bool IsCallReloc, CallLoweringInfo &CLI, ++ SDValue Callee, SDValue Chain, bool IsTailCall) const { ++ // Build a sequence of copy-to-reg nodes chained together with token ++ // chain and flag operands which copy the outgoing args into registers. ++ // The InFlag in necessary since all emitted instructions must be ++ // stuck together. ++ SDValue InFlag; ++ ++ Ops.push_back(Callee); ++ ++ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { ++ Chain = CLI.DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first, ++ RegsToPass[i].second, InFlag); ++ InFlag = Chain.getValue(1); ++ } ++ ++ // Add argument registers to the end of the list so that they are ++ // known live into the call. ++ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) ++ Ops.push_back(CLI.DAG.getRegister(RegsToPass[i].first, ++ RegsToPass[i].second.getValueType())); ++ ++ if (!IsTailCall) { ++ // Add a register mask operand representing the call-preserved registers. ++ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); ++ const uint32_t *Mask = ++ TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv); ++ assert(Mask && "Missing call preserved mask for calling convention"); ++ Ops.push_back(CLI.DAG.getRegisterMask(Mask)); ++ } ++ ++ if (InFlag.getNode()) ++ Ops.push_back(InFlag); ++} ++ ++void LoongArchTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, ++ SDNode *Node) const { ++ switch (MI.getOpcode()) { ++ default: ++ return; ++ } ++} ++ ++/// LowerCall - functions arguments are copied from virtual regs to ++/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. ++SDValue ++LoongArchTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, ++ SmallVectorImpl &InVals) const { ++ SelectionDAG &DAG = CLI.DAG; ++ SDLoc DL = CLI.DL; ++ SmallVectorImpl &Outs = CLI.Outs; ++ SmallVectorImpl &OutVals = CLI.OutVals; ++ SmallVectorImpl &Ins = CLI.Ins; ++ SDValue Chain = CLI.Chain; ++ SDValue Callee = CLI.Callee; ++ bool &IsTailCall = CLI.IsTailCall; ++ CallingConv::ID CallConv = CLI.CallConv; ++ bool IsVarArg = CLI.IsVarArg; ++ ++ MachineFunction &MF = DAG.getMachineFunction(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); ++ bool IsPIC = isPositionIndependent(); ++ ++ // Analyze operands of the call, assigning locations to each operand. ++ SmallVector ArgLocs; ++ LoongArchCCState CCInfo( ++ CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), ++ LoongArchCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); ++ ++ const ExternalSymbolSDNode *ES = ++ dyn_cast_or_null(Callee.getNode()); ++ ++ // There is one case where CALLSEQ_START..CALLSEQ_END can be nested, which ++ // is during the lowering of a call with a byval argument which produces ++ // a call to memcpy. For the LP32 case, this causes the caller to allocate ++ // stack space for the reserved argument area for the callee, then recursively ++ // again for the memcpy call. In the NEWABI case, this doesn't occur as those ++ // ABIs mandate that the callee allocates the reserved argument area. We do ++ // still produce nested CALLSEQ_START..CALLSEQ_END with zero space though. ++ // ++ // If the callee has a byval argument and memcpy is used, we are mandated ++ // to already have produced a reserved argument area for the callee for LP32. ++ // Therefore, the reserved argument area can be reused for both calls. ++ // ++ // Other cases of calling memcpy cannot have a chain with a CALLSEQ_START ++ // present, as we have yet to hook that node onto the chain. ++ // ++ // Hence, the CALLSEQ_START and CALLSEQ_END nodes can be eliminated in this ++ // case. GCC does a similar trick, in that wherever possible, it calculates ++ // the maximum out going argument area (including the reserved area), and ++ // preallocates the stack space on entrance to the caller. ++ // ++ // FIXME: We should do the same for efficiency and space. ++ ++ bool MemcpyInByVal = ES && ++ StringRef(ES->getSymbol()) == StringRef("memcpy") && ++ Chain.getOpcode() == ISD::CALLSEQ_START; ++ ++ CCInfo.AnalyzeCallOperands(Outs, CC_LoongArch, CLI.getArgs(), ++ ES ? ES->getSymbol() : nullptr); ++ ++ // Get a count of how many bytes are to be pushed on the stack. ++ unsigned NextStackOffset = CCInfo.getNextStackOffset(); ++ ++ // Check if it's really possible to do a tail call. Restrict it to functions ++ // that are part of this compilation unit. ++ if (IsTailCall) { ++ IsTailCall = isEligibleForTailCallOptimization( ++ CCInfo, CLI, MF, NextStackOffset, *MF.getInfo()); ++ if (GlobalAddressSDNode *G = dyn_cast(Callee)) { ++ if (G->getGlobal()->hasExternalWeakLinkage()) ++ IsTailCall = false; ++ } ++ } ++ if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall()) ++ report_fatal_error("failed to perform tail call elimination on a call " ++ "site marked musttail"); ++ ++ if (IsTailCall) ++ ++NumTailCalls; ++ ++ // Chain is the output chain of the last Load/Store or CopyToReg node. ++ // ByValChain is the output chain of the last Memcpy node created for copying ++ // byval arguments to the stack. ++ unsigned StackAlignment = TFL->getStackAlignment(); ++ NextStackOffset = alignTo(NextStackOffset, StackAlignment); ++ SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); ++ ++ if (!(IsTailCall || MemcpyInByVal)) ++ Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); ++ ++ SDValue StackPtr = ++ DAG.getCopyFromReg(Chain, DL, ABI.IsLP64() ? LoongArch::SP_64 : LoongArch::SP, ++ getPointerTy(DAG.getDataLayout())); ++ ++ std::deque> RegsToPass; ++ SmallVector MemOpChains; ++ ++ CCInfo.rewindByValRegsInfo(); ++ ++ // Walk the register/memloc assignments, inserting copies/loads. ++ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { ++ SDValue Arg = OutVals[i]; ++ CCValAssign &VA = ArgLocs[i]; ++ MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); ++ ISD::ArgFlagsTy Flags = Outs[i].Flags; ++ bool UseUpperBits = false; ++ ++ // ByVal Arg. ++ if (Flags.isByVal()) { ++ unsigned FirstByValReg, LastByValReg; ++ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); ++ CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); ++ ++ assert(Flags.getByValSize() && ++ "ByVal args of size 0 should have been ignored by front-end."); ++ assert(ByValIdx < CCInfo.getInRegsParamsCount()); ++ assert(!IsTailCall && ++ "Do not tail-call optimize if there is a byval argument."); ++ passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, ++ FirstByValReg, LastByValReg, Flags, ++ VA); ++ CCInfo.nextInRegsParam(); ++ continue; ++ } ++ ++ // Promote the value if needed. ++ switch (VA.getLocInfo()) { ++ default: ++ llvm_unreachable("Unknown loc info!"); ++ case CCValAssign::Full: ++ if (VA.isRegLoc()) { ++ if ((ValVT == MVT::f32 && LocVT == MVT::i32) || ++ (ValVT == MVT::f64 && LocVT == MVT::i64) || ++ (ValVT == MVT::i64 && LocVT == MVT::f64)) ++ Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); ++ } ++ break; ++ case CCValAssign::BCvt: ++ Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); ++ break; ++ case CCValAssign::SExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::SExt: ++ Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); ++ break; ++ case CCValAssign::ZExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::ZExt: ++ Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); ++ break; ++ case CCValAssign::AExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::AExt: ++ Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); ++ break; ++ } ++ ++ if (UseUpperBits) { ++ unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); ++ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); ++ Arg = DAG.getNode( ++ ISD::SHL, DL, VA.getLocVT(), Arg, ++ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); ++ } ++ ++ // Arguments that can be passed on register must be kept at ++ // RegsToPass vector ++ if (VA.isRegLoc()) { ++ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); ++ continue; ++ } ++ ++ // Register can't get to this point... ++ assert(VA.isMemLoc()); ++ ++ // emit ISD::STORE whichs stores the ++ // parameter value to a stack Location ++ MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), ++ Chain, Arg, DL, IsTailCall, DAG)); ++ } ++ ++ // Transform all store nodes into one single node because all store ++ // nodes are independent of each other. ++ if (!MemOpChains.empty()) ++ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); ++ ++ // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every ++ // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol ++ // node so that legalize doesn't hack it. ++ ++ bool GlobalOrExternal = false, IsCallReloc = false; ++ ++ if (GlobalAddressSDNode *G = dyn_cast(Callee)) { ++ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, ++ getPointerTy(DAG.getDataLayout()), 0, ++ LoongArchII::MO_NO_FLAG); ++ GlobalOrExternal = true; ++ } ++ else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { ++ const char *Sym = S->getSymbol(); ++ Callee = DAG.getTargetExternalSymbol( ++ Sym, getPointerTy(DAG.getDataLayout()), LoongArchII::MO_NO_FLAG); ++ ++ GlobalOrExternal = true; ++ } ++ ++ SmallVector Ops(1, Chain); ++ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); ++ ++ getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, IsCallReloc, CLI, ++ Callee, Chain, IsTailCall); ++ ++ if (IsTailCall) { ++ MF.getFrameInfo().setHasTailCall(); ++ return DAG.getNode(LoongArchISD::TailCall, DL, MVT::Other, Ops); ++ } ++ ++ Chain = DAG.getNode(LoongArchISD::JmpLink, DL, NodeTys, Ops); ++ DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); ++ SDValue InFlag = Chain.getValue(1); ++ ++ // Create the CALLSEQ_END node in the case of where it is not a call to ++ // memcpy. ++ if (!(MemcpyInByVal)) { ++ Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, ++ DAG.getIntPtrConstant(0, DL, true), InFlag, DL); ++ InFlag = Chain.getValue(1); ++ } ++ ++ // Handle result values, copying them out of physregs into vregs that we ++ // return. ++ return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, ++ InVals, CLI); ++} ++ ++/// LowerCallResult - Lower the result values of a call into the ++/// appropriate copies out of appropriate physical registers. ++SDValue LoongArchTargetLowering::LowerCallResult( ++ SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, ++ const SmallVectorImpl &Ins, const SDLoc &DL, ++ SelectionDAG &DAG, SmallVectorImpl &InVals, ++ TargetLowering::CallLoweringInfo &CLI) const { ++ // Assign locations to each value returned by this call. ++ SmallVector RVLocs; ++ LoongArchCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, ++ *DAG.getContext()); ++ ++ const ExternalSymbolSDNode *ES = ++ dyn_cast_or_null(CLI.Callee.getNode()); ++ CCInfo.AnalyzeCallResult(Ins, RetCC_LoongArch, CLI.RetTy, ++ ES ? ES->getSymbol() : nullptr); ++ ++ // Copy all of the result registers out of their specified physreg. ++ for (unsigned i = 0; i != RVLocs.size(); ++i) { ++ CCValAssign &VA = RVLocs[i]; ++ assert(VA.isRegLoc() && "Can only return in registers!"); ++ ++ SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(), ++ RVLocs[i].getLocVT(), InFlag); ++ Chain = Val.getValue(1); ++ InFlag = Val.getValue(2); ++ ++ if (VA.isUpperBitsInLoc()) { ++ unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits(); ++ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); ++ unsigned Shift = ++ VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; ++ Val = DAG.getNode( ++ Shift, DL, VA.getLocVT(), Val, ++ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); ++ } ++ ++ switch (VA.getLocInfo()) { ++ default: ++ llvm_unreachable("Unknown loc info!"); ++ case CCValAssign::Full: ++ break; ++ case CCValAssign::BCvt: ++ Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); ++ break; ++ case CCValAssign::AExt: ++ case CCValAssign::AExtUpper: ++ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); ++ break; ++ case CCValAssign::ZExt: ++ case CCValAssign::ZExtUpper: ++ Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val, ++ DAG.getValueType(VA.getValVT())); ++ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); ++ break; ++ case CCValAssign::SExt: ++ case CCValAssign::SExtUpper: ++ Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val, ++ DAG.getValueType(VA.getValVT())); ++ Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); ++ break; ++ } ++ ++ InVals.push_back(Val); ++ } ++ ++ return Chain; ++} ++ ++static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, ++ EVT ArgVT, const SDLoc &DL, ++ SelectionDAG &DAG) { ++ MVT LocVT = VA.getLocVT(); ++ EVT ValVT = VA.getValVT(); ++ ++ // Shift into the upper bits if necessary. ++ switch (VA.getLocInfo()) { ++ default: ++ break; ++ case CCValAssign::AExtUpper: ++ case CCValAssign::SExtUpper: ++ case CCValAssign::ZExtUpper: { ++ unsigned ValSizeInBits = ArgVT.getSizeInBits(); ++ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); ++ unsigned Opcode = ++ VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; ++ Val = DAG.getNode( ++ Opcode, DL, VA.getLocVT(), Val, ++ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); ++ break; ++ } ++ } ++ ++ // If this is an value smaller than the argument slot size (32-bit for LP32, ++ // 64-bit for LPX32/LP64), it has been promoted in some way to the argument slot ++ // size. Extract the value and insert any appropriate assertions regarding ++ // sign/zero extension. ++ switch (VA.getLocInfo()) { ++ default: ++ llvm_unreachable("Unknown loc info!"); ++ case CCValAssign::Full: ++ break; ++ case CCValAssign::AExtUpper: ++ case CCValAssign::AExt: ++ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); ++ break; ++ case CCValAssign::SExtUpper: ++ case CCValAssign::SExt: { ++ if ((ArgVT == MVT::i1) || (ArgVT == MVT::i8) || (ArgVT == MVT::i16)) { ++ SDValue SubReg = DAG.getTargetConstant(LoongArch::sub_32, DL, MVT::i32); ++ Val = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, ValVT, ++ Val, SubReg), ++ 0); ++ } else { ++ Val = ++ DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); ++ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); ++ } ++ break; ++ } ++ case CCValAssign::ZExtUpper: ++ case CCValAssign::ZExt: ++ Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); ++ Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); ++ break; ++ case CCValAssign::BCvt: ++ Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); ++ break; ++ } ++ ++ return Val; ++} ++ ++//===----------------------------------------------------------------------===// ++// Formal Arguments Calling Convention Implementation ++//===----------------------------------------------------------------------===// ++/// LowerFormalArguments - transform physical registers into virtual registers ++/// and generate load operations for arguments places on the stack. ++SDValue LoongArchTargetLowering::LowerFormalArguments( ++ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, ++ const SmallVectorImpl &Ins, const SDLoc &DL, ++ SelectionDAG &DAG, SmallVectorImpl &InVals) const { ++ MachineFunction &MF = DAG.getMachineFunction(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); ++ ++ LoongArchFI->setVarArgsFrameIndex(0); ++ ++ // Used with vargs to acumulate store chains. ++ std::vector OutChains; ++ ++ // Assign locations to all of the incoming arguments. ++ SmallVector ArgLocs; ++ LoongArchCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, ++ *DAG.getContext()); ++ const Function &Func = DAG.getMachineFunction().getFunction(); ++ Function::const_arg_iterator FuncArg = Func.arg_begin(); ++ ++ CCInfo.AnalyzeFormalArguments(Ins, CC_LoongArch_FixedArg); ++ LoongArchFI->setFormalArgInfo(CCInfo.getNextStackOffset(), ++ CCInfo.getInRegsParamsCount() > 0); ++ ++ unsigned CurArgIdx = 0; ++ CCInfo.rewindByValRegsInfo(); ++ ++ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { ++ CCValAssign &VA = ArgLocs[i]; ++ if (Ins[i].isOrigArg()) { ++ std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); ++ CurArgIdx = Ins[i].getOrigArgIndex(); ++ } ++ EVT ValVT = VA.getValVT(); ++ ISD::ArgFlagsTy Flags = Ins[i].Flags; ++ bool IsRegLoc = VA.isRegLoc(); ++ ++ if (Flags.isByVal()) { ++ assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); ++ unsigned FirstByValReg, LastByValReg; ++ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); ++ CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); ++ ++ assert(Flags.getByValSize() && ++ "ByVal args of size 0 should have been ignored by front-end."); ++ assert(ByValIdx < CCInfo.getInRegsParamsCount()); ++ copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, ++ FirstByValReg, LastByValReg, VA, CCInfo); ++ CCInfo.nextInRegsParam(); ++ continue; ++ } ++ ++ // Arguments stored on registers ++ if (IsRegLoc) { ++ MVT RegVT = VA.getLocVT(); ++ unsigned ArgReg = VA.getLocReg(); ++ const TargetRegisterClass *RC = getRegClassFor(RegVT); ++ ++ // Transform the arguments stored on ++ // physical registers into virtual ones ++ unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); ++ SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); ++ ++ ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); ++ ++ // Handle floating point arguments passed in integer registers and ++ // long double arguments passed in floating point registers. ++ if ((RegVT == MVT::i32 && ValVT == MVT::f32) || ++ (RegVT == MVT::i64 && ValVT == MVT::f64) || ++ (RegVT == MVT::f64 && ValVT == MVT::i64)) ++ ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); ++ else if (ABI.IsLP32() && RegVT == MVT::i32 && ++ ValVT == MVT::f64) { ++ // TODO: lp32 ++ } ++ ++ InVals.push_back(ArgValue); ++ } else { // VA.isRegLoc() ++ MVT LocVT = VA.getLocVT(); ++ ++ if (ABI.IsLP32()) { ++ // We ought to be able to use LocVT directly but LP32 sets it to i32 ++ // when allocating floating point values to integer registers. ++ // This shouldn't influence how we load the value into registers unless ++ // we are targeting softfloat. ++ if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat()) ++ LocVT = VA.getValVT(); ++ } ++ ++ // sanity check ++ assert(VA.isMemLoc()); ++ ++ // The stack pointer offset is relative to the caller stack frame. ++ int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8, ++ VA.getLocMemOffset(), true); ++ ++ // Create load nodes to retrieve arguments from the stack ++ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); ++ SDValue ArgValue = DAG.getLoad( ++ LocVT, DL, Chain, FIN, ++ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); ++ OutChains.push_back(ArgValue.getValue(1)); ++ ++ ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); ++ ++ InVals.push_back(ArgValue); ++ } ++ } ++ ++ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { ++ // The loongarch ABIs for returning structs by value requires that we copy ++ // the sret argument into $v0 for the return. Save the argument into ++ // a virtual register so that we can access it from the return points. ++ if (Ins[i].Flags.isSRet()) { ++ unsigned Reg = LoongArchFI->getSRetReturnReg(); ++ if (!Reg) { ++ Reg = MF.getRegInfo().createVirtualRegister( ++ getRegClassFor(ABI.IsLP64() ? MVT::i64 : MVT::i32)); ++ LoongArchFI->setSRetReturnReg(Reg); ++ } ++ SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); ++ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); ++ break; ++ } + } +- return SDValue(); ++ ++ if (IsVarArg) ++ writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo); ++ ++ // All stores are grouped in one node to allow the matching between ++ // the size of Ins and InVals. This only happens when on varg functions ++ if (!OutChains.empty()) { ++ OutChains.push_back(Chain); ++ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); ++ } ++ ++ return Chain; + } + +-static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, +- MachineBasicBlock &MBB, +- const TargetInstrInfo &TII) { +- if (!ZeroDivCheck) +- return &MBB; ++//===----------------------------------------------------------------------===// ++// Return Value Calling Convention Implementation ++//===----------------------------------------------------------------------===// + +- // Build instructions: +- // div(or mod) $dst, $dividend, $divisor +- // bnez $divisor, 8 +- // break 7 +- // fallthrough +- MachineOperand &Divisor = MI.getOperand(2); +- auto FallThrough = std::next(MI.getIterator()); ++bool ++LoongArchTargetLowering::CanLowerReturn(CallingConv::ID CallConv, ++ MachineFunction &MF, bool IsVarArg, ++ const SmallVectorImpl &Outs, ++ LLVMContext &Context) const { ++ SmallVector RVLocs; ++ LoongArchCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); ++ return CCInfo.CheckReturn(Outs, RetCC_LoongArch); ++} + +- BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BNEZ)) +- .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) +- .addImm(8); ++bool ++LoongArchTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { ++ if ((ABI.IsLPX32() || ABI.IsLP64()) && Type == MVT::i32) ++ return true; + +- // See linux header file arch/loongarch/include/uapi/asm/break.h for the +- // definition of BRK_DIVZERO. +- BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BREAK)) +- .addImm(7/*BRK_DIVZERO*/); ++ return IsSigned; ++} + +- // Clear Divisor's kill flag. +- Divisor.setIsKill(false); ++SDValue ++LoongArchTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, ++ bool IsVarArg, ++ const SmallVectorImpl &Outs, ++ const SmallVectorImpl &OutVals, ++ const SDLoc &DL, SelectionDAG &DAG) const { ++ // CCValAssign - represent the assignment of ++ // the return value to a location ++ SmallVector RVLocs; ++ MachineFunction &MF = DAG.getMachineFunction(); + +- return &MBB; ++ // CCState - Info about the registers and stack slot. ++ LoongArchCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); ++ ++ // Analyze return values. ++ CCInfo.AnalyzeReturn(Outs, RetCC_LoongArch); ++ ++ SDValue Flag; ++ SmallVector RetOps(1, Chain); ++ ++ // Copy the result values into the output registers. ++ for (unsigned i = 0; i != RVLocs.size(); ++i) { ++ SDValue Val = OutVals[i]; ++ CCValAssign &VA = RVLocs[i]; ++ assert(VA.isRegLoc() && "Can only return in registers!"); ++ bool UseUpperBits = false; ++ ++ switch (VA.getLocInfo()) { ++ default: ++ llvm_unreachable("Unknown loc info!"); ++ case CCValAssign::Full: ++ break; ++ case CCValAssign::BCvt: ++ Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val); ++ break; ++ case CCValAssign::AExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::AExt: ++ Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val); ++ break; ++ case CCValAssign::ZExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::ZExt: ++ Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val); ++ break; ++ case CCValAssign::SExtUpper: ++ UseUpperBits = true; ++ LLVM_FALLTHROUGH; ++ case CCValAssign::SExt: ++ Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val); ++ break; ++ } ++ ++ if (UseUpperBits) { ++ unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); ++ unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); ++ Val = DAG.getNode( ++ ISD::SHL, DL, VA.getLocVT(), Val, ++ DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); ++ } ++ ++ Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); ++ ++ // Guarantee that all emitted copies are stuck together with flags. ++ Flag = Chain.getValue(1); ++ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); ++ } ++ ++ // The loongarch ABIs for returning structs by value requires that we copy ++ // the sret argument into $v0 for the return. We saved the argument into ++ // a virtual register in the entry block, so now we copy the value out ++ // and into $v0. ++ if (MF.getFunction().hasStructRetAttr()) { ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); ++ unsigned Reg = LoongArchFI->getSRetReturnReg(); ++ ++ if (!Reg) ++ llvm_unreachable("sret virtual register not created in the entry block"); ++ SDValue Val = ++ DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout())); ++ unsigned A0 = ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; ++ ++ Chain = DAG.getCopyToReg(Chain, DL, A0, Val, Flag); ++ Flag = Chain.getValue(1); ++ RetOps.push_back(DAG.getRegister(A0, getPointerTy(DAG.getDataLayout()))); ++ } ++ ++ RetOps[0] = Chain; // Update chain. ++ ++ // Add the flag if we have it. ++ if (Flag.getNode()) ++ RetOps.push_back(Flag); ++ ++ // Standard return on LoongArch is a "jr $ra" ++ return DAG.getNode(LoongArchISD::Ret, DL, MVT::Other, RetOps); + } + +-MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter( +- MachineInstr &MI, MachineBasicBlock *BB) const { ++//===----------------------------------------------------------------------===// ++// LoongArch Inline Assembly Support ++//===----------------------------------------------------------------------===// + +- switch (MI.getOpcode()) { ++/// getConstraintType - Given a constraint letter, return the type of ++/// constraint it is for this target. ++LoongArchTargetLowering::ConstraintType ++LoongArchTargetLowering::getConstraintType(StringRef Constraint) const { ++ // LoongArch specific constraints ++ // GCC config/loongarch/constraints.md ++ // ++ // 'f': Floating Point register ++ // 'G': Floating-point 0 ++ // 'l': Signed 16-bit constant ++ // 'R': Memory address that can be used in a non-macro load or store ++ // "ZC" Memory address with 16-bit and 4 bytes aligned offset ++ // "ZB" Memory address with 0 offset ++ ++ if (Constraint.size() == 1) { ++ switch (Constraint[0]) { ++ default : break; ++ case 'f': ++ return C_RegisterClass; ++ case 'l': ++ case 'G': ++ return C_Other; ++ case 'R': ++ return C_Memory; ++ } ++ } ++ ++ if (Constraint == "ZC" || Constraint == "ZB") ++ return C_Memory; ++ ++ return TargetLowering::getConstraintType(Constraint); ++} ++ ++/// Examine constraint type and operand type and determine a weight value. ++/// This object must already have been set up with the operand type ++/// and the current alternative constraint selected. ++TargetLowering::ConstraintWeight ++LoongArchTargetLowering::getSingleConstraintMatchWeight( ++ AsmOperandInfo &info, const char *constraint) const { ++ ConstraintWeight weight = CW_Invalid; ++ Value *CallOperandVal = info.CallOperandVal; ++ // If we don't have a value, we can't do a match, ++ // but allow it at the lowest weight. ++ if (!CallOperandVal) ++ return CW_Default; ++ Type *type = CallOperandVal->getType(); ++ // Look at the constraint type. ++ switch (*constraint) { + default: +- llvm_unreachable("Unexpected instr type to insert"); +- case LoongArch::DIV_W: +- case LoongArch::DIV_WU: +- case LoongArch::MOD_W: +- case LoongArch::MOD_WU: +- case LoongArch::DIV_D: +- case LoongArch::DIV_DU: +- case LoongArch::MOD_D: +- case LoongArch::MOD_DU: +- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo()); ++ weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); ++ break; ++ case 'f': // FPU ++ if (Subtarget.hasLSX() && type->isVectorTy() && ++ type->getPrimitiveSizeInBits() == 128) ++ weight = CW_Register; ++ else if (Subtarget.hasLASX() && type->isVectorTy() && ++ type->getPrimitiveSizeInBits() == 256) ++ weight = CW_Register; ++ else if (type->isFloatTy()) ++ weight = CW_Register; ++ break; ++ case 'l': // signed 16 bit immediate ++ case 'I': // signed 12 bit immediate ++ case 'J': // integer zero ++ case 'G': // floating-point zero ++ case 'K': // unsigned 12 bit immediate ++ if (isa(CallOperandVal)) ++ weight = CW_Constant; ++ break; ++ case 'm': ++ case 'R': ++ weight = CW_Memory; + break; + } ++ return weight; + } + +-const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { +- switch ((LoongArchISD::NodeType)Opcode) { +- case LoongArchISD::FIRST_NUMBER: +- break; +- +-#define NODE_NAME_CASE(node) \ +- case LoongArchISD::node: \ +- return "LoongArchISD::" #node; +- +- // TODO: Add more target-dependent nodes later. +- NODE_NAME_CASE(CALL) +- NODE_NAME_CASE(RET) +- NODE_NAME_CASE(SLL_W) +- NODE_NAME_CASE(SRA_W) +- NODE_NAME_CASE(SRL_W) +- NODE_NAME_CASE(BSTRINS) +- NODE_NAME_CASE(BSTRPICK) +- NODE_NAME_CASE(MOVGR2FR_W_LA64) +- NODE_NAME_CASE(MOVFR2GR_S_LA64) +- NODE_NAME_CASE(FTINT) +- } +-#undef NODE_NAME_CASE ++/// This is a helper function to parse a physical register string and split it ++/// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag ++/// that is returned indicates whether parsing was successful. The second flag ++/// is true if the numeric part exists. ++static std::pair parsePhysicalReg(StringRef C, StringRef &Prefix, ++ unsigned long long &Reg) { ++ if (C.empty() || C.front() != '{' || C.back() != '}') ++ return std::make_pair(false, false); ++ ++ // Search for the first numeric character. ++ StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; ++ I = std::find_if(B, E, isdigit); ++ ++ Prefix = StringRef(B, I - B); ++ ++ // The second flag is set to false if no numeric characters were found. ++ if (I == E) ++ return std::make_pair(true, false); ++ ++ // Parse the numeric characters. ++ return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg), ++ true); ++} ++ ++EVT LoongArchTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, ++ ISD::NodeType) const { ++ bool Cond = !Subtarget.isABI_LP32() && VT.getSizeInBits() == 32; ++ EVT MinVT = getRegisterType(Context, Cond ? MVT::i64 : MVT::i32); ++ return VT.bitsLT(MinVT) ? MinVT : VT; ++} ++ ++static const TargetRegisterClass *getRegisterClassForVT(MVT VT, bool Is64Bit) { ++ // Newer llvm versions (>= 12) do not require simple VTs for constraints and ++ // they use MVT::Other for constraints with complex VTs. For more details, ++ // please see https://reviews.llvm.org/D91710. ++ if (VT == MVT::Other || VT.getSizeInBits() <= 32) ++ return &LoongArch::GPR32RegClass; ++ if (VT.getSizeInBits() <= 64) ++ return Is64Bit ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; + return nullptr; + } + +-//===----------------------------------------------------------------------===// +-// Calling Convention Implementation +-//===----------------------------------------------------------------------===// +-// FIXME: Now, we only support CallingConv::C with fixed arguments which are +-// passed with integer or floating-point registers. +-const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, +- LoongArch::R7, LoongArch::R8, LoongArch::R9, +- LoongArch::R10, LoongArch::R11}; +-const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2, +- LoongArch::F3, LoongArch::F4, LoongArch::F5, +- LoongArch::F6, LoongArch::F7}; +-const MCPhysReg ArgFPR64s[] = { +- LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, +- LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64}; +- +-// Implements the LoongArch calling convention. Returns true upon failure. +-static bool CC_LoongArch(unsigned ValNo, MVT ValVT, +- CCValAssign::LocInfo LocInfo, CCState &State) { +- // Allocate to a register if possible. +- Register Reg; +- +- if (ValVT == MVT::f32) +- Reg = State.AllocateReg(ArgFPR32s); +- else if (ValVT == MVT::f64) +- Reg = State.AllocateReg(ArgFPR64s); +- else +- Reg = State.AllocateReg(ArgGPRs); +- if (Reg) { +- State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); +- return false; ++std::pair LoongArchTargetLowering:: ++parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { ++ const TargetRegisterInfo *TRI = ++ Subtarget.getRegisterInfo(); ++ const TargetRegisterClass *RC; ++ StringRef Prefix; ++ unsigned long long Reg; ++ ++ std::pair R = parsePhysicalReg(C, Prefix, Reg); ++ ++ if (!R.first) ++ return std::make_pair(0U, nullptr); ++ ++ if (!R.second) ++ return std::make_pair(0U, nullptr); ++ ++ if (Prefix == "$f") { // Parse $f0-$f31. ++ // If the size of FP registers is 64-bit or Reg is an even number, select ++ // the 64-bit register class. Otherwise, select the 32-bit register class. ++ if (VT == MVT::Other) ++ VT = (Subtarget.isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32; ++ ++ RC = getRegClassFor(VT); ++ } ++ else if (Prefix == "$vr") { // Parse $vr0-$vr31. ++ RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); ++ } ++ else if (Prefix == "$xr") { // Parse $xr0-$xr31. ++ RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); ++ } ++ else if (Prefix == "$fcc") // Parse $fcc0-$fcc7. ++ RC = TRI->getRegClass(LoongArch::FCFRRegClassID); ++ else { // Parse $r0-$r31. ++ assert(Prefix == "$r"); ++ if ((RC = getRegisterClassForVT(VT, Subtarget.is64Bit())) == nullptr) { ++ // This will generate an error message. ++ return std::make_pair(0U, nullptr); ++ } + } + +- // TODO: Handle arguments passed without register. +- return true; ++ assert(Reg < RC->getNumRegs()); ++ ++ if (RC == &LoongArch::GPR64RegClass || RC == &LoongArch::GPR32RegClass) { ++ // Sync with the GPR32/GPR64 RegisterClass in LoongArchRegisterInfo.td ++ // that just like LoongArchAsmParser.cpp ++ switch (Reg) { ++ case 0: return std::make_pair(*(RC->begin() + 0), RC); // r0 ++ case 1: return std::make_pair(*(RC->begin() + 27), RC); // r1 ++ case 2: return std::make_pair(*(RC->begin() + 28), RC); // r2 ++ case 3: return std::make_pair(*(RC->begin() + 29), RC); // r3 ++ case 4: return std::make_pair(*(RC->begin() + 1), RC); // r4 ++ case 5: return std::make_pair(*(RC->begin() + 2), RC); // r5 ++ case 6: return std::make_pair(*(RC->begin() + 3), RC); // r6 ++ case 7: return std::make_pair(*(RC->begin() + 4), RC); // r7 ++ case 8: return std::make_pair(*(RC->begin() + 5), RC); // r8 ++ case 9: return std::make_pair(*(RC->begin() + 6), RC); // r9 ++ case 10: return std::make_pair(*(RC->begin() + 7), RC); // r10 ++ case 11: return std::make_pair(*(RC->begin() + 8), RC); // r11 ++ case 12: return std::make_pair(*(RC->begin() + 9), RC); // r12 ++ case 13: return std::make_pair(*(RC->begin() + 10), RC); // r13 ++ case 14: return std::make_pair(*(RC->begin() + 11), RC); // r14 ++ case 15: return std::make_pair(*(RC->begin() + 12), RC); // r15 ++ case 16: return std::make_pair(*(RC->begin() + 13), RC); // r16 ++ case 17: return std::make_pair(*(RC->begin() + 14), RC); // r17 ++ case 18: return std::make_pair(*(RC->begin() + 15), RC); // r18 ++ case 19: return std::make_pair(*(RC->begin() + 16), RC); // r19 ++ case 20: return std::make_pair(*(RC->begin() + 17), RC); // r20 ++ case 21: return std::make_pair(*(RC->begin() + 30), RC); // r21 ++ case 22: return std::make_pair(*(RC->begin() + 31), RC); // r22 ++ case 23: return std::make_pair(*(RC->begin() + 18), RC); // r23 ++ case 24: return std::make_pair(*(RC->begin() + 19), RC); // r24 ++ case 25: return std::make_pair(*(RC->begin() + 20), RC); // r25 ++ case 26: return std::make_pair(*(RC->begin() + 21), RC); // r26 ++ case 27: return std::make_pair(*(RC->begin() + 22), RC); // r27 ++ case 28: return std::make_pair(*(RC->begin() + 23), RC); // r28 ++ case 29: return std::make_pair(*(RC->begin() + 24), RC); // r29 ++ case 30: return std::make_pair(*(RC->begin() + 25), RC); // r30 ++ case 31: return std::make_pair(*(RC->begin() + 26), RC); // r31 ++ } ++ } ++ return std::make_pair(*(RC->begin() + Reg), RC); + } + +-void LoongArchTargetLowering::analyzeInputArgs( +- CCState &CCInfo, const SmallVectorImpl &Ins, +- LoongArchCCAssignFn Fn) const { +- for (unsigned i = 0, e = Ins.size(); i != e; ++i) { +- MVT ArgVT = Ins[i].VT; ++/// Given a register class constraint, like 'r', if this corresponds directly ++/// to an LLVM register class, return a register of 0 and the register class ++/// pointer. ++std::pair ++LoongArchTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, ++ StringRef Constraint, ++ MVT VT) const { ++ if (Constraint.size() == 1) { ++ switch (Constraint[0]) { ++ case 'r': ++ return std::make_pair(0U, getRegisterClassForVT(VT, Subtarget.is64Bit())); ++ case 'f': // FPU or LSX register ++ if (VT == MVT::v16i8) ++ return std::make_pair(0U, &LoongArch::LSX128BRegClass); ++ else if (VT == MVT::v8i16) ++ return std::make_pair(0U, &LoongArch::LSX128HRegClass); ++ else if (VT == MVT::v4i32 || VT == MVT::v4f32) ++ return std::make_pair(0U, &LoongArch::LSX128WRegClass); ++ else if (VT == MVT::v2i64 || VT == MVT::v2f64) ++ return std::make_pair(0U, &LoongArch::LSX128DRegClass); ++ else if (VT == MVT::v32i8) ++ return std::make_pair(0U, &LoongArch::LASX256BRegClass); ++ else if (VT == MVT::v16i16) ++ return std::make_pair(0U, &LoongArch::LASX256HRegClass); ++ else if (VT == MVT::v8i32 || VT == MVT::v8f32) ++ return std::make_pair(0U, &LoongArch::LASX256WRegClass); ++ else if (VT == MVT::v4i64 || VT == MVT::v4f64) ++ return std::make_pair(0U, &LoongArch::LASX256DRegClass); ++ else if (VT == MVT::f32) ++ return std::make_pair(0U, &LoongArch::FGR32RegClass); ++ else if (VT == MVT::f64) ++ return std::make_pair(0U, &LoongArch::FGR64RegClass); ++ break; ++ } ++ } ++ ++ std::pair R; ++ R = parseRegForInlineAsmConstraint(Constraint, VT); ++ ++ if (R.second) ++ return R; ++ ++ return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); ++} + +- if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { +- LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " +- << EVT(ArgVT).getEVTString() << '\n'); +- llvm_unreachable(""); ++/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops ++/// vector. If it is invalid, don't add anything to Ops. ++void LoongArchTargetLowering::LowerAsmOperandForConstraint(SDValue Op, ++ std::string &Constraint, ++ std::vector&Ops, ++ SelectionDAG &DAG) const { ++ SDLoc DL(Op); ++ SDValue Result; ++ ++ // Only support length 1 constraints for now. ++ if (Constraint.length() > 1) return; ++ ++ char ConstraintLetter = Constraint[0]; ++ switch (ConstraintLetter) { ++ default: break; // This will fall through to the generic implementation ++ case 'l': // Signed 16 bit constant ++ // If this fails, the parent routine will give an error ++ if (ConstantSDNode *C = dyn_cast(Op)) { ++ EVT Type = Op.getValueType(); ++ int64_t Val = C->getSExtValue(); ++ if (isInt<16>(Val)) { ++ Result = DAG.getTargetConstant(Val, DL, Type); ++ break; ++ } ++ } ++ return; ++ case 'I': // Signed 12 bit constant ++ // If this fails, the parent routine will give an error ++ if (ConstantSDNode *C = dyn_cast(Op)) { ++ EVT Type = Op.getValueType(); ++ int64_t Val = C->getSExtValue(); ++ if (isInt<12>(Val)) { ++ Result = DAG.getTargetConstant(Val, DL, Type); ++ break; ++ } ++ } ++ return; ++ case 'J': // integer zero ++ if (ConstantSDNode *C = dyn_cast(Op)) { ++ EVT Type = Op.getValueType(); ++ int64_t Val = C->getZExtValue(); ++ if (Val == 0) { ++ Result = DAG.getTargetConstant(0, DL, Type); ++ break; ++ } + } ++ return; ++ case 'G': // floating-point zero ++ if (ConstantFPSDNode *C = dyn_cast(Op)) { ++ if (C->isZero()) { ++ EVT Type = Op.getValueType(); ++ Result = DAG.getTargetConstantFP(0, DL, Type); ++ break; ++ } ++ } ++ return; ++ case 'K': // unsigned 12 bit immediate ++ if (ConstantSDNode *C = dyn_cast(Op)) { ++ EVT Type = Op.getValueType(); ++ uint64_t Val = (uint64_t)C->getZExtValue(); ++ if (isUInt<12>(Val)) { ++ Result = DAG.getTargetConstant(Val, DL, Type); ++ break; ++ } ++ } ++ return; ++ } ++ ++ if (Result.getNode()) { ++ Ops.push_back(Result); ++ return; ++ } ++ ++ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); ++} ++ ++bool LoongArchTargetLowering::isLegalAddressingMode(const DataLayout &DL, ++ const AddrMode &AM, Type *Ty, ++ unsigned AS, Instruction *I) const { ++ // No global is ever allowed as a base. ++ if (AM.BaseGV) ++ return false; ++ ++ switch (AM.Scale) { ++ case 0: // "r+i" or just "i", depending on HasBaseReg. ++ break; ++ case 1: ++ if (!AM.HasBaseReg) // allow "r+i". ++ break; ++ return false; // disallow "r+r" or "r+r+i". ++ default: ++ return false; + } ++ ++ return true; + } + +-void LoongArchTargetLowering::analyzeOutputArgs( +- CCState &CCInfo, const SmallVectorImpl &Outs, +- LoongArchCCAssignFn Fn) const { +- for (unsigned i = 0, e = Outs.size(); i != e; ++i) { +- MVT ArgVT = Outs[i].VT; ++bool ++LoongArchTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { ++ // The LoongArch target isn't yet aware of offsets. ++ return false; ++} + +- if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { +- LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " +- << EVT(ArgVT).getEVTString() << "\n"); +- llvm_unreachable(""); ++EVT LoongArchTargetLowering::getOptimalMemOpType( ++ const MemOp &Op, const AttributeList &FuncAttributes) const { ++ if (!FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) { ++ if (Op.size() >= 16) { ++ if (Op.size() >= 32 && Subtarget.hasLASX()) { ++ return MVT::v32i8; ++ } ++ if (Subtarget.hasLSX()) ++ return MVT::v16i8; + } + } ++ ++ if (Subtarget.is64Bit()) ++ return MVT::i64; ++ ++ return MVT::i32; + } + +-static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, +- const CCValAssign &VA, const SDLoc &DL, +- const LoongArchTargetLowering &TLI) { +- MachineFunction &MF = DAG.getMachineFunction(); +- MachineRegisterInfo &RegInfo = MF.getRegInfo(); +- EVT LocVT = VA.getLocVT(); +- const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); +- Register VReg = RegInfo.createVirtualRegister(RC); +- RegInfo.addLiveIn(VA.getLocReg(), VReg); ++/// isFPImmLegal - Returns true if the target can instruction select the ++/// specified FP immediate natively. If false, the legalizer will ++/// materialize the FP immediate as a load from a constant pool. ++bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, ++ bool ForCodeSize) const { ++ if (VT != MVT::f32 && VT != MVT::f64) ++ return false; ++ if (Imm.isNegZero()) ++ return false; ++ return (Imm.isZero() || Imm.isExactlyValue(+1.0)); ++} + +- return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); ++bool LoongArchTargetLowering::useSoftFloat() const { ++ return Subtarget.useSoftFloat(); + } + +-// Transform physical registers into virtual registers. +-SDValue LoongArchTargetLowering::LowerFormalArguments( +- SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, +- const SmallVectorImpl &Ins, const SDLoc &DL, +- SelectionDAG &DAG, SmallVectorImpl &InVals) const { ++// Return whether the an instruction can potentially be optimized to a tail ++// call. This will cause the optimizers to attempt to move, or duplicate, ++// return instructions to help enable tail call optimizations for this ++// instruction. ++bool LoongArchTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { ++ return CI->isTailCall(); ++} + ++void LoongArchTargetLowering::copyByValRegs( ++ SDValue Chain, const SDLoc &DL, std::vector &OutChains, ++ SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, ++ SmallVectorImpl &InVals, const Argument *FuncArg, ++ unsigned FirstReg, unsigned LastReg, const CCValAssign &VA, ++ LoongArchCCState &State) const { + MachineFunction &MF = DAG.getMachineFunction(); +- +- switch (CallConv) { +- default: +- llvm_unreachable("Unsupported calling convention"); +- case CallingConv::C: +- break; ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); ++ unsigned NumRegs = LastReg - FirstReg; ++ unsigned RegAreaSize = NumRegs * GPRSizeInBytes; ++ unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); ++ int FrameObjOffset; ++ ArrayRef ByValArgRegs = ABI.GetByValArgRegs(); ++ ++ if (RegAreaSize) ++ FrameObjOffset = -(int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes); ++ else ++ FrameObjOffset = VA.getLocMemOffset(); ++ ++ // Create frame object. ++ EVT PtrTy = getPointerTy(DAG.getDataLayout()); ++ // Make the fixed object stored to mutable so that the load instructions ++ // referencing it have their memory dependencies added. ++ // Set the frame object as isAliased which clears the underlying objects ++ // vector in ScheduleDAGInstrs::buildSchedGraph() resulting in addition of all ++ // stores as dependencies for loads referencing this fixed object. ++ int FI = MFI.CreateFixedObject(FrameObjSize, FrameObjOffset, false, true); ++ SDValue FIN = DAG.getFrameIndex(FI, PtrTy); ++ InVals.push_back(FIN); ++ ++ if (!NumRegs) ++ return; ++ ++ // Copy arg registers. ++ MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); ++ const TargetRegisterClass *RC = getRegClassFor(RegTy); ++ ++ for (unsigned I = 0; I < NumRegs; ++I) { ++ unsigned ArgReg = ByValArgRegs[FirstReg + I]; ++ unsigned VReg = addLiveIn(MF, ArgReg, RC); ++ unsigned Offset = I * GPRSizeInBytes; ++ SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, ++ DAG.getConstant(Offset, DL, PtrTy)); ++ SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), ++ StorePtr, MachinePointerInfo(FuncArg, Offset)); ++ OutChains.push_back(Store); + } ++} + +- // Assign locations to all of the incoming arguments. +- SmallVector ArgLocs; +- CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); ++// Copy byVal arg to registers and stack. ++void LoongArchTargetLowering::passByValArg( ++ SDValue Chain, const SDLoc &DL, ++ std::deque> &RegsToPass, ++ SmallVectorImpl &MemOpChains, SDValue StackPtr, ++ MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, ++ unsigned LastReg, const ISD::ArgFlagsTy &Flags, ++ const CCValAssign &VA) const { ++ unsigned ByValSizeInBytes = Flags.getByValSize(); ++ unsigned OffsetInBytes = 0; // From beginning of struct ++ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); ++ Align Alignment = ++ std::min(Flags.getNonZeroByValAlign(), Align(RegSizeInBytes)); ++ EVT PtrTy = getPointerTy(DAG.getDataLayout()), ++ RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); ++ unsigned NumRegs = LastReg - FirstReg; ++ ++ if (NumRegs) { ++ ArrayRef ArgRegs = ABI.GetByValArgRegs(); ++ bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); ++ unsigned I = 0; ++ ++ // Copy words to registers. ++ for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { ++ SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, ++ DAG.getConstant(OffsetInBytes, DL, PtrTy)); ++ SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, ++ MachinePointerInfo(), Alignment); ++ MemOpChains.push_back(LoadVal.getValue(1)); ++ unsigned ArgReg = ArgRegs[FirstReg + I]; ++ RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); ++ } + +- analyzeInputArgs(CCInfo, Ins, CC_LoongArch); ++ // Return if the struct has been fully copied. ++ if (ByValSizeInBytes == OffsetInBytes) ++ return; + +- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) +- InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); ++ // Copy the remainder of the byval argument with sub-word loads and shifts. ++ if (LeftoverBytes) { ++ SDValue Val; + +- return Chain; +-} ++ for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0; ++ OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) { ++ unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes; + +-// Lower a call to a callseq_start + CALL + callseq_end chain, and add input +-// and output parameter nodes. +-SDValue +-LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI, +- SmallVectorImpl &InVals) const { +- SelectionDAG &DAG = CLI.DAG; +- SDLoc &DL = CLI.DL; +- SmallVectorImpl &Outs = CLI.Outs; +- SmallVectorImpl &OutVals = CLI.OutVals; +- SmallVectorImpl &Ins = CLI.Ins; +- SDValue Chain = CLI.Chain; +- SDValue Callee = CLI.Callee; +- CallingConv::ID CallConv = CLI.CallConv; +- bool IsVarArg = CLI.IsVarArg; +- EVT PtrVT = getPointerTy(DAG.getDataLayout()); +- CLI.IsTailCall = false; ++ if (RemainingSizeInBytes < LoadSizeInBytes) ++ continue; + +- if (IsVarArg) +- report_fatal_error("LowerCall with varargs not implemented"); ++ // Load subword. ++ SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, ++ DAG.getConstant(OffsetInBytes, DL, ++ PtrTy)); ++ SDValue LoadVal = DAG.getExtLoad( ++ ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), ++ MVT::getIntegerVT(LoadSizeInBytes * 8), Alignment); ++ MemOpChains.push_back(LoadVal.getValue(1)); + +- MachineFunction &MF = DAG.getMachineFunction(); ++ // Shift the loaded value. ++ unsigned Shamt; + +- // Analyze the operands of the call, assigning locations to each operand. +- SmallVector ArgLocs; +- CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); ++ Shamt = TotalBytesLoaded * 8; + +- analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch); ++ SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, ++ DAG.getConstant(Shamt, DL, MVT::i32)); + +- // Get a count of how many bytes are to be pushed on the stack. +- unsigned NumBytes = ArgCCInfo.getNextStackOffset(); ++ if (Val.getNode()) ++ Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); ++ else ++ Val = Shift; + +- for (auto &Arg : Outs) { +- if (!Arg.Flags.isByVal()) +- continue; +- report_fatal_error("Passing arguments byval not implemented"); ++ OffsetInBytes += LoadSizeInBytes; ++ TotalBytesLoaded += LoadSizeInBytes; ++ Alignment = std::min(Alignment, Align(LoadSizeInBytes)); ++ } ++ ++ unsigned ArgReg = ArgRegs[FirstReg + I]; ++ RegsToPass.push_back(std::make_pair(ArgReg, Val)); ++ return; ++ } + } + +- Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); ++ // Copy remainder of byval arg to it with memcpy. ++ unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; ++ SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, ++ DAG.getConstant(OffsetInBytes, DL, PtrTy)); ++ SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, ++ DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); ++ Chain = DAG.getMemcpy( ++ Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, DL, PtrTy), ++ Align(Alignment), /*isVolatile=*/false, /*AlwaysInline=*/false, ++ /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); ++ MemOpChains.push_back(Chain); ++} + +- // Copy argument values to their designated locations. +- SmallVector> RegsToPass; +- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { +- CCValAssign &VA = ArgLocs[i]; +- SDValue ArgValue = OutVals[i]; ++void LoongArchTargetLowering::writeVarArgRegs(std::vector &OutChains, ++ SDValue Chain, const SDLoc &DL, ++ SelectionDAG &DAG, ++ CCState &State) const { ++ ArrayRef ArgRegs = ABI.GetVarArgRegs(); ++ unsigned Idx = State.getFirstUnallocated(ArgRegs); ++ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); ++ MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); ++ const TargetRegisterClass *RC = getRegClassFor(RegTy); ++ MachineFunction &MF = DAG.getMachineFunction(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ LoongArchFunctionInfo *LoongArchFI = MF.getInfo(); + +- // Promote the value if needed. +- // For now, only handle fully promoted arguments. +- if (VA.getLocInfo() != CCValAssign::Full) +- report_fatal_error("Unknown loc info"); ++ // Offset of the first variable argument from stack pointer. ++ int VaArgOffset, VarArgsSaveSize; + +- if (VA.isRegLoc()) { +- // Queue up the argument copies and emit them at the end. +- RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); +- } else { +- report_fatal_error("Passing arguments via the stack not implemented"); +- } ++ if (ArgRegs.size() == Idx) { ++ VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes); ++ VarArgsSaveSize = 0; ++ } else { ++ VarArgsSaveSize = (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); ++ VaArgOffset = -VarArgsSaveSize; + } + +- SDValue Glue; ++ // Record the frame index of the first variable argument ++ // which is a value necessary to VASTART. ++ int FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); ++ LoongArchFI->setVarArgsFrameIndex(FI); ++ ++ // If saving an odd number of registers then create an extra stack slot to ++ // ensure that the frame pointer is 2*GRLEN-aligned, which in turn ensures ++ // offsets to even-numbered registered remain 2*GRLEN-aligned. ++ if (Idx % 2) { ++ MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset - (int)RegSizeInBytes, ++ true); ++ VarArgsSaveSize += RegSizeInBytes; ++ } + +- // Build a sequence of copy-to-reg nodes, chained and glued together. +- for (auto &Reg : RegsToPass) { +- Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); +- Glue = Chain.getValue(1); ++ // Copy the integer registers that have not been used for argument passing ++ // to the argument register save area. For LP32, the save area is allocated ++ // in the caller's stack frame, while for LPX32/LP64, it is allocated in the ++ // callee's stack frame. ++ for (unsigned I = Idx; I < ArgRegs.size(); ++ ++I, VaArgOffset += RegSizeInBytes) { ++ unsigned Reg = addLiveIn(MF, ArgRegs[I], RC); ++ SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); ++ FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); ++ SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); ++ SDValue Store = ++ DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo()); ++ cast(Store.getNode())->getMemOperand()->setValue( ++ (Value *)nullptr); ++ OutChains.push_back(Store); + } ++ LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize); ++} + +- // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a +- // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't +- // split it and then direct call can be matched by PseudoCALL. +- // FIXME: Add target flags for relocation. +- if (GlobalAddressSDNode *S = dyn_cast(Callee)) +- Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT); +- else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) +- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT); ++void LoongArchTargetLowering::HandleByVal(CCState *State, unsigned &Size, ++ Align Alignment) const { ++ const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); ++ ++ assert(Size && "Byval argument's size shouldn't be 0."); ++ ++ Alignment = std::min(Alignment, TFL->getStackAlign()); ++ ++ unsigned FirstReg = 0; ++ unsigned NumRegs = 0; ++ unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); ++ ArrayRef IntArgRegs = ABI.GetByValArgRegs(); ++ // FIXME: The LP32 case actually describes no shadow registers. ++ const MCPhysReg *ShadowRegs = ++ ABI.IsLP32() ? IntArgRegs.data() : LoongArch64DPRegs; ++ ++ // We used to check the size as well but we can't do that anymore since ++ // CCState::HandleByVal() rounds up the size after calling this function. ++ assert(Alignment >= Align(RegSizeInBytes) && ++ "Byval argument's alignment should be a multiple of RegSizeInBytes."); ++ ++ FirstReg = State->getFirstUnallocated(IntArgRegs); ++ ++ // If Alignment > RegSizeInBytes, the first arg register must be even. ++ // FIXME: This condition happens to do the right thing but it's not the ++ // right way to test it. We want to check that the stack frame offset ++ // of the register is aligned. ++ if ((Alignment > RegSizeInBytes) && (FirstReg % 2)) { ++ State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]); ++ ++FirstReg; ++ // assert(true && "debug#######################################"); ++ } + +- // The first call operand is the chain and the second is the target address. +- SmallVector Ops; +- Ops.push_back(Chain); +- Ops.push_back(Callee); ++ // Mark the registers allocated. ++ // Size = alignTo(Size, RegSizeInBytes); ++ // for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); ++ // Size -= RegSizeInBytes, ++I, ++NumRegs) ++ // State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); + +- // Add argument registers to the end of the list so that they are +- // known live into the call. +- for (auto &Reg : RegsToPass) +- Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); ++ State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); ++} + +- // Add a register mask operand representing the call-preserved registers. +- const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); +- const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); +- assert(Mask && "Missing call preserved mask for calling convention"); +- Ops.push_back(DAG.getRegisterMask(Mask)); ++MachineBasicBlock *LoongArchTargetLowering::emitPseudoSELECT(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ bool isFPCmp, ++ unsigned Opc) const { ++ const TargetInstrInfo *TII = ++ Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ // To "insert" a SELECT instruction, we actually have to insert the ++ // diamond control-flow pattern. The incoming instruction knows the ++ // destination vreg to set, the condition code register to branch on, the ++ // true/false values to select between, and a branch opcode to use. ++ const BasicBlock *LLVM_BB = BB->getBasicBlock(); ++ MachineFunction::iterator It = ++BB->getIterator(); ++ ++ // thisMBB: ++ // ... ++ // TrueVal = ... ++ // setcc r1, r2, r3 ++ // bNE r1, r0, copy1MBB ++ // fallthrough --> copy0MBB ++ MachineBasicBlock *thisMBB = BB; ++ MachineFunction *F = BB->getParent(); ++ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); ++ F->insert(It, copy0MBB); ++ F->insert(It, sinkMBB); ++ ++ // Transfer the remainder of BB and its successor edges to sinkMBB. ++ sinkMBB->splice(sinkMBB->begin(), BB, ++ std::next(MachineBasicBlock::iterator(MI)), BB->end()); ++ sinkMBB->transferSuccessorsAndUpdatePHIs(BB); ++ ++ // Next, add the true and fallthrough blocks as its successors. ++ BB->addSuccessor(copy0MBB); ++ BB->addSuccessor(sinkMBB); ++ ++ if (isFPCmp) { ++ // bc1[tf] cc, sinkMBB ++ BuildMI(BB, DL, TII->get(Opc)) ++ .addReg(MI.getOperand(1).getReg()) ++ .addMBB(sinkMBB); ++ } else { ++ BuildMI(BB, DL, TII->get(Opc)) ++ .addReg(MI.getOperand(1).getReg()) ++ .addReg(LoongArch::ZERO) ++ .addMBB(sinkMBB); ++ } + +- // Glue the call to the argument copies, if any. +- if (Glue.getNode()) +- Ops.push_back(Glue); ++ // copy0MBB: ++ // %FalseValue = ... ++ // # fallthrough to sinkMBB ++ BB = copy0MBB; + +- // Emit the call. +- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); ++ // Update machine-CFG edges ++ BB->addSuccessor(sinkMBB); + +- Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops); +- DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); +- Glue = Chain.getValue(1); ++ // sinkMBB: ++ // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] ++ // ... ++ BB = sinkMBB; + +- // Mark the end of the call, which is glued to the call itself. +- Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), +- DAG.getConstant(0, DL, PtrVT, true), Glue, DL); +- Glue = Chain.getValue(1); ++ BuildMI(*BB, BB->begin(), DL, TII->get(LoongArch::PHI), MI.getOperand(0).getReg()) ++ .addReg(MI.getOperand(2).getReg()) ++ .addMBB(thisMBB) ++ .addReg(MI.getOperand(3).getReg()) ++ .addMBB(copy0MBB); + +- // Assign locations to each value returned by this call. +- SmallVector RVLocs; +- CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); +- analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch); ++ MI.eraseFromParent(); // The pseudo instruction is gone now. + +- // Copy all of the result registers out of their specified physreg. +- for (auto &VA : RVLocs) { +- // Copy the value out. +- SDValue RetValue = +- DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); +- Chain = RetValue.getValue(1); +- Glue = RetValue.getValue(2); ++ return BB; ++} + +- InVals.push_back(Chain.getValue(0)); ++MachineBasicBlock *LoongArchTargetLowering::emitLSXCBranchPseudo( ++ MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const { ++ ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ const TargetRegisterClass *RC = &LoongArch::GPR32RegClass; ++ DebugLoc DL = MI.getDebugLoc(); ++ const BasicBlock *LLVM_BB = BB->getBasicBlock(); ++ MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); ++ MachineFunction *F = BB->getParent(); ++ MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); ++ F->insert(It, FBB); ++ F->insert(It, TBB); ++ F->insert(It, Sink); ++ ++ // Transfer the remainder of BB and its successor edges to Sink. ++ Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), ++ BB->end()); ++ Sink->transferSuccessorsAndUpdatePHIs(BB); ++ ++ // Add successors. ++ BB->addSuccessor(FBB); ++ BB->addSuccessor(TBB); ++ FBB->addSuccessor(Sink); ++ TBB->addSuccessor(Sink); ++ // Insert the real bnz.b instruction to $BB. ++ BuildMI(BB, DL, TII->get(BranchOp)) ++ .addReg(LoongArch::FCC0) ++ .addReg(MI.getOperand(1).getReg()); ++ ++ BuildMI(BB, DL, TII->get(LoongArch::BCNEZ)) ++ .addReg(LoongArch::FCC0) ++ .addMBB(TBB); ++ ++ // Fill $FBB. ++ unsigned RD1 = RegInfo.createVirtualRegister(RC); ++ BuildMI(*FBB, FBB->end(), DL, TII->get(LoongArch::ADDI_W), RD1) ++ .addReg(LoongArch::ZERO) ++ .addImm(0); ++ BuildMI(*FBB, FBB->end(), DL, TII->get(LoongArch::B32)).addMBB(Sink); ++ ++ // Fill $TBB. ++ unsigned RD2 = RegInfo.createVirtualRegister(RC); ++ BuildMI(*TBB, TBB->end(), DL, TII->get(LoongArch::ADDI_W), RD2) ++ .addReg(LoongArch::ZERO) ++ .addImm(1); ++ ++ // Insert phi function to $Sink. ++ BuildMI(*Sink, Sink->begin(), DL, TII->get(LoongArch::PHI), ++ MI.getOperand(0).getReg()) ++ .addReg(RD1) ++ .addMBB(FBB) ++ .addReg(RD2) ++ .addMBB(TBB); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return Sink; ++} ++ ++// Emit the COPY_FW pseudo instruction. ++// ++// copy_fw_pseudo $fd, $vk, n ++// => ++// vreplvei.w $rt, $vk, $n ++// copy $rt, $fd ++// ++// When n is zero, the equivalent operation can be performed with (potentially) ++// zero instructions due to register overlaps. ++MachineBasicBlock * ++LoongArchTargetLowering::emitCOPY_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Fd = MI.getOperand(0).getReg(); ++ unsigned Vk = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ ++ if (Lane == 0) { ++ unsigned Vj = Vk; ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Vj, 0, LoongArch::sub_lo); ++ } else { ++ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_W), Vj) ++ .addReg(Vk) ++ .addImm(Lane); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Vj, 0, LoongArch::sub_lo); + } + +- return Chain; ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the COPY_FD pseudo instruction. ++// ++// copy_fd_pseudo $fd, $vj, n ++// => ++// vreplvei.d $vd, $vj, $n ++// copy $fd, $vd:sub_64 ++// ++// When n is zero, the equivalent operation can be performed with (potentially) ++// zero instructions due to register overlaps. ++MachineBasicBlock * ++LoongArchTargetLowering::emitCOPY_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ unsigned Fd = MI.getOperand(0).getReg(); ++ unsigned Vk = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ if (Lane == 0) ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Vk, 0, LoongArch::sub_64); ++ else { ++ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); ++ assert(Lane == 1); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_D), Vj) ++ .addReg(Vk) ++ .addImm(Lane); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Vj, 0, LoongArch::sub_64); ++ } ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; + } + +-bool LoongArchTargetLowering::CanLowerReturn( +- CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, +- const SmallVectorImpl &Outs, LLVMContext &Context) const { +- // Any return value split in to more than two values can't be returned +- // directly. +- return Outs.size() <= 2; ++MachineBasicBlock * ++LoongArchTargetLowering::emitXCOPY_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Fd = MI.getOperand(0).getReg(); ++ unsigned Xk = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned Xj = Xk; ++ ++ if (Lane == 0) { ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Xj, 0, LoongArch::sub_lo); ++ } else { ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Rj) ++ .addReg(Xk) ++ .addImm(Lane); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd).addReg(Rj); ++ } ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; + } + +-SDValue LoongArchTargetLowering::LowerReturn( +- SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, +- const SmallVectorImpl &Outs, +- const SmallVectorImpl &OutVals, const SDLoc &DL, +- SelectionDAG &DAG) const { +- // Stores the assignment of the return value to a location. +- SmallVector RVLocs; ++MachineBasicBlock * ++LoongArchTargetLowering::emitXCOPY_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ unsigned Fd = MI.getOperand(0).getReg(); ++ unsigned Xk = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ DebugLoc DL = MI.getDebugLoc(); ++ ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR64RegClass); ++ if (Lane == 0) { ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd) ++ .addReg(Xk, 0, LoongArch::sub_64); ++ } else { ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_DU), Rj) ++ .addReg(Xk) ++ .addImm(Lane); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Fd).addReg(Rj); ++ } + +- // Info about the registers and stack slot. +- CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, +- *DAG.getContext()); ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} + +- analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); ++MachineBasicBlock *LoongArchTargetLowering::emitCONCAT_VECTORS( ++ MachineInstr &MI, MachineBasicBlock *BB, unsigned Bytes) const { + +- SDValue Glue; +- SmallVector RetOps(1, Chain); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned SubReg1 = MI.getOperand(1).getReg(); ++ unsigned SubReg2 = MI.getOperand(2).getReg(); ++ const TargetRegisterClass *RC = nullptr; + +- // Copy the result values into the output registers. +- for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { +- CCValAssign &VA = RVLocs[i]; +- assert(VA.isRegLoc() && "Can only return in registers!"); ++ switch (Bytes) { ++ default: ++ llvm_unreachable("Unexpected size"); ++ case 1: ++ RC = &LoongArch::LASX256BRegClass; ++ break; ++ case 2: ++ RC = &LoongArch::LASX256HRegClass; ++ break; ++ case 4: ++ RC = &LoongArch::LASX256WRegClass; ++ break; ++ case 8: ++ RC = &LoongArch::LASX256DRegClass; ++ break; ++ } + +- // Handle a 'normal' return. +- Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); ++ unsigned X0 = RegInfo.createVirtualRegister(RC); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), X0) ++ .addImm(0) ++ .addReg(SubReg1) ++ .addImm(LoongArch::sub_128); ++ unsigned X1 = RegInfo.createVirtualRegister(RC); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), X1) ++ .addImm(0) ++ .addReg(SubReg2) ++ .addImm(LoongArch::sub_128); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xd) ++ .addReg(X0) ++ .addReg(X1) ++ .addImm(2); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} + +- // Guarantee that all emitted copies are stuck together. +- Glue = Chain.getValue(1); +- RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); ++// xcopy_fw_gpr_pseudo $fd, $xs, $rk ++// => ++// bb: addi.d $rt1, zero, 4 ++// bge $lane, $rt1 hbb ++// lbb:xvreplve.w $xt1, $xs, $lane ++// copy $rf0, $xt1 ++// b sink ++// hbb: addi.d $rt2, $lane, -4 ++// xvpermi.q $xt2 $xs, 1 ++// xvreplve.w $xt3, $xt2, $rt2 ++// copy $rf1, $xt3 ++// sink:phi ++MachineBasicBlock * ++LoongArchTargetLowering::emitXCOPY_FW_GPR(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xs = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getReg(); ++ ++ const TargetRegisterClass *RC = &LoongArch::GPR64RegClass; ++ const BasicBlock *LLVM_BB = BB->getBasicBlock(); ++ MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); ++ MachineFunction *F = BB->getParent(); ++ MachineBasicBlock *HBB = F->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *LBB = F->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); ++ F->insert(It, LBB); ++ F->insert(It, HBB); ++ F->insert(It, Sink); ++ ++ Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), ++ BB->end()); ++ Sink->transferSuccessorsAndUpdatePHIs(BB); ++ ++ BB->addSuccessor(LBB); ++ BB->addSuccessor(HBB); ++ HBB->addSuccessor(Sink); ++ LBB->addSuccessor(Sink); ++ ++ unsigned Rt1 = RegInfo.createVirtualRegister(RC); ++ BuildMI(BB, DL, TII->get(LoongArch::ADDI_D), Rt1) ++ .addReg(LoongArch::ZERO_64) ++ .addImm(4); ++ BuildMI(BB, DL, TII->get(LoongArch::BGE)) ++ .addReg(Lane) ++ .addReg(Rt1) ++ .addMBB(HBB); ++ ++ unsigned Xt1 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ unsigned Rf0 = RegInfo.createVirtualRegister(&LoongArch::FGR32RegClass); ++ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::XVREPLVE_W_N), Xt1) ++ .addReg(Xs) ++ .addReg(Lane); ++ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::COPY), Rf0) ++ .addReg(Xt1, 0, LoongArch::sub_lo); ++ BuildMI(*LBB, LBB->end(), DL, TII->get(LoongArch::B)).addMBB(Sink); ++ ++ unsigned Xt2 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ unsigned Xt3 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ unsigned Rt2 = RegInfo.createVirtualRegister(RC); ++ unsigned Rf1 = RegInfo.createVirtualRegister(&LoongArch::FGR32RegClass); ++ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::ADDI_D), Rt2) ++ .addReg(Lane) ++ .addImm(-4); ++ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::XVPERMI_Q), Xt2) ++ .addReg(Xs) ++ .addReg(Xs) ++ .addImm(1); ++ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::XVREPLVE_W_N), Xt3) ++ .addReg(Xt2) ++ .addReg(Rt2); ++ BuildMI(*HBB, HBB->end(), DL, TII->get(LoongArch::COPY), Rf1) ++ .addReg(Xt3, 0, LoongArch::sub_lo); ++ ++ BuildMI(*Sink, Sink->begin(), DL, TII->get(LoongArch::PHI), ++ MI.getOperand(0).getReg()) ++ .addReg(Rf0) ++ .addMBB(LBB) ++ .addReg(Rf1) ++ .addMBB(HBB); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return Sink; ++} ++ ++MachineBasicBlock * ++LoongArchTargetLowering::emitXINSERT_BH(MachineInstr &MI, MachineBasicBlock *BB, ++ unsigned Size) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned Xd_in = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Fs = MI.getOperand(3).getReg(); ++ const TargetRegisterClass *VecRC = nullptr; ++ const TargetRegisterClass *SubVecRC = nullptr; ++ unsigned HalfSize = 0; ++ unsigned InsertOp = 0; ++ ++ if (Size == 1) { ++ VecRC = &LoongArch::LASX256BRegClass; ++ SubVecRC = &LoongArch::LSX128BRegClass; ++ HalfSize = 16; ++ InsertOp = LoongArch::VINSGR2VR_B; ++ } else if (Size == 2) { ++ VecRC = &LoongArch::LASX256HRegClass; ++ SubVecRC = &LoongArch::LSX128HRegClass; ++ HalfSize = 8; ++ InsertOp = LoongArch::VINSGR2VR_H; ++ } else { ++ llvm_unreachable("Unexpected type"); ++ } ++ ++ unsigned Xk = Xd_in; ++ unsigned Imm = Lane; ++ if (Lane >= HalfSize) { ++ Xk = RegInfo.createVirtualRegister(VecRC); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xk) ++ .addReg(Xd_in) ++ .addReg(Xd_in) ++ .addImm(1); ++ Imm = Lane - HalfSize; + } + +- RetOps[0] = Chain; // Update chain. ++ unsigned Xk128 = RegInfo.createVirtualRegister(SubVecRC); ++ unsigned Xd128 = RegInfo.createVirtualRegister(SubVecRC); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), Xk128) ++ .addReg(Xk, 0, LoongArch::sub_128); ++ BuildMI(*BB, MI, DL, TII->get(InsertOp), Xd128) ++ .addReg(Xk128) ++ .addReg(Fs) ++ .addImm(Imm); ++ ++ unsigned Xd256 = Xd; ++ if (Lane >= HalfSize) { ++ Xd256 = RegInfo.createVirtualRegister(VecRC); ++ } ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xd256) ++ .addImm(0) ++ .addReg(Xd128) ++ .addImm(LoongArch::sub_128); + +- // Add the glue node if we have it. +- if (Glue.getNode()) +- RetOps.push_back(Glue); ++ if (Lane >= HalfSize) { ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), Xd) ++ .addReg(Xd_in) ++ .addReg(Xd256) ++ .addImm(2); ++ } + +- return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; + } + +-bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, +- bool ForCodeSize) const { +- assert((VT == MVT::f32 || VT == MVT::f64) && "Unexpected VT"); ++MachineBasicBlock * ++LoongArchTargetLowering::emitXINSERT_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned Xd_in = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Fs = MI.getOperand(3).getReg(); ++ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) ++ .addImm(0) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_lo); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Rj) ++ .addReg(Xj) ++ .addImm(0); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVINSGR2VR_W), Xd) ++ .addReg(Xd_in) ++ .addReg(Rj) ++ .addImm(Lane); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the INSERT_FW pseudo instruction. ++// ++// insert_fw_pseudo $vd, $vd_in, $n, $fs ++// => ++// subreg_to_reg $vj:sub_lo, $fs ++// vpickve2gr.w rj, vj, 0 ++// vinsgr2vr.w, vd, rj, lane ++MachineBasicBlock * ++LoongArchTargetLowering::emitINSERT_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Vd = MI.getOperand(0).getReg(); ++ unsigned Vd_in = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Fs = MI.getOperand(3).getReg(); ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR32RegClass); ++ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Vj) ++ .addImm(0) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_lo); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VPICKVE2GR_W), Rj) ++ .addReg(Vj) ++ .addImm(0); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VINSGR2VR_W), Vd) ++ .addReg(Vd_in) ++ .addReg(Rj) ++ .addImm(Lane); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the INSERT_FD pseudo instruction. ++// insert_fd_pseudo $vd, $fs, n ++// => ++// subreg_to_reg $vk:sub_64, $fs ++// vpickve2gr.d rj, vk, 0 ++// vinsgr2vr.d vd, rj, lane ++MachineBasicBlock * ++LoongArchTargetLowering::emitINSERT_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Vd = MI.getOperand(0).getReg(); ++ unsigned Vd_in = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Fs = MI.getOperand(3).getReg(); ++ unsigned Vj = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); ++ unsigned Rj = RegInfo.createVirtualRegister(&LoongArch::GPR64RegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Vj) ++ .addImm(0) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_64); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VPICKVE2GR_D), Rj) ++ .addReg(Vj) ++ .addImm(0); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VINSGR2VR_D), Vd) ++ .addReg(Vd_in) ++ .addReg(Rj) ++ .addImm(Lane); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++MachineBasicBlock * ++LoongArchTargetLowering::emitXINSERT_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned Xd_in = MI.getOperand(1).getReg(); ++ unsigned Lane = MI.getOperand(2).getImm(); ++ unsigned Fs = MI.getOperand(3).getReg(); ++ unsigned Xj = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), Xj) ++ .addImm(0) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_64); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVINSVE0_D), Xd) ++ .addReg(Xd_in) ++ .addReg(Xj) ++ .addImm(Lane); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the FILL_FW pseudo instruction. ++// ++// fill_fw_pseudo $vd, $fs ++// => ++// implicit_def $vt1 ++// insert_subreg $vt2:subreg_lo, $vt1, $fs ++// vreplvei.w vd, vt2, 0 ++MachineBasicBlock * ++LoongArchTargetLowering::emitFILL_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Vd = MI.getOperand(0).getReg(); ++ unsigned Fs = MI.getOperand(1).getReg(); ++ unsigned Vj1 = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); ++ unsigned Vj2 = RegInfo.createVirtualRegister(&LoongArch::LSX128WRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Vj1); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Vj2) ++ .addReg(Vj1) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_lo); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_W), Vd) ++ .addReg(Vj2) ++ .addImm(0); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the FILL_FD pseudo instruction. ++// ++// fill_fd_pseudo $vd, $fs ++// => ++// implicit_def $vt1 ++// insert_subreg $vt2:subreg_64, $vt1, $fs ++// vreplvei.d vd, vt2, 0 ++MachineBasicBlock * ++LoongArchTargetLowering::emitFILL_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Vd = MI.getOperand(0).getReg(); ++ unsigned Fs = MI.getOperand(1).getReg(); ++ unsigned Vj1 = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); ++ unsigned Vj2 = RegInfo.createVirtualRegister(&LoongArch::LSX128DRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Vj1); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Vj2) ++ .addReg(Vj1) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_64); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::VREPLVEI_D), Vd) ++ .addReg(Vj2) ++ .addImm(0); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the XFILL_FW pseudo instruction. ++// ++// xfill_fw_pseudo $xd, $fs ++// => ++// implicit_def $xt1 ++// insert_subreg $xt2:subreg_lo, $xt1, $fs ++// xvreplve0.w xd, xt2, 0 ++MachineBasicBlock * ++LoongArchTargetLowering::emitXFILL_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned Fs = MI.getOperand(1).getReg(); ++ unsigned Xj1 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ unsigned Xj2 = RegInfo.createVirtualRegister(&LoongArch::LASX256WRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Xj1); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Xj2) ++ .addReg(Xj1) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_lo); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVREPLVE0_W), Xd).addReg(Xj2); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++// Emit the XFILL_FD pseudo instruction. ++// ++// xfill_fd_pseudo $xd, $fs ++// => ++// implicit_def $xt1 ++// insert_subreg $xt2:subreg_64, $xt1, $fs ++// xvreplve0.d xd, xt2, 0 ++MachineBasicBlock * ++LoongArchTargetLowering::emitXFILL_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const { ++ assert(Subtarget.isFP64bit()); ++ ++ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); ++ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); ++ DebugLoc DL = MI.getDebugLoc(); ++ unsigned Xd = MI.getOperand(0).getReg(); ++ unsigned Fs = MI.getOperand(1).getReg(); ++ unsigned Xj1 = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); ++ unsigned Xj2 = RegInfo.createVirtualRegister(&LoongArch::LASX256DRegClass); ++ ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::IMPLICIT_DEF), Xj1); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::INSERT_SUBREG), Xj2) ++ .addReg(Xj1) ++ .addReg(Fs) ++ .addImm(LoongArch::sub_64); ++ BuildMI(*BB, MI, DL, TII->get(LoongArch::XVREPLVE0_D), Xd).addReg(Xj2); ++ ++ MI.eraseFromParent(); // The pseudo instruction is gone now. ++ return BB; ++} ++ ++bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm) const { ++ bool IsLegal = false; ++ if (Subtarget.hasLSX() || Subtarget.hasLASX()) { ++ return isUInt<5>(Imm); ++ } ++ return IsLegal; ++} + +- if (VT == MVT::f32 && !Subtarget.hasBasicF()) ++bool LoongArchTargetLowering::isFMAFasterThanFMulAndFAdd( ++ const MachineFunction &MF, EVT VT) const { ++ ++ VT = VT.getScalarType(); ++ ++ if (!VT.isSimple()) + return false; +- if (VT == MVT::f64 && !Subtarget.hasBasicD()) ++ ++ switch (VT.getSimpleVT().SimpleTy) { ++ case MVT::f32: ++ case MVT::f64: ++ return true; ++ default: ++ break; ++ } ++ ++ return false; ++} ++ ++bool LoongArchTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, ++ unsigned Index) const { ++ if (!isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, ResVT)) + return false; +- return (Imm.isZero() || Imm.isExactlyValue(+1.0)); ++ ++ return ( ++ (ResVT != MVT::v16i8) && (ResVT != MVT::v8i16) && ++ (Index == 0 || (Index == ResVT.getVectorNumElements() && ++ (ResVT.getSizeInBits() == SrcVT.getSizeInBits() / 2)))); ++} ++ ++Register ++LoongArchTargetLowering::getRegisterByName(const char *RegName, LLT VT, ++ const MachineFunction &MF) const { ++ // Named registers is expected to be fairly rare. For now, just support $r2 ++ // and $r21 since the linux kernel uses them. ++ if (Subtarget.is64Bit()) { ++ Register Reg = StringSwitch(RegName) ++ .Case("$r2", LoongArch::TP_64) ++ .Case("$r21", LoongArch::T9_64) ++ .Default(Register()); ++ if (Reg) ++ return Reg; ++ } else { ++ Register Reg = StringSwitch(RegName) ++ .Case("$r2", LoongArch::TP) ++ .Case("$r21", LoongArch::T9) ++ .Default(Register()); ++ if (Reg) ++ return Reg; ++ } ++ report_fatal_error("Invalid register name global variable"); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +index 141f1fd3a..64e06b53f 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +@@ -1,4 +1,4 @@ +-//=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===// ++//===- LoongArchISelLowering.h - LoongArch DAG Lowering Interface ---------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,115 +6,553 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file defines the interfaces that LoongArch uses to lower LLVM code into +-// a selection DAG. ++// This file defines the interfaces that LoongArch uses to lower LLVM code into a ++// selection DAG. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H + ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" + #include "LoongArch.h" + #include "llvm/CodeGen/CallingConvLower.h" ++#include "llvm/CodeGen/ISDOpcodes.h" ++#include "llvm/CodeGen/MachineMemOperand.h" + #include "llvm/CodeGen/SelectionDAG.h" ++#include "llvm/CodeGen/SelectionDAGNodes.h" + #include "llvm/CodeGen/TargetLowering.h" ++#include "llvm/CodeGen/ValueTypes.h" ++#include "llvm/IR/CallingConv.h" ++#include "llvm/IR/InlineAsm.h" ++#include "llvm/IR/Type.h" ++#include "llvm/Support/MachineValueType.h" ++#include "llvm/Target/TargetMachine.h" ++#include ++#include ++#include ++#include ++#include ++#include + + namespace llvm { ++ ++class Argument; ++class CCState; ++class CCValAssign; ++class FastISel; ++class FunctionLoweringInfo; ++class MachineBasicBlock; ++class MachineFrameInfo; ++class MachineInstr; ++class LoongArchCCState; ++class LoongArchFunctionInfo; + class LoongArchSubtarget; +-struct LoongArchRegisterInfo; +-namespace LoongArchISD { +-enum NodeType : unsigned { +- FIRST_NUMBER = ISD::BUILTIN_OP_END, +- +- // TODO: add more LoongArchISDs +- CALL, +- RET, +- // 32-bit shifts, directly matching the semantics of the named LoongArch +- // instructions. +- SLL_W, +- SRA_W, +- SRL_W, +- +- // FPR<->GPR transfer operations +- MOVGR2FR_W_LA64, +- MOVFR2GR_S_LA64, +- +- FTINT, +- +- BSTRINS, +- BSTRPICK, +- +-}; +-} // end namespace LoongArchISD +- +-class LoongArchTargetLowering : public TargetLowering { +- const LoongArchSubtarget &Subtarget; +- +-public: +- explicit LoongArchTargetLowering(const TargetMachine &TM, +- const LoongArchSubtarget &STI); +- +- const LoongArchSubtarget &getSubtarget() const { return Subtarget; } +- +- // Provide custom lowering hooks for some operations. +- SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; +- void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, +- SelectionDAG &DAG) const override; +- +- SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; +- +- // This method returns the name of a target specific DAG node. +- const char *getTargetNodeName(unsigned Opcode) const override; +- +- // Lower incoming arguments, copy physregs into vregs. +- SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, +- bool IsVarArg, +- const SmallVectorImpl &Ins, +- const SDLoc &DL, SelectionDAG &DAG, +- SmallVectorImpl &InVals) const override; +- bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, +- bool IsVarArg, +- const SmallVectorImpl &Outs, +- LLVMContext &Context) const override; +- SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, +- const SmallVectorImpl &Outs, +- const SmallVectorImpl &OutVals, const SDLoc &DL, +- SelectionDAG &DAG) const override; +- SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, +- SmallVectorImpl &InVals) const override; +- +-private: +- /// Target-specific function used to lower LoongArch calling conventions. +- typedef bool LoongArchCCAssignFn(unsigned ValNo, MVT ValVT, +- CCValAssign::LocInfo LocInfo, +- CCState &State); +- +- void analyzeInputArgs(CCState &CCInfo, +- const SmallVectorImpl &Ins, +- LoongArchCCAssignFn Fn) const; +- void analyzeOutputArgs(CCState &CCInfo, +- const SmallVectorImpl &Outs, +- LoongArchCCAssignFn Fn) const; +- +- SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; +- SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; +- SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; +- +- MachineBasicBlock * +- EmitInstrWithCustomInserter(MachineInstr &MI, +- MachineBasicBlock *BB) const override; +- SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; +- SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; +- SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; +- SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; +- +- bool isFPImmLegal(const APFloat &Imm, EVT VT, +- bool ForCodeSize) const override; +- +- bool shouldInsertFencesForAtomic(const Instruction *I) const override { +- return isa(I) || isa(I); +- } +-}; ++class LoongArchTargetMachine; ++class SelectionDAG; ++class TargetLibraryInfo; ++class TargetRegisterClass; ++ ++ namespace LoongArchISD { ++ ++ enum NodeType : unsigned { ++ // Start the numbering from where ISD NodeType finishes. ++ FIRST_NUMBER = ISD::BUILTIN_OP_END, ++ ++ // Jump and link (call) ++ JmpLink, ++ ++ // Tail call ++ TailCall, ++ ++ // global address ++ GlobalAddress, ++ ++ // Floating Point Branch Conditional ++ FPBrcond, ++ ++ // Floating Point Compare ++ FPCmp, ++ ++ // Floating Point Conditional Moves ++ CMovFP_T, ++ CMovFP_F, ++ FSEL, ++ ++ // FP-to-int truncation node. ++ TruncIntFP, ++ ++ // Return ++ Ret, ++ ++ // error trap Return ++ ERet, ++ ++ // Software Exception Return. ++ EH_RETURN, ++ ++ DBAR, ++ ++ BSTRPICK, ++ BSTRINS, ++ ++ // Vector comparisons. ++ // These take a vector and return a boolean. ++ VALL_ZERO, ++ VANY_ZERO, ++ VALL_NONZERO, ++ VANY_NONZERO, ++ ++ // Vector Shuffle with mask as an operand ++ VSHF, // Generic shuffle ++ SHF, // 4-element set shuffle. ++ VPACKEV, // Interleave even elements ++ VPACKOD, // Interleave odd elements ++ VILVH, // Interleave left elements ++ VILVL, // Interleave right elements ++ VPICKEV, // Pack even elements ++ VPICKOD, // Pack odd elements ++ ++ // Vector Lane Copy ++ INSVE, // Copy element from one vector to another ++ ++ // Combined (XOR (OR $a, $b), -1) ++ VNOR, ++ ++ VROR, ++ VRORI, ++ XVPICKVE, ++ XVPERMI, ++ XVSHUF4I, ++ REVBD, ++ ++ // Extended vector element extraction ++ VEXTRACT_SEXT_ELT, ++ VEXTRACT_ZEXT_ELT, ++ ++ XVBROADCAST, ++ VBROADCAST, ++ VABSD, ++ UVABSD, ++ }; ++ ++ } // ene namespace LoongArchISD ++ ++ //===--------------------------------------------------------------------===// ++ // TargetLowering Implementation ++ //===--------------------------------------------------------------------===// ++ ++ class LoongArchTargetLowering : public TargetLowering { ++ public: ++ explicit LoongArchTargetLowering(const LoongArchTargetMachine &TM, ++ const LoongArchSubtarget &STI); ++ ++ bool allowsMisalignedMemoryAccesses( ++ EVT VT, unsigned AS = 0, Align Alignment = Align(1), ++ MachineMemOperand::Flags Flags = MachineMemOperand::MONone, ++ bool *Fast = nullptr) const override; ++ ++ /// Enable LSX support for the given integer type and Register ++ /// class. ++ void addLSXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); ++ ++ /// Enable LSX support for the given floating-point type and ++ /// Register class. ++ void addLSXFloatType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC); ++ ++ /// Enable LASX support for the given integer type and Register ++ /// class. ++ void addLASXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); ++ ++ /// Enable LASX support for the given floating-point type and ++ /// Register class. ++ void addLASXFloatType(MVT::SimpleValueType Ty, ++ const TargetRegisterClass *RC); ++ ++ MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { ++ return MVT::i32; ++ } ++ ++ EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, ++ ISD::NodeType) const override; ++ ++ bool isCheapToSpeculateCttz() const override; ++ bool isCheapToSpeculateCtlz() const override; ++ ++ bool isLegalAddImmediate(int64_t) const override; ++ ++ /// Return the correct alignment for the current calling convention. ++ Align getABIAlignmentForCallingConv(Type *ArgTy, ++ const DataLayout &DL) const override { ++ const Align ABIAlign = DL.getABITypeAlign(ArgTy); ++ if (ArgTy->isVectorTy()) ++ return std::min(ABIAlign, Align(8)); ++ return ABIAlign; ++ } ++ ++ ISD::NodeType getExtendForAtomicOps() const override { ++ return ISD::SIGN_EXTEND; ++ } ++ ++ bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, ++ unsigned Index) const override; ++ ++ void LowerOperationWrapper(SDNode *N, ++ SmallVectorImpl &Results, ++ SelectionDAG &DAG) const override; ++ ++ /// LowerOperation - Provide custom lowering hooks for some operations. ++ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; ++ ++ bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, ++ EVT VT) const override; ++ ++ /// ReplaceNodeResults - Replace the results of node with an illegal result ++ /// type with new values built out of custom code. ++ /// ++ void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, ++ SelectionDAG &DAG) const override; ++ ++ /// getTargetNodeName - This method returns the name of a target specific ++ // DAG node. ++ const char *getTargetNodeName(unsigned Opcode) const override; ++ ++ /// getSetCCResultType - get the ISD::SETCC result ValueType ++ EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, ++ EVT VT) const override; ++ ++ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; ++ ++ MachineBasicBlock * ++ EmitInstrWithCustomInserter(MachineInstr &MI, ++ MachineBasicBlock *MBB) const override; ++ ++ bool isShuffleMaskLegal(ArrayRef Mask, EVT VT) const override { ++ return false; ++ } ++ ++ const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; ++ ++ void AdjustInstrPostInstrSelection(MachineInstr &MI, ++ SDNode *Node) const override; ++ ++ void HandleByVal(CCState *, unsigned &, Align) const override; ++ ++ Register getRegisterByName(const char* RegName, LLT VT, ++ const MachineFunction &MF) const override; ++ ++ /// If a physical register, this returns the register that receives the ++ /// exception address on entry to an EH pad. ++ Register ++ getExceptionPointerRegister(const Constant *PersonalityFn) const override { ++ return ABI.IsLP64() ? LoongArch::A0_64 : LoongArch::A0; ++ } ++ ++ /// If a physical register, this returns the register that receives the ++ /// exception typeid on entry to a landing pad. ++ Register ++ getExceptionSelectorRegister(const Constant *PersonalityFn) const override { ++ return ABI.IsLP64() ? LoongArch::A1_64 : LoongArch::A1; ++ } ++ ++ bool isJumpTableRelative() const override { ++ return getTargetMachine().isPositionIndependent(); ++ } ++ ++ CCAssignFn *CCAssignFnForCall() const; ++ ++ CCAssignFn *CCAssignFnForReturn() const; ++ ++ private: ++ template ++ SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; ++ ++ /// This function fills Ops, which is the list of operands that will later ++ /// be used when a function call node is created. It also generates ++ /// copyToReg nodes to set up argument registers. ++ void getOpndList(SmallVectorImpl &Ops, ++ std::deque> &RegsToPass, ++ bool IsPICCall, bool GlobalOrExternal, bool IsCallReloc, ++ CallLoweringInfo &CLI, SDValue Callee, SDValue Chain, ++ bool IsTailCall) const; ++ ++ SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; ++ ++ // Subtarget Info ++ const LoongArchSubtarget &Subtarget; ++ // Cache the ABI from the TargetMachine, we use it everywhere. ++ const LoongArchABIInfo &ABI; ++ ++ // Create a TargetGlobalAddress node. ++ SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, ++ unsigned Flag) const; ++ ++ // Create a TargetExternalSymbol node. ++ SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, ++ unsigned Flag) const; ++ ++ // Create a TargetBlockAddress node. ++ SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, ++ unsigned Flag) const; ++ ++ // Create a TargetJumpTable node. ++ SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, ++ unsigned Flag) const; ++ ++ // Create a TargetConstantPool node. ++ SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, ++ unsigned Flag) const; ++ ++ // Lower Operand helpers ++ SDValue LowerCallResult(SDValue Chain, SDValue InFlag, ++ CallingConv::ID CallConv, bool isVarArg, ++ const SmallVectorImpl &Ins, ++ const SDLoc &dl, SelectionDAG &DAG, ++ SmallVectorImpl &InVals, ++ TargetLowering::CallLoweringInfo &CLI) const; ++ ++ // Lower Operand specifics ++ SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; ++ /// Lower VECTOR_SHUFFLE into one of a number of instructions ++ /// depending on the indices in the shuffle. ++ SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; ++ SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; ++ SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; ++ SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, ++ bool IsSRA) const; ++ SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; ++ ++ /// isEligibleForTailCallOptimization - Check whether the call is eligible ++ /// for tail call optimization. ++ bool ++ isEligibleForTailCallOptimization(const CCState &CCInfo, ++ CallLoweringInfo &CLI, MachineFunction &MF, ++ unsigned NextStackOffset, ++ const LoongArchFunctionInfo &FI) const; ++ ++ /// copyByValArg - Copy argument registers which were used to pass a byval ++ /// argument to the stack. Create a stack frame object for the byval ++ /// argument. ++ void copyByValRegs(SDValue Chain, const SDLoc &DL, ++ std::vector &OutChains, SelectionDAG &DAG, ++ const ISD::ArgFlagsTy &Flags, ++ SmallVectorImpl &InVals, ++ const Argument *FuncArg, unsigned FirstReg, ++ unsigned LastReg, const CCValAssign &VA, ++ LoongArchCCState &State) const; ++ ++ /// passByValArg - Pass a byval argument in registers or on stack. ++ void passByValArg(SDValue Chain, const SDLoc &DL, ++ std::deque> &RegsToPass, ++ SmallVectorImpl &MemOpChains, SDValue StackPtr, ++ MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, ++ unsigned FirstReg, unsigned LastReg, ++ const ISD::ArgFlagsTy &Flags, ++ const CCValAssign &VA) const; ++ ++ /// writeVarArgRegs - Write variable function arguments passed in registers ++ /// to the stack. Also create a stack frame object for the first variable ++ /// argument. ++ void writeVarArgRegs(std::vector &OutChains, SDValue Chain, ++ const SDLoc &DL, SelectionDAG &DAG, ++ CCState &State) const; ++ ++ SDValue ++ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, ++ const SmallVectorImpl &Ins, ++ const SDLoc &dl, SelectionDAG &DAG, ++ SmallVectorImpl &InVals) const override; ++ ++ SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, ++ SDValue Arg, const SDLoc &DL, bool IsTailCall, ++ SelectionDAG &DAG) const; ++ ++ SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, ++ SmallVectorImpl &InVals) const override; ++ ++ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, ++ bool isVarArg, ++ const SmallVectorImpl &Outs, ++ LLVMContext &Context) const override; ++ ++ SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, ++ const SmallVectorImpl &Outs, ++ const SmallVectorImpl &OutVals, ++ const SDLoc &dl, SelectionDAG &DAG) const override; ++ ++ bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override; ++ ++ // Inline asm support ++ ConstraintType getConstraintType(StringRef Constraint) const override; ++ ++ /// Examine constraint string and operand type and determine a weight value. ++ /// The operand object must already have been set up with the operand type. ++ ConstraintWeight getSingleConstraintMatchWeight( ++ AsmOperandInfo &info, const char *constraint) const override; ++ ++ /// This function parses registers that appear in inline-asm constraints. ++ /// It returns pair (0, 0) on failure. ++ std::pair ++ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; ++ ++ std::pair ++ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, ++ StringRef Constraint, MVT VT) const override; ++ ++ /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops ++ /// vector. If it is invalid, don't add anything to Ops. If hasMemory is ++ /// true it means one of the asm constraint of the inline asm instruction ++ /// being processed is 'm'. ++ void LowerAsmOperandForConstraint(SDValue Op, ++ std::string &Constraint, ++ std::vector &Ops, ++ SelectionDAG &DAG) const override; ++ ++ unsigned ++ getInlineAsmMemConstraint(StringRef ConstraintCode) const override { ++ if (ConstraintCode == "R") ++ return InlineAsm::Constraint_R; ++ else if (ConstraintCode == "ZC") ++ return InlineAsm::Constraint_ZC; ++ else if (ConstraintCode == "ZB") ++ return InlineAsm::Constraint_ZB; ++ return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); ++ } ++ ++ bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, ++ Type *Ty, unsigned AS, ++ Instruction *I = nullptr) const override; ++ ++ bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; ++ ++ EVT getOptimalMemOpType(const MemOp &Op, ++ const AttributeList &FuncAttributes) const override; ++ ++ /// isFPImmLegal - Returns true if the target can instruction select the ++ /// specified FP immediate natively. If false, the legalizer will ++ /// materialize the FP immediate as a load from a constant pool. ++ bool isFPImmLegal(const APFloat &Imm, EVT VT, ++ bool ForCodeSize) const override; ++ ++ bool useSoftFloat() const override; ++ ++ bool shouldInsertFencesForAtomic(const Instruction *I) const override { ++ return isa(I) || isa(I); ++ } ++ ++ bool mayBeEmittedAsTailCall(const CallInst *CI) const override; ++ ++ /// Emit a sign-extension using sll/sra, seb, or seh appropriately. ++ MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ unsigned Size, unsigned DstReg, ++ unsigned SrcRec) const; ++ ++ MachineBasicBlock *emitLoadAddress(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ unsigned Size) const; ++ ++ MachineBasicBlock *emitXINSERT_B(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ MachineBasicBlock *emitINSERT_H_VIDX(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ unsigned Size) const; ++ MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, ++ bool isFPCmp, unsigned Opc) const; ++ ++ /// SE ++ MachineBasicBlock *emitLSXCBranchPseudo(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ unsigned BranchOp) const; ++ /// Emit the COPY_FW pseudo instruction ++ MachineBasicBlock *emitCOPY_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ /// Emit the COPY_FD pseudo instruction ++ MachineBasicBlock *emitCOPY_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXCOPY_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXCOPY_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitCONCAT_VECTORS(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ unsigned Bytes) const; ++ ++ MachineBasicBlock *emitXCOPY_FW_GPR(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXINSERT_BH(MachineInstr &MI, MachineBasicBlock *BB, ++ unsigned EltSizeInBytes) const; ++ ++ MachineBasicBlock *emitXINSERT_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ /// Emit the INSERT_FW pseudo instruction ++ MachineBasicBlock *emitINSERT_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ /// Emit the INSERT_FD pseudo instruction ++ MachineBasicBlock *emitINSERT_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXINSERT_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXINSERT_DF_VIDX(MachineInstr &MI, ++ MachineBasicBlock *BB, ++ bool IsGPR64) const; ++ /// Emit the FILL_FW pseudo instruction ++ MachineBasicBlock *emitFILL_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ /// Emit the FILL_FD pseudo instruction ++ MachineBasicBlock *emitFILL_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ ++ MachineBasicBlock *emitXFILL_FW(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ MachineBasicBlock *emitXFILL_FD(MachineInstr &MI, ++ MachineBasicBlock *BB) const; ++ }; + + } // end namespace llvm + +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td +index bebc83a86..d75d5198b 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td +@@ -1,4 +1,4 @@ +-//===- LoongArchInstrFormats.td - LoongArch Instr. Formats -*- tablegen -*-===// ++//===-- LoongArchInstrFormats.td - LoongArch Instruction Formats -----*- tablegen -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -9,396 +9,782 @@ + //===----------------------------------------------------------------------===// + // Describe LoongArch instructions format + // +-// opcode - operation code. +-// rd - destination register operand. +-// r{j/k} - source register operand. +-// immN - immediate data operand. ++// CPU INSTRUCTION FORMATS ++// ++// opcode - operation code. ++// rs - src reg. ++// rt - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr). ++// rd - dst reg, only used on 3 regs instr. ++// shamt - only used on shift instructions, contains the shift amount. ++// funct - combined with opcode field give us an operation code. + // + //===----------------------------------------------------------------------===// + +-class LAInst pattern = []> +- : Instruction { ++class StdArch { ++ ++ bits<32> Inst; ++} ++ ++// Format specifies the encoding used by the instruction. This is part of the ++// ad-hoc solution used to emit machine instruction encodings by our machine ++// code emitter. ++class Format val> { ++ bits<4> Value = val; ++} ++ ++def Pseudo : Format<0>; ++def FrmR : Format<1>; ++def FrmI : Format<2>; ++def FrmJ : Format<3>; ++def FrmFR : Format<4>; ++def FrmFI : Format<5>; ++def FrmOther : Format<6>; ++ ++// Generic LoongArch Format ++class InstLA pattern, Format f> ++ : Instruction ++{ + field bits<32> Inst; +- // SoftFail is a field the disassembler can use to provide a way for +- // instructions to not match without killing the whole decode process. It is +- // mainly used for ARM, but Tablegen expects this field to exist or it fails +- // to build the decode table. +- field bits<32> SoftFail = 0; ++ Format Form = f; + + let Namespace = "LoongArch"; ++ + let Size = 4; ++ + let OutOperandList = outs; +- let InOperandList = ins; +- let AsmString = opcstr # "\t" # opnstr; +- let Pattern = pattern; ++ let InOperandList = ins; ++ let AsmString = asmstr; ++ let Pattern = pattern; ++ ++ // ++ // Attributes specific to LoongArch instructions... ++ // ++ bits<4> FormBits = Form.Value; ++ bit isCTI = 0; // Any form of Control Transfer Instruction. ++ // Required for LoongArch ++ bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. ++ bit IsPCRelativeLoad = 0; // Load instruction with implicit source register ++ // ($pc) and with explicit offset and destination ++ // register ++ bit hasFCCRegOperand = 0; // Instruction uses $fcc register ++ ++ // TSFlags layout should be kept in sync with MCTargetDesc/LoongArchBaseInfo.h. ++ let TSFlags{3-0} = FormBits; ++ let TSFlags{4} = isCTI; ++ let TSFlags{5} = hasForbiddenSlot; ++ let TSFlags{6} = IsPCRelativeLoad; ++ let TSFlags{7} = hasFCCRegOperand; ++ ++ let DecoderNamespace = "LoongArch"; ++ ++ field bits<32> SoftFail = 0; + } + +-// Pseudo instructions +-class Pseudo pattern = [], string opcstr = "", +- string opnstr = ""> +- : LAInst { +- let isPseudo = 1; +- let isCodeGenOnly = 1; ++class InstForm pattern, ++ Format f, string opstr = ""> : ++ InstLA { ++ string BaseOpcode = opstr; ++ string Arch; ++} ++ ++class LoongArch_str { ++ string Arch; ++ string BaseOpcode = opstr; ++} ++ ++//===-----------------------------------------------------------===// ++// Format instruction classes in the LoongArch ++//===-----------------------------------------------------------===// ++ ++// R2 classes: 2 registers ++// ++class R2 : StdArch { ++ bits<5> rj; ++ bits<5> rd; ++ ++ let Inst{9-5} = rj; ++ let Inst{4-0} = rd; ++} ++ ++class R2I op> ++ : R2 { ++ let Inst{31-15} = 0x0; ++ let Inst{14-10} = op; ++} ++ ++class R2F op> ++ : R2 { ++ bits<5> fj; ++ bits<5> fd; ++ ++ let Inst{31-20} = 0x11; ++ let Inst{19-10} = op; ++ let Inst{9-5} = fj; ++ let Inst{4-0} = fd; ++} ++ ++class MOVFI op> ++ : R2 { ++ bits<5> rj; ++ bits<5> fd; ++ ++ let Inst{31-20} = 0x11; ++ let Inst{19-10} = op; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = fd; ++} ++ ++class MOVIF op> ++ : R2 { ++ bits<5> fj; ++ bits<5> rd; ++ ++ let Inst{31-20} = 0x11; ++ let Inst{19-10} = op; ++ let Inst{9-5} = fj; ++ let Inst{4-0} = rd; ++} ++ ++class R2P op> ++ : R2 { ++ let Inst{31-13} = 0x3240; ++ let Inst{12-10} = op; ++} ++ ++class R2_CSR op> ++ : StdArch { ++ bits<5> rj; ++ bits<5> rd; ++ bits<14> csr; ++ ++ let Inst{31-24} = op; ++ let Inst{23-10} = csr; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = rd; + } + +-// 2R-type +-// +-class Fmt2R op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { ++class R2_SI16 op> ++ : StdArch { ++ bits<5> rd; ++ bits<5> rj; ++ bits<16> si16; ++ ++ let Inst{31-26} = op; ++ let Inst{25-10} = si16; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = rd; ++} ++ ++class R2_COND op, bits<5> cond> ++ : StdArch { ++ bits<5> fj; ++ bits<5> fk; ++ bits<3> cd; ++ ++ let Inst{31-22} = 0x30; ++ let Inst{21-20} = op; ++ let Inst{19-15} = cond; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-3} = 0b00; ++ let Inst{2-0} = cd; ++} ++ ++class R2_LEVEL op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<8> level; + +- let Inst{31-10} = op; ++ let Inst{31-18} = op; ++ let Inst{17-10} = level; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 3R-type +-// +-class Fmt3R op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { ++class IMM32 op> ++ : StdArch { ++ let Inst{31-16} = 0x0648; ++ let Inst{15-10} = op; ++ let Inst{9-0} = 0; ++} ++ ++class WAIT_FM : StdArch { ++ bits<15> hint; ++ ++ let Inst{31-15} = 0xc91; ++ let Inst{14-0} = hint; ++} ++ ++class R2_INVTLB : StdArch { ++ bits<5> rj; ++ bits<5> op; ++ bits<5> rk; ++ ++ let Inst{31-15} = 0xc93; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = op; ++} ++ ++class BAR_FM op> ++ : StdArch { ++ bits<15> hint; ++ ++ let Inst{31-16} = 0x3872; ++ let Inst{15} = op; ++ let Inst{14-0} = hint; ++} ++ ++class PRELD_FM : StdArch { ++ bits<5> rj; ++ bits<5> hint; ++ bits<12> imm12; ++ ++ let Inst{31-22} = 0xab; ++ let Inst{21-10} = imm12; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = hint; ++} ++ ++// R3 classes: 3 registers ++// ++class R3 : StdArch { + bits<5> rk; + bits<5> rj; + bits<5> rd; + +- let Inst{31-15} = op; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 3RI2-type +-// +-class Fmt3RI2 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<2> imm2; ++class R3I op> ++ : R3 { ++ let Inst{31-22} = 0x0; ++ let Inst{21-15} = op; ++} ++ ++class R3F op> ++ : R3 { ++ bits<5> fk; ++ bits<5> fj; ++ bits<5> fd; ++ ++ let Inst{31-21} = 0x8; ++ let Inst{20-15} = op; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-0} = fd; ++} ++ ++class R3MI op> ++ : R3 { ++ let Inst{31-23} = 0x70; ++ let Inst{22-15} = op; ++} ++ ++class AM op> : StdArch { ++ bits<5> rk; ++ bits<17> addr; // rj + 12 bits offset 0 ++ bits<5> rd; ++ ++ let Inst{31-21} = 0x1c3; ++ let Inst{20-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = rd; ++} ++ ++class R3MF op> ++ : R3 { ++ bits<5> fd; ++ ++ let Inst{31-23} = 0x70; ++ let Inst{22-15} = op; ++ let Inst{4-0} = fd; ++} ++ ++class R3_SA2 op> ++ : StdArch { + bits<5> rk; + bits<5> rj; + bits<5> rd; ++ bits<2> sa; + +- let Inst{31-17} = op; +- let Inst{16-15} = imm2; ++ let Inst{31-22} = 0x0; ++ let Inst{21-17} = op; ++ let Inst{16-15} = sa; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 3RI3-type +-// +-class Fmt3RI3 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<3> imm3; ++class R3_SA3 : StdArch { + bits<5> rk; + bits<5> rj; + bits<5> rd; ++ bits<3> sa; + +- let Inst{31-18} = op; +- let Inst{17-15} = imm3; ++ let Inst{31-18} = 3; ++ let Inst{17-15} = sa; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI5-type +-// +-class Fmt2RI5 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> imm5; ++// R4 classes: 4 registers ++// ++class R4MUL op> ++ : StdArch { ++ bits<5> fa; ++ bits<5> fk; ++ bits<5> fj; ++ bits<5> fd; ++ ++ let Inst{31-24} = 0x8; ++ let Inst{23-20} = op; ++ let Inst{19-15} = fa; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-0} = fd; ++} ++ ++class R4CMP op> ++ : StdArch { ++ bits<5> cond; ++ bits<5> fk; ++ bits<5> fj; ++ bits<3> cd; ++ ++ let Inst{31-22} = 0x30; ++ let Inst{21-20} = op; ++ let Inst{19-15} = cond; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-3} = 0; ++ let Inst{2-0} = cd; ++} ++ ++class R4SEL : StdArch { ++ bits<3> ca; ++ bits<5> fk; ++ bits<5> fj; ++ bits<5> fd; ++ ++ let Inst{31-18} = 0x340; ++ let Inst{17-15} = ca; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-0} = fd; ++} ++ ++// R2_IMM5 classes: 2registers and 1 5bit-immediate ++// ++class R2_IMM5 op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<5> imm5; + +- let Inst{31-15} = op; ++ let Inst{31-20} = 0x4; ++ let Inst{19-18} = op; ++ let Inst{17-15} = 0x1; + let Inst{14-10} = imm5; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI6-type +-// +-class Fmt2RI6 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<6> imm6; ++// R2_IMM6 classes: 2registers and 1 6bit-immediate ++// ++class R2_IMM6 op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<6> imm6; + +- let Inst{31-16} = op; ++ let Inst{31-20} = 0x4; ++ let Inst{19-18} = op; ++ let Inst{17-16} = 0x1; + let Inst{15-10} = imm6; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI8-type +-// +-class Fmt2RI8 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<8> imm8; ++// R2_IMM12 classes: 2 registers and 1 12bit-immediate ++// ++class LOAD_STORE op> ++ : StdArch { ++ bits<5> rd; ++ bits<17> addr; ++ ++ let Inst{31-26} = 0xa; ++ let Inst{25-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = rd; ++} ++// for reloc ++class LOAD_STORE_RRI op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<12> imm12; + +- let Inst{31-18} = op; +- let Inst{17-10} = imm8; ++ let Inst{31-26} = 0xa; ++ let Inst{25-22} = op; ++ let Inst{21-10} = imm12; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI12-type +-// +-class Fmt2RI12 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<12> imm12; ++ ++class R2_IMM12 op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<12> imm12; + +- let Inst{31-22} = op; ++ let Inst{31-25} = 0x1; ++ let Inst{24-22} = op; + let Inst{21-10} = imm12; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI14-type +-// +-class Fmt2RI14 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<14> imm14; ++class LEA_ADDI_FM op> ++ : StdArch { ++ bits<5> rd; ++ bits<17> addr; ++ ++ let Inst{31-25} = 0x1; ++ let Inst{24-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = rd; ++} ++ ++// R2_IMM14 classes: 2 registers and 1 14bit-immediate ++// ++class LL_SC op> ++ : StdArch { ++ bits<5> rd; ++ bits<19> addr; ++ ++ let Inst{31-27} = 4; ++ let Inst{26-24} = op; ++ let Inst{23-10} = addr{13-0}; ++ let Inst{9-5} = addr{18-14}; ++ let Inst{4-0} = rd; ++} ++ ++// R2_IMM16 classes: 2 registers and 1 16bit-immediate ++// ++class R2_IMM16BEQ op> ++ : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<16> offs16; + +- let Inst{31-24} = op; +- let Inst{23-10} = imm14; ++ let Inst{31-26} = op; ++ let Inst{25-10} = offs16; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// 2RI16-type +-// +-class Fmt2RI16 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<16> imm16; ++class R2_IMM16JIRL : StdArch { + bits<5> rj; + bits<5> rd; ++ bits<16> offs16; ++ ++ let Inst{31-26} = 0x13; ++ let Inst{25-10} = offs16; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = rd; ++} ++ ++// R1_IMM21 classes: 1 registers and 1 21bit-immediate ++// ++class R1_IMM21BEQZ op> ++ : StdArch { ++ bits<5> rj; ++ bits<21> offs21; + + let Inst{31-26} = op; +- let Inst{25-10} = imm16; ++ let Inst{25-10} = offs21{15-0}; + let Inst{9-5} = rj; ++ let Inst{4-0} = offs21{20-16}; ++} ++ ++class R1_CSR op> ++ : StdArch { ++ bits<5> rd; ++ bits<14> csr; ++ ++ let Inst{31-24} = op{7-0}; ++ let Inst{23-10} = csr; ++ let Inst{9-5} = op{12-8}; + let Inst{4-0} = rd; + } + +-// 1RI20-type +-// +-class Fmt1RI20 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<20> imm20; ++class R1_SI20 op> ++ : StdArch { + bits<5> rd; ++ bits<20> si20; + + let Inst{31-25} = op; +- let Inst{24-5} = imm20; ++ let Inst{24-5} = si20; + let Inst{4-0} = rd; + } + +-// 1RI21-type +-// +-class Fmt1RI21 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<21> imm21; ++class R1_CACHE : StdArch { + bits<5> rj; ++ bits<5> op; ++ bits<12> si12; + +- let Inst{31-26} = op; +- let Inst{25-10} = imm21{15-0}; ++ let Inst{31-22} = 0x18; ++ let Inst{21-10} = si12; + let Inst{9-5} = rj; +- let Inst{4-0} = imm21{20-16}; ++ let Inst{4-0} = op; ++} ++ ++class R1_SEQ op> ++ : StdArch { ++ bits<5> rj; ++ bits<5> offset; ++ bits<8> seq; ++ ++ let Inst{31-18} = op; ++ let Inst{17-10} = seq; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = 0b00000; + } + +-// I15-type +-// +-class FmtI15 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<15> imm15; ++class R1_BCEQZ op> ++ : StdArch { ++ bits<21> offset; ++ bits<3> cj; + +- let Inst{31-15} = op; +- let Inst{14-0} = imm15; ++ let Inst{31-26} = 0x12; ++ let Inst{25-10} = offset{15-0}; ++ let Inst{9-8} = op; ++ let Inst{7-5} = cj; ++ let Inst{4-0} = offset{20-16}; + } + +-// I26-type +-// +-class FmtI26 op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<26> imm26; ++// IMM26 classes: 1 26bit-immediate ++// ++class IMM26B op> ++ : StdArch { ++ bits<26> offs26; + + let Inst{31-26} = op; +- let Inst{25-10} = imm26{15-0}; +- let Inst{9-0} = imm26{25-16}; ++ let Inst{25-10} = offs26{15-0}; ++ let Inst{9-0} = offs26{25-16}; ++} ++ ++// LoongArch Pseudo Instructions Format ++class LoongArchPseudo pattern> : ++ InstLA { ++ let isCodeGenOnly = 1; ++ let isPseudo = 1; ++} ++ ++// Pseudo-instructions for alternate assembly syntax (never used by codegen). ++// These are aliases that require C++ handling to convert to the target ++// instruction, while InstAliases can be handled directly by tblgen. ++class LoongArchAsmPseudoInst: ++ InstLA { ++ let isPseudo = 1; ++ let Pattern = []; + } + +-// FmtBSTR_W +-// +-class FmtBSTR_W op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { ++// ++// Misc instruction classes ++class ASSERT op> ++ : StdArch { ++ bits<5> rk; ++ bits<5> rj; ++ ++ let Inst{31-17} = 0x0; ++ let Inst{16-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = 0x0; ++} ++ ++class CODE15 op> ++ : StdArch { ++ bits<15> Code; ++ ++ let Inst{31-22} = 0x0; ++ let Inst{21-15} = op; ++ let Inst{14-0} = Code; ++} ++ ++class INSERT_BIT32 op> ++ : StdArch { + bits<5> msbw; + bits<5> lsbw; + bits<5> rj; + bits<5> rd; + +- let Inst{31-21} = op{11-1}; ++ let Inst{31-21} = 0x3; + let Inst{20-16} = msbw; +- let Inst{15} = op{0}; ++ let Inst{15} = op; + let Inst{14-10} = lsbw; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// FmtBSTR_D +-// +-class FmtBSTR_D op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { ++class INSERT_BIT64 op> ++ : StdArch { + bits<6> msbd; + bits<6> lsbd; + bits<5> rj; + bits<5> rd; + +- let Inst{31-22} = op; ++ let Inst{31-23} = 0x1; ++ let Inst{22} = op; + let Inst{21-16} = msbd; + let Inst{15-10} = lsbd; + let Inst{9-5} = rj; + let Inst{4-0} = rd; + } + +-// FmtASRT +-// +-class FmtASRT op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<5> rk; ++class MOVGPR2FCSR: StdArch { ++ bits<5> fcsr; + bits<5> rj; + +- let Inst{31-15} = op; +- let Inst{14-10} = rk; ++ let Inst{31-10} = 0x4530; + let Inst{9-5} = rj; +- let Inst{4-0} = 0x0; ++ let Inst{4-0} = fcsr; + } + +-// FmtPRELD +-// < 0b0010101011 | I12 | rj | I5> +-class FmtPRELD pattern = []> +- : LAInst { +- bits<12> imm12; +- bits<5> rj; +- bits<5> imm5; ++class MOVFCSR2GPR: StdArch { ++ bits<5> fcsr; ++ bits<5> rd; + +- let Inst{31-22} = 0b0010101011; +- let Inst{21-10} = imm12; +- let Inst{9-5} = rj; +- let Inst{4-0} = imm5; ++ let Inst{31-10} = 0x4532; ++ let Inst{9-5} = fcsr; ++ let Inst{4-0} = rd; + } + +-// FmtPRELDX +-// < 0b00111000001011000 | rk | rj | I5> +-class FmtPRELDX pattern = []> +- : LAInst { +- bits<5> rk; ++class MOVFGR2FCFR: StdArch { ++ bits<3> cd; ++ bits<5> fj; ++ ++ let Inst{31-10} = 0x4534; ++ let Inst{9-5} = fj; ++ let Inst{4-3} = 0; ++ let Inst{2-0} = cd; ++} ++ ++class MOVFCFR2FGR: StdArch { ++ bits<3> cj; ++ bits<5> fd; ++ ++ let Inst{31-10} = 0x4535; ++ let Inst{9-8} = 0; ++ let Inst{7-5} = cj; ++ let Inst{4-0} = fd; ++} ++ ++class MOVGPR2FCFR: StdArch { ++ bits<3> cd; + bits<5> rj; +- bits<5> imm5; + +- let Inst{31-15} = 0b00111000001011000; +- let Inst{14-10} = rk; ++ let Inst{31-10} = 0x4536; + let Inst{9-5} = rj; +- let Inst{4-0} = imm5; ++ let Inst{4-3} = 0; ++ let Inst{2-0} = cd; + } + +-// FmtCSR +-// +-class FmtCSR op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<14> csr_num; ++class MOVFCFR2GPR: StdArch { ++ bits<3> cj; + bits<5> rd; + +- let Inst{31-24} = op{12-5}; +- let Inst{23-10} = csr_num; +- let Inst{9-5} = op{4-0}; ++ let Inst{31-10} = 0x4537; ++ let Inst{9-8} = 0; ++ let Inst{7-5} = cj; + let Inst{4-0} = rd; + } + +-// FmtCSRXCHG +-// +-class FmtCSRXCHG op, dag outs, dag ins, string opcstr, string opnstr, +- list pattern = []> +- : LAInst { +- bits<14> csr_num; +- bits<5> rj; +- bits<5> rd; ++class LoongArchInst : InstLA<(outs), (ins), "", [], FrmOther> { ++} ++class JMP_OFFS_2R op> : LoongArchInst { ++ bits<5> rs; ++ bits<5> rd; ++ bits<16> offset; + +- let Inst{31-24} = op; +- let Inst{23-10} = csr_num; +- let Inst{9-5} = rj; +- let Inst{4-0} = rd; ++ bits<32> Inst; ++ ++ let Inst{31-26} = op; ++ let Inst{25-10} = offset; ++ let Inst{9-5} = rs; ++ let Inst{4-0} = rd; + } + +-// FmtCACOP +-// <0b0000011000 | I12 | rj | I5> +-class FmtCACOP pattern = []> +- : LAInst { +- bits<12> imm12; +- bits<5> rj; +- bits<5> op; ++class FJ op> : StdArch ++{ ++ bits<26> target; + +- let Inst{31-22} = 0b0000011000; +- let Inst{21-10} = imm12; +- let Inst{9-5} = rj; +- let Inst{4-0} = op; ++ let Inst{31-26} = op; ++ let Inst{25-10} = target{15-0}; ++ let Inst{9-0} = target{25-16}; + } + +-// FmtIMM32 +-// +-class FmtI32 op, string opstr, list pattern = []> +- : LAInst<(outs), (ins), opstr, "", pattern> { +- let Inst{31-0} = op; ++class LUI_FM : StdArch { ++ bits<5> rt; ++ bits<16> imm16; ++ ++ let Inst{31-26} = 0xf; ++ let Inst{25-21} = 0; ++ let Inst{20-16} = rt; ++ let Inst{15-0} = imm16; + } + +-// FmtINVTLB +-// <0b00000110010010011 | rk | rj | I5> +-class FmtINVTLB pattern = []> +- : LAInst { +- bits<5> rk; ++class R2_IMM12M_STD op> : StdArch { + bits<5> rj; +- bits<5> op; ++ bits<5> rd; ++ bits<12> imm12; + +- let Inst{31-15} = 0b00000110010010011; +- let Inst{14-10} = rk; ++ let Inst{31-26} = 0xa; ++ let Inst{25-22} = op; ++ let Inst{21-10} = imm12; + let Inst{9-5} = rj; +- let Inst{4-0} = op; ++ let Inst{4-0} = rd; + } + +-// FmtLDPTE +-// <0b00000110010001 | seq | rj | 00000> +-class FmtLDPTE pattern = []> +- : LAInst { +- bits<8> seq; +- bits<5> rj; ++class LLD_2R Code> : LoongArchInst { ++ bits<5> rd; ++ bits<19> addr; ++ bits<5> rj = addr{18-14}; ++ bits<14> offset = addr{13-0}; + +- let Inst{31-18} = 0b00000110010001; +- let Inst{17-10} = seq; ++ bits<32> Inst; ++ ++ let Inst{31-27} = 0x4; ++ let Inst{26-24} = Code; ++ let Inst{23-10} = offset; + let Inst{9-5} = rj; +- let Inst{4-0} = 0b00000; ++ let Inst{4-0} = rd; + } ++ ++class CEQS_FM op> { ++ bits<5> fj; ++ bits<5> fk; ++ bits<3> cd; ++ bits<5> cond; ++ ++ bits<32> Inst; ++ ++ let Inst{31-22} = 0x30; ++ let Inst{21-20} = op; ++ let Inst{19-15} = cond; ++ let Inst{14-10} = fk; ++ let Inst{9-5} = fj; ++ let Inst{4-3} = 0b00; ++ let Inst{2-0} = cd; ++} ++ +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +index bcbd4b28f..00abd9167 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +@@ -1,4 +1,4 @@ +-//=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- C++ -*-===// ++//===- LoongArchInstrInfo.cpp - LoongArch Instruction Information -------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,105 +11,1030 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchInstrInfo.h" +-#include "LoongArch.h" +-#include "LoongArchMachineFunctionInfo.h" ++#include "LoongArchSubtarget.h" ++#include "MCTargetDesc/LoongArchAnalyzeImmediate.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/ADT/SmallVector.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" ++#include "llvm/CodeGen/MachineFrameInfo.h" ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/CodeGen/RegisterScavenging.h" ++#include "llvm/CodeGen/TargetOpcodes.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++#include "llvm/IR/DebugLoc.h" ++#include "llvm/MC/MCInstrDesc.h" ++#include "llvm/Target/TargetMachine.h" ++#include + + using namespace llvm; + + #define GET_INSTRINFO_CTOR_DTOR + #include "LoongArchGenInstrInfo.inc" + +-LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI) ++// Pin the vtable to this file. ++void LoongArchInstrInfo::anchor() {} ++LoongArchInstrInfo::LoongArchInstrInfo(const LoongArchSubtarget &STI) + : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN, +- LoongArch::ADJCALLSTACKUP) {} ++ LoongArch::ADJCALLSTACKUP), ++ RI(), Subtarget(STI) {} ++ ++const LoongArchRegisterInfo &LoongArchInstrInfo::getRegisterInfo() const { ++ return RI; ++} ++ ++/// isLoadFromStackSlot - If the specified machine instruction is a direct ++/// load from a stack slot, return the virtual or physical register number of ++/// the destination along with the FrameIndex of the loaded stack slot. If ++/// not, return 0. This predicate must return 0 if the instruction has ++/// any side effects other than loading from the stack slot. ++unsigned LoongArchInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, ++ int &FrameIndex) const { ++ unsigned Opc = MI.getOpcode(); ++ if ((Opc == LoongArch::LD_W) || (Opc == LoongArch::LD_D) || ++ (Opc == LoongArch::FLD_S) || (Opc == LoongArch::FLD_D)) { ++ if ((MI.getOperand(1).isFI()) && // is a stack slot ++ (MI.getOperand(2).isImm()) && // the imm is zero ++ (isZeroImm(MI.getOperand(2)))) { ++ FrameIndex = MI.getOperand(1).getIndex(); ++ return MI.getOperand(0).getReg(); ++ } ++ } ++ return 0; ++} ++ ++/// isStoreToStackSlot - If the specified machine instruction is a direct ++/// store to a stack slot, return the virtual or physical register number of ++/// the source reg along with the FrameIndex of the loaded stack slot. If ++/// not, return 0. This predicate must return 0 if the instruction has ++/// any side effects other than storing to the stack slot. ++unsigned LoongArchInstrInfo::isStoreToStackSlot(const MachineInstr &MI, ++ int &FrameIndex) const { ++ unsigned Opc = MI.getOpcode(); ++ if ((Opc == LoongArch::ST_D) || (Opc == LoongArch::ST_W) || ++ (Opc == LoongArch::FST_S) ||(Opc == LoongArch::FST_D)) { ++ if ((MI.getOperand(1).isFI()) && // is a stack slot ++ (MI.getOperand(2).isImm()) && // the imm is zero ++ (isZeroImm(MI.getOperand(2)))) { ++ FrameIndex = MI.getOperand(1).getIndex(); ++ return MI.getOperand(0).getReg(); ++ } ++ } ++ return 0; ++} + + void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator MBBI, +- const DebugLoc &DL, MCRegister DstReg, ++ MachineBasicBlock::iterator I, ++ const DebugLoc &DL, MCRegister DestReg, + MCRegister SrcReg, bool KillSrc) const { +- if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) { +- BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg) +- .addReg(SrcReg, getKillRegState(KillSrc)) +- .addReg(LoongArch::R0); +- return; ++ unsigned Opc = 0, ZeroReg = 0; ++ unsigned ZeroImm = 1; ++ if (LoongArch::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg. ++ if (LoongArch::GPR32RegClass.contains(SrcReg)) { ++ Opc = LoongArch::OR32, ZeroReg = LoongArch::ZERO; ++ } ++ else if (LoongArch::FGR32RegClass.contains(SrcReg)) ++ Opc = LoongArch::MOVFR2GR_S; ++ else if (LoongArch::FCFRRegClass.contains(SrcReg)) ++ Opc = LoongArch::MOVCF2GR; + } +- +- // FPR->FPR copies. +- unsigned Opc; +- if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) { ++ else if (LoongArch::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg. ++ if (LoongArch::FGR32RegClass.contains(DestReg)) ++ Opc = LoongArch::MOVGR2FR_W; ++ else if (LoongArch::FCFRRegClass.contains(DestReg)) ++ Opc = LoongArch::MOVGR2CF; ++ } ++ else if (LoongArch::FGR32RegClass.contains(DestReg, SrcReg)) + Opc = LoongArch::FMOV_S; +- } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) { ++ else if (LoongArch::FGR64RegClass.contains(DestReg, SrcReg)) + Opc = LoongArch::FMOV_D; +- } else { +- // TODO: support other copies. +- llvm_unreachable("Impossible reg-to-reg copy"); ++ else if (LoongArch::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg. ++ if (LoongArch::GPR64RegClass.contains(SrcReg)) ++ Opc = LoongArch::OR, ZeroReg = LoongArch::ZERO_64; ++ else if (LoongArch::FGR64RegClass.contains(SrcReg)) ++ Opc = LoongArch::MOVFR2GR_D; ++ else if (LoongArch::FCFRRegClass.contains(SrcReg)) ++ Opc = LoongArch::MOVCF2GR; ++ } ++ else if (LoongArch::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg. ++ if (LoongArch::FGR64RegClass.contains(DestReg)) ++ Opc = LoongArch::MOVGR2FR_D; ++ else if (LoongArch::FCFRRegClass.contains(DestReg)) ++ Opc = LoongArch::MOVGR2CF; + } ++ else if (LoongArch::FGR32RegClass.contains(DestReg)) // Copy to FGR32 Reg ++ Opc = LoongArch::MOVCF2FR; ++ else if (LoongArch::FGR32RegClass.contains(SrcReg)) // Copy from FGR32 Reg ++ Opc = LoongArch::MOVFR2CF; ++ else if (LoongArch::FGR64RegClass.contains(DestReg)) // Copy to FGR64 Reg ++ Opc = LoongArch::MOVCF2FR; ++ else if (LoongArch::FGR64RegClass.contains(SrcReg)) // Copy from FGR64 Reg ++ Opc = LoongArch::MOVFR2CF; ++ else if (LoongArch::LSX128BRegClass.contains(DestReg)) { // Copy to LSX reg ++ if (LoongArch::LSX128BRegClass.contains(SrcReg)) ++ Opc = LoongArch::VORI_B, ZeroImm = 0; ++ } else if (LoongArch::LASX256BRegClass.contains( ++ DestReg)) { // Copy to LASX reg ++ if (LoongArch::LASX256BRegClass.contains(SrcReg)) ++ Opc = LoongArch::XVORI_B, ZeroImm = 0; ++ } ++ ++ assert(Opc && "Cannot copy registers"); ++ ++ MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); ++ ++ if (DestReg) ++ MIB.addReg(DestReg, RegState::Define); ++ ++ if (SrcReg) ++ MIB.addReg(SrcReg, getKillRegState(KillSrc)); ++ ++ if (ZeroReg) ++ MIB.addReg(ZeroReg); + +- BuildMI(MBB, MBBI, DL, get(Opc), DstReg) +- .addReg(SrcReg, getKillRegState(KillSrc)); ++ if (!ZeroImm) ++ MIB.addImm(0); ++} ++ ++static bool isORCopyInst(const MachineInstr &MI) { ++ switch (MI.getOpcode()) { ++ default: ++ break; ++ case LoongArch::OR: ++ if (MI.getOperand(2).getReg() == LoongArch::ZERO_64) ++ return true; ++ break; ++ case LoongArch::OR32: ++ if (MI.getOperand(2).getReg() == LoongArch::ZERO) ++ return true; ++ break; ++ } ++ return false; ++} ++ ++/// We check for the common case of 'or', as it's LoongArch' preferred instruction ++/// for GPRs but we have to check the operands to ensure that is the case. ++/// Other move instructions for LoongArch are directly identifiable. ++Optional ++LoongArchInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const { ++ if (MI.isMoveReg() || isORCopyInst(MI)) { ++ return DestSourcePair{MI.getOperand(0), MI.getOperand(1)}; ++ } ++ return None; + } + +-void LoongArchInstrInfo::storeRegToStackSlot( +- MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg, +- bool IsKill, int FI, const TargetRegisterClass *RC, +- const TargetRegisterInfo *TRI) const { ++void LoongArchInstrInfo:: ++storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, ++ Register SrcReg, bool isKill, int FI, ++ const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, ++ int64_t Offset) const { + DebugLoc DL; +- if (I != MBB.end()) +- DL = I->getDebugLoc(); +- MachineFunction *MF = MBB.getParent(); +- MachineFrameInfo &MFI = MF->getFrameInfo(); +- +- unsigned Opcode; +- if (LoongArch::GPRRegClass.hasSubClassEq(RC)) +- Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 +- ? LoongArch::ST_W +- : LoongArch::ST_D; +- else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) +- Opcode = LoongArch::FST_S; +- else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) +- Opcode = LoongArch::FST_D; +- else +- llvm_unreachable("Can't store this register to stack slot"); ++ MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); + +- MachineMemOperand *MMO = MF->getMachineMemOperand( +- MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, +- MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); ++ unsigned Opc = 0; ++ if (LoongArch::GPR32RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::ST_W; ++ else if (LoongArch::GPR64RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::ST_D; ++ else if (LoongArch::FGR64RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::FST_D; ++ else if (LoongArch::FGR32RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::FST_S; + +- BuildMI(MBB, I, DL, get(Opcode)) +- .addReg(SrcReg, getKillRegState(IsKill)) ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) ++ Opc = LoongArch::VST; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16)) ++ Opc = LoongArch::VST_H; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || ++ TRI->isTypeLegalForClass(*RC, MVT::v4f32)) ++ Opc = LoongArch::VST_W; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || ++ TRI->isTypeLegalForClass(*RC, MVT::v2f64)) ++ Opc = LoongArch::VST_D; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v32i8)) ++ Opc = LoongArch::XVST; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i16)) ++ Opc = LoongArch::XVST_H; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i32) || ++ TRI->isTypeLegalForClass(*RC, MVT::v8f32)) ++ Opc = LoongArch::XVST_W; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i64) || ++ TRI->isTypeLegalForClass(*RC, MVT::v4f64)) ++ Opc = LoongArch::XVST_D; ++ ++ assert(Opc && "Register class not handled!"); ++ BuildMI(MBB, I, DL, get(Opc)) ++ .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI) +- .addImm(0) ++ .addImm(Offset) + .addMemOperand(MMO); + } + +-void LoongArchInstrInfo::loadRegFromStackSlot( +- MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DstReg, +- int FI, const TargetRegisterClass *RC, +- const TargetRegisterInfo *TRI) const { ++void LoongArchInstrInfo:: ++loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, ++ Register DestReg, int FI, const TargetRegisterClass *RC, ++ const TargetRegisterInfo *TRI, int64_t Offset) const { + DebugLoc DL; + if (I != MBB.end()) + DL = I->getDebugLoc(); +- MachineFunction *MF = MBB.getParent(); +- MachineFrameInfo &MFI = MF->getFrameInfo(); +- +- unsigned Opcode; +- if (LoongArch::GPRRegClass.hasSubClassEq(RC)) +- Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 +- ? LoongArch::LD_W +- : LoongArch::LD_D; +- else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) +- Opcode = LoongArch::FLD_S; +- else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) +- Opcode = LoongArch::FLD_D; +- else +- llvm_unreachable("Can't load this register from stack slot"); ++ MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); ++ unsigned Opc = 0; + +- MachineMemOperand *MMO = MF->getMachineMemOperand( +- MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, +- MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); ++ if (LoongArch::GPR32RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::LD_W; ++ else if (LoongArch::GPR64RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::LD_D; ++ else if (LoongArch::FGR32RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::FLD_S; ++ else if (LoongArch::FGR64RegClass.hasSubClassEq(RC)) ++ Opc = LoongArch::FLD_D; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) ++ Opc = LoongArch::VLD; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16)) ++ Opc = LoongArch::VLD_H; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || ++ TRI->isTypeLegalForClass(*RC, MVT::v4f32)) ++ Opc = LoongArch::VLD_W; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || ++ TRI->isTypeLegalForClass(*RC, MVT::v2f64)) ++ Opc = LoongArch::VLD_D; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v32i8)) ++ Opc = LoongArch::XVLD; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i16)) ++ Opc = LoongArch::XVLD_H; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i32) || ++ TRI->isTypeLegalForClass(*RC, MVT::v8f32)) ++ Opc = LoongArch::XVLD_W; ++ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i64) || ++ TRI->isTypeLegalForClass(*RC, MVT::v4f64)) ++ Opc = LoongArch::XVLD_D; + +- BuildMI(MBB, I, DL, get(Opcode), DstReg) ++ assert(Opc && "Register class not handled!"); ++ ++ BuildMI(MBB, I, DL, get(Opc), DestReg) + .addFrameIndex(FI) +- .addImm(0) ++ .addImm(Offset) + .addMemOperand(MMO); + } ++ ++bool LoongArchInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { ++ MachineBasicBlock &MBB = *MI.getParent(); ++ switch (MI.getDesc().getOpcode()) { ++ default: ++ return false; ++ case LoongArch::RetRA: ++ expandRetRA(MBB, MI); ++ break; ++ case LoongArch::ERet: ++ expandERet(MBB, MI); ++ break; ++ case LoongArch::PseudoFFINT_S_W: ++ expandCvtFPInt(MBB, MI, LoongArch::FFINT_S_W, LoongArch::MOVGR2FR_W, false); ++ break; ++ case LoongArch::PseudoFFINT_S_L: ++ expandCvtFPInt(MBB, MI, LoongArch::FFINT_S_L, LoongArch::MOVGR2FR_D, true); ++ break; ++ case LoongArch::PseudoFFINT_D_W: ++ expandCvtFPInt(MBB, MI, LoongArch::FFINT_D_W, LoongArch::MOVGR2FR_W, true); ++ break; ++ case LoongArch::PseudoFFINT_D_L: ++ expandCvtFPInt(MBB, MI, LoongArch::FFINT_D_L, LoongArch::MOVGR2FR_D, true); ++ break; ++ case LoongArch::LoongArcheh_return32: ++ case LoongArch::LoongArcheh_return64: ++ expandEhReturn(MBB, MI); ++ break; ++ } ++ ++ MBB.erase(MI); ++ return true; ++} ++ ++/// getOppositeBranchOpc - Return the inverse of the specified ++/// opcode, e.g. turning BEQ to BNE. ++unsigned LoongArchInstrInfo::getOppositeBranchOpc(unsigned Opc) const { ++ switch (Opc) { ++ default: llvm_unreachable("Illegal opcode!"); ++ case LoongArch::BEQ32: return LoongArch::BNE32; ++ case LoongArch::BEQ: return LoongArch::BNE; ++ case LoongArch::BNE32: return LoongArch::BEQ32; ++ case LoongArch::BNE: return LoongArch::BEQ; ++ case LoongArch::BEQZ32: return LoongArch::BNEZ32; ++ case LoongArch::BEQZ: return LoongArch::BNEZ; ++ case LoongArch::BNEZ32: return LoongArch::BEQZ32; ++ case LoongArch::BNEZ: return LoongArch::BEQZ; ++ case LoongArch::BCEQZ: return LoongArch::BCNEZ; ++ case LoongArch::BCNEZ: return LoongArch::BCEQZ; ++ case LoongArch::BLT32: return LoongArch::BGE32; ++ case LoongArch::BLT: return LoongArch::BGE; ++ case LoongArch::BGE32: return LoongArch::BLT32; ++ case LoongArch::BGE: return LoongArch::BLT; ++ case LoongArch::BLTU32: return LoongArch::BGEU32; ++ case LoongArch::BLTU: return LoongArch::BGEU; ++ case LoongArch::BGEU32: return LoongArch::BLTU32; ++ case LoongArch::BGEU: return LoongArch::BLTU; ++ } ++} ++ ++void LoongArchInstrInfo::adjustReg(unsigned DestReg, unsigned SrcReg, ++ int64_t Amount, MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I, ++ MachineInstr::MIFlag Flag) const { ++ LoongArchABIInfo ABI = Subtarget.getABI(); ++ DebugLoc DL; ++ unsigned ADDI = ABI.GetPtrAddiOp(); ++ ++ if (Amount == 0) ++ return; ++ ++ if (isInt<12>(Amount)) { ++ // addi $DestReg, $SrcReg, amount ++ BuildMI(MBB, I, DL, get(ADDI), DestReg) ++ .addReg(SrcReg) ++ .addImm(Amount) ++ .setMIFlag(Flag); ++ } else { ++ // For numbers which are not 12bit integers we synthesize Amount inline ++ // then add or subtract it from $SrcReg. ++ unsigned Opc = ABI.GetPtrAddOp(); ++ if (Amount < 0) { ++ Opc = ABI.GetPtrSubOp(); ++ Amount = -Amount; ++ } ++ unsigned Reg = loadImmediate(Amount, MBB, I, DL); ++ BuildMI(MBB, I, DL, get(Opc), DestReg) ++ .addReg(SrcReg) ++ .addReg(Reg, RegState::Kill) ++ .setMIFlag(Flag); ++ } ++} ++ ++/// This function generates the sequence of instructions needed to get the ++/// result of adding register REG and immediate IMM. ++unsigned LoongArchInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator II, ++ const DebugLoc &DL) const { ++ const TargetRegisterClass *RC = Subtarget.isABI_LP64() ++ ? &LoongArch::GPR64RegClass ++ : &LoongArch::GPR32RegClass; ++ LoongArchAnalyzeImmediate::InstSeq Seq = ++ LoongArchAnalyzeImmediate::generateInstSeq(Imm, Subtarget.is64Bit()); ++ unsigned DstReg = MBB.getParent()->getRegInfo().createVirtualRegister(RC); ++ unsigned SrcReg = ++ Subtarget.isABI_LP64() ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ // Build the instructions in Seq. ++ for (auto &Inst : Seq) { ++ if (Inst.Opc == LoongArch::LU12I_W || Inst.Opc == LoongArch::LU12I_W32) ++ BuildMI(MBB, II, DL, get(Inst.Opc), DstReg).addImm(Inst.Imm); ++ else ++ BuildMI(MBB, II, DL, get(Inst.Opc), DstReg) ++ .addReg(SrcReg, RegState::Kill) ++ .addImm(Inst.Imm); ++ SrcReg = DstReg; ++ } ++ return DstReg; ++} ++ ++unsigned LoongArchInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { ++ return (Opc == LoongArch::B || Opc == LoongArch::B32 || ++ Opc == LoongArch::BEQZ || Opc == LoongArch::BEQZ32 || ++ Opc == LoongArch::BNEZ || Opc == LoongArch::BNEZ32 || ++ Opc == LoongArch::BCEQZ || ++ Opc == LoongArch::BCNEZ || ++ Opc == LoongArch::BEQ || Opc == LoongArch::BEQ32 || ++ Opc == LoongArch::BNE || Opc == LoongArch::BNE32 || ++ Opc == LoongArch::BLT || Opc == LoongArch::BLT32 || ++ Opc == LoongArch::BGE || Opc == LoongArch::BGE32 || ++ Opc == LoongArch::BLTU || Opc == LoongArch::BLTU32 || ++ Opc == LoongArch::BGEU || Opc == LoongArch::BGEU32) ? Opc : 0; ++} ++ ++void LoongArchInstrInfo::expandRetRA(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const { ++ ++ MachineInstrBuilder MIB; ++ ++ if (Subtarget.is64Bit()) ++ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::PseudoReturn64)) ++ .addReg(LoongArch::RA_64, RegState::Undef); ++ else ++ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::PseudoReturn)) ++ .addReg(LoongArch::RA, RegState::Undef); ++ ++ // Retain any imp-use flags. ++ for (auto & MO : I->operands()) { ++ if (MO.isImplicit()) ++ MIB.add(MO); ++ } ++} ++ ++void LoongArchInstrInfo::expandERet(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const { ++ BuildMI(MBB, I, I->getDebugLoc(), get(LoongArch::ERTN)); ++} ++ ++std::pair ++LoongArchInstrInfo::compareOpndSize(unsigned Opc, ++ const MachineFunction &MF) const { ++ const MCInstrDesc &Desc = get(Opc); ++ assert(Desc.NumOperands == 2 && "Unary instruction expected."); ++ const LoongArchRegisterInfo *RI = &getRegisterInfo(); ++ unsigned DstRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 0, RI, MF)); ++ unsigned SrcRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 1, RI, MF)); ++ ++ return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize); ++} ++ ++void LoongArchInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I, ++ unsigned CvtOpc, unsigned MovOpc, ++ bool IsI64) const { ++ const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc); ++ const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1); ++ unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg; ++ unsigned KillSrc = getKillRegState(Src.isKill()); ++ DebugLoc DL = I->getDebugLoc(); ++ bool DstIsLarger, SrcIsLarger; ++ ++ std::tie(DstIsLarger, SrcIsLarger) = ++ compareOpndSize(CvtOpc, *MBB.getParent()); ++ ++ if (DstIsLarger) ++ TmpReg = getRegisterInfo().getSubReg(DstReg, LoongArch::sub_lo); ++ ++ if (SrcIsLarger) ++ DstReg = getRegisterInfo().getSubReg(DstReg, LoongArch::sub_lo); ++ ++ BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc); ++ BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill); ++} ++ ++void LoongArchInstrInfo::expandEhReturn(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const { ++ // This pseudo instruction is generated as part of the lowering of ++ // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and ++ // indirect jump to TargetReg ++ LoongArchABIInfo ABI = Subtarget.getABI(); ++ unsigned ADD = ABI.GetPtrAddOp(); ++ unsigned SP = Subtarget.is64Bit() ? LoongArch::SP_64 : LoongArch::SP; ++ unsigned RA = Subtarget.is64Bit() ? LoongArch::RA_64 : LoongArch::RA; ++ unsigned T8 = Subtarget.is64Bit() ? LoongArch::T8_64 : LoongArch::T8; ++ unsigned ZERO = Subtarget.is64Bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ unsigned OffsetReg = I->getOperand(0).getReg(); ++ unsigned TargetReg = I->getOperand(1).getReg(); ++ ++ // add $ra, $v0, $zero ++ // add $sp, $sp, $v1 ++ // jr $ra (via RetRA) ++ const TargetMachine &TM = MBB.getParent()->getTarget(); ++ if (TM.isPositionIndependent()) ++ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), T8) ++ .addReg(TargetReg) ++ .addReg(ZERO); ++ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), RA) ++ .addReg(TargetReg) ++ .addReg(ZERO); ++ BuildMI(MBB, I, I->getDebugLoc(), get(ADD), SP).addReg(SP).addReg(OffsetReg); ++ expandRetRA(MBB, I); ++} ++ ++ ++bool LoongArchInstrInfo::isZeroImm(const MachineOperand &op) const { ++ return op.isImm() && op.getImm() == 0; ++} ++ ++/// insertNoop - If data hazard condition is found insert the target nop ++/// instruction. ++// FIXME: This appears to be dead code. ++void LoongArchInstrInfo:: ++insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const ++{ ++ DebugLoc DL; ++ BuildMI(MBB, MI, DL, get(LoongArch::NOP)); ++} ++ ++MachineMemOperand * ++LoongArchInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, ++ MachineMemOperand::Flags Flags) const { ++ MachineFunction &MF = *MBB.getParent(); ++ MachineFrameInfo &MFI = MF.getFrameInfo(); ++ ++ return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), ++ Flags, MFI.getObjectSize(FI), ++ MFI.getObjectAlign(FI)); ++} ++ ++//===----------------------------------------------------------------------===// ++// Branch Analysis ++//===----------------------------------------------------------------------===// ++ ++void LoongArchInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, ++ MachineBasicBlock *&BB, ++ SmallVectorImpl &Cond) const { ++ assert(getAnalyzableBrOpc(Opc) && "Not an analyzable branch"); ++ int NumOp = Inst->getNumExplicitOperands(); ++ ++ // for both int and fp branches, the last explicit operand is the ++ // MBB. ++ BB = Inst->getOperand(NumOp-1).getMBB(); ++ Cond.push_back(MachineOperand::CreateImm(Opc)); ++ ++ for (int i = 0; i < NumOp-1; i++) ++ Cond.push_back(Inst->getOperand(i)); ++} ++ ++bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB, ++ MachineBasicBlock *&TBB, ++ MachineBasicBlock *&FBB, ++ SmallVectorImpl &Cond, ++ bool AllowModify) const { ++ SmallVector BranchInstrs; ++ BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); ++ ++ return (BT == BT_None) || (BT == BT_Indirect); ++} ++ ++MachineInstr * ++LoongArchInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, ++ const DebugLoc &DL, ++ ArrayRef Cond) const { ++ unsigned Opc = Cond[0].getImm(); ++ const MCInstrDesc &MCID = get(Opc); ++ MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); ++ ++ for (unsigned i = 1; i < Cond.size(); ++i) { ++ assert((Cond[i].isImm() || Cond[i].isReg()) && ++ "Cannot copy operand for conditional branch!"); ++ MIB.add(Cond[i]); ++ } ++ MIB.addMBB(TBB); ++ return MIB.getInstr(); ++} ++ ++unsigned LoongArchInstrInfo::insertBranch(MachineBasicBlock &MBB, ++ MachineBasicBlock *TBB, ++ MachineBasicBlock *FBB, ++ ArrayRef Cond, ++ const DebugLoc &DL, ++ int *BytesAdded) const { ++ unsigned UncondBrOpc = LoongArch::B; ++ // Shouldn't be a fall through. ++ assert(TBB && "insertBranch must not be told to insert a fallthrough"); ++ if (BytesAdded) ++ *BytesAdded = 0; ++ ++ // # of condition operands: ++ // Unconditional branches: 0 ++ // Floating point branches: 1 (opc) ++ // Int BranchZero: 2 (opc, reg) ++ // Int Branch: 3 (opc, reg0, reg1) ++ assert((Cond.size() <= 3) && ++ "# of LoongArch branch conditions must be <= 3!"); ++ ++ // Two-way Conditional branch. ++ if (FBB) { ++ MachineInstr &MI1 = *BuildCondBr(MBB, TBB, DL, Cond); ++ if (BytesAdded) ++ *BytesAdded += getInstSizeInBytes(MI1); ++ MachineInstr &MI2 = *BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB); ++ if (BytesAdded) ++ *BytesAdded += getInstSizeInBytes(MI2); ++ return 2; ++ } ++ ++ // One way branch. ++ // Unconditional branch. ++ if (Cond.empty()) { ++ MachineInstr &MI = *BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB); ++ if (BytesAdded) ++ *BytesAdded += getInstSizeInBytes(MI); ++ } ++ else {// Conditional branch. ++ MachineInstr &MI = *BuildCondBr(MBB, TBB, DL, Cond); ++ if (BytesAdded) ++ *BytesAdded += getInstSizeInBytes(MI); ++ } ++ return 1; ++} ++ ++void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, ++ MachineBasicBlock &DestBB, ++ MachineBasicBlock &RestoreBB, ++ const DebugLoc &DL, ++ int64_t BrOffset, ++ RegScavenger *RS) const { ++ assert(RS && "RegScavenger required for long branching"); ++ assert(MBB.empty() && ++ "new block should be inserted for expanding unconditional branch"); ++ assert(MBB.pred_size() == 1); ++ ++ MachineFunction *MF = MBB.getParent(); ++ MachineRegisterInfo &MRI = MF->getRegInfo(); ++ const LoongArchSubtarget &Subtarget = MF->getSubtarget(); ++ bool is64 = Subtarget.isABI_LP64(); ++ const TargetRegisterClass *RC = ++ is64 ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ ++ if (!is64 && !isInt<32>(BrOffset)) ++ report_fatal_error( ++ "Branch offsets outside of the signed 32-bit range not supported"); ++ ++ unsigned ScratchReg = MRI.createVirtualRegister(RC); ++ unsigned ZeroReg = is64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ auto II = MBB.end(); ++ ++ MachineInstr &Pcaddu12iMI = ++ *BuildMI(MBB, II, DL, get(LoongArch::LONG_BRANCH_PCADDU12I), ScratchReg) ++ .addMBB(&DestBB, LoongArchII::MO_PCREL_HI); ++ BuildMI(MBB, II, DL, get(LoongArch::LONG_BRANCH_ADDID2Op), ScratchReg) ++ .addReg(ScratchReg) ++ .addMBB(&DestBB, LoongArchII::MO_PCREL_LO); ++ BuildMI(MBB, II, DL, get(LoongArch::JIRL)) ++ .addReg(ZeroReg) ++ .addReg(ScratchReg, RegState::Kill) ++ .addImm(0); ++ RS->enterBasicBlockEnd(MBB); ++ unsigned Scav = RS->scavengeRegisterBackwards( ++ *RC, MachineBasicBlock::iterator(Pcaddu12iMI), false, 0); ++ MRI.replaceRegWith(ScratchReg, Scav); ++ MRI.clearVirtRegs(); ++ RS->setRegUsed(Scav); ++} ++ ++unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, ++ int *BytesRemoved) const { ++ if (BytesRemoved) ++ *BytesRemoved = 0; ++ ++ MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); ++ unsigned removed = 0; ++ ++ // Up to 2 branches are removed. ++ // Note that indirect branches are not removed. ++ while (I != REnd && removed < 2) { ++ // Skip past debug instructions. ++ if (I->isDebugInstr()) { ++ ++I; ++ continue; ++ } ++ if (!getAnalyzableBrOpc(I->getOpcode())) ++ break; ++ // Remove the branch. ++ I->eraseFromParent(); ++ if (BytesRemoved) ++ *BytesRemoved += getInstSizeInBytes(*I); ++ I = MBB.rbegin(); ++ ++removed; ++ } ++ ++ return removed; ++} ++ ++/// reverseBranchCondition - Return the inverse opcode of the ++/// specified Branch instruction. ++bool LoongArchInstrInfo::reverseBranchCondition( ++ SmallVectorImpl &Cond) const { ++ assert( (Cond.size() && Cond.size() <= 3) && ++ "Invalid LoongArch branch condition!"); ++ Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); ++ return false; ++} ++ ++LoongArchInstrInfo::BranchType LoongArchInstrInfo::analyzeBranch( ++ MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, ++ SmallVectorImpl &Cond, bool AllowModify, ++ SmallVectorImpl &BranchInstrs) const { ++ MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); ++ ++ // Skip all the debug instructions. ++ while (I != REnd && I->isDebugInstr()) ++ ++I; ++ ++ if (I == REnd || !isUnpredicatedTerminator(*I)) { ++ // This block ends with no branches (it just falls through to its succ). ++ // Leave TBB/FBB null. ++ TBB = FBB = nullptr; ++ return BT_NoBranch; ++ } ++ ++ MachineInstr *LastInst = &*I; ++ unsigned LastOpc = LastInst->getOpcode(); ++ BranchInstrs.push_back(LastInst); ++ ++ // Not an analyzable branch (e.g., indirect jump). ++ if (!getAnalyzableBrOpc(LastOpc)) ++ return LastInst->isIndirectBranch() ? BT_Indirect : BT_None; ++ ++ // Get the second to last instruction in the block. ++ unsigned SecondLastOpc = 0; ++ MachineInstr *SecondLastInst = nullptr; ++ ++ // Skip past any debug instruction to see if the second last actual ++ // is a branch. ++ ++I; ++ while (I != REnd && I->isDebugInstr()) ++ ++I; ++ ++ if (I != REnd) { ++ SecondLastInst = &*I; ++ SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); ++ ++ // Not an analyzable branch (must be an indirect jump). ++ if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) ++ return BT_None; ++ } ++ ++ // If there is only one terminator instruction, process it. ++ if (!SecondLastOpc) { ++ // Unconditional branch. ++ if (LastInst->isUnconditionalBranch()) { ++ TBB = LastInst->getOperand(0).getMBB(); ++ return BT_Uncond; ++ } ++ ++ // Conditional branch ++ AnalyzeCondBr(LastInst, LastOpc, TBB, Cond); ++ return BT_Cond; ++ } ++ ++ // If we reached here, there are two branches. ++ // If there are three terminators, we don't know what sort of block this is. ++ if (++I != REnd && isUnpredicatedTerminator(*I)) ++ return BT_None; ++ ++ BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); ++ ++ // If second to last instruction is an unconditional branch, ++ // analyze it and remove the last instruction. ++ if (SecondLastInst->isUnconditionalBranch()) { ++ // Return if the last instruction cannot be removed. ++ if (!AllowModify) ++ return BT_None; ++ ++ TBB = SecondLastInst->getOperand(0).getMBB(); ++ LastInst->eraseFromParent(); ++ BranchInstrs.pop_back(); ++ return BT_Uncond; ++ } ++ ++ // Conditional branch followed by an unconditional branch. ++ // The last one must be unconditional. ++ if (!LastInst->isUnconditionalBranch()) ++ return BT_None; ++ ++ AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); ++ FBB = LastInst->getOperand(0).getMBB(); ++ ++ return BT_CondUncond; ++} ++ ++MachineBasicBlock * ++LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { ++ assert(MI.getDesc().isBranch() && "Unexpected opcode!"); ++ // The branch target is always the last operand. ++ int NumOp = MI.getNumExplicitOperands(); ++ return MI.getOperand(NumOp - 1).getMBB(); ++} ++ ++bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const { ++/* ++ switch (BranchOpc) { ++ case LoongArch::B: ++ case LoongArch::BAL: ++ case LoongArch::BAL_BR: ++ case LoongArch::BC1F: ++ case LoongArch::BC1FL: ++ case LoongArch::BC1T: ++ case LoongArch::BC1TL: ++ case LoongArch::BEQ: case LoongArch::BEQ64: ++ case LoongArch::BEQL: ++ case LoongArch::BGEZ: case LoongArch::BGEZ64: ++ case LoongArch::BGEZL: ++ case LoongArch::BGEZAL: ++ case LoongArch::BGEZALL: ++ case LoongArch::BGTZ: case LoongArch::BGTZ64: ++ case LoongArch::BGTZL: ++ case LoongArch::BLEZ: case LoongArch::BLEZ64: ++ case LoongArch::BLEZL: ++ case LoongArch::BLTZ: case LoongArch::BLTZ64: ++ case LoongArch::BLTZL: ++ case LoongArch::BLTZAL: ++ case LoongArch::BLTZALL: ++ case LoongArch::BNE: case LoongArch::BNE64: ++ case LoongArch::BNEL: ++ return isInt<18>(BrOffset); ++ ++ case LoongArch::BC1EQZ: ++ case LoongArch::BC1NEZ: ++ case LoongArch::BC2EQZ: ++ case LoongArch::BC2NEZ: ++ case LoongArch::BEQC: case LoongArch::BEQC64: ++ case LoongArch::BNEC: case LoongArch::BNEC64: ++ case LoongArch::BGEC: case LoongArch::BGEC64: ++ case LoongArch::BGEUC: case LoongArch::BGEUC64: ++ case LoongArch::BGEZC: case LoongArch::BGEZC64: ++ case LoongArch::BGTZC: case LoongArch::BGTZC64: ++ case LoongArch::BLEZC: case LoongArch::BLEZC64: ++ case LoongArch::BLTC: case LoongArch::BLTC64: ++ case LoongArch::BLTUC: case LoongArch::BLTUC64: ++ case LoongArch::BLTZC: case LoongArch::BLTZC64: ++ case LoongArch::BNVC: ++ case LoongArch::BOVC: ++ case LoongArch::BGEZALC: ++ case LoongArch::BEQZALC: ++ case LoongArch::BGTZALC: ++ case LoongArch::BLEZALC: ++ case LoongArch::BLTZALC: ++ case LoongArch::BNEZALC: ++ return isInt<18>(BrOffset); ++ ++ case LoongArch::BEQZC: case LoongArch::BEQZC64: ++ case LoongArch::BNEZC: case LoongArch::BNEZC64: ++ return isInt<23>(BrOffset); ++ } ++ */ ++ switch (BranchOpc) { ++ case LoongArch::B: case LoongArch::B32: ++ return isInt<28>(BrOffset); ++ ++ case LoongArch::BEQZ: case LoongArch::BEQZ32: ++ case LoongArch::BNEZ: case LoongArch::BNEZ32: ++ case LoongArch::BCEQZ: ++ case LoongArch::BCNEZ: ++ return isInt<23>(BrOffset); ++ ++ case LoongArch::BEQ: case LoongArch::BEQ32: ++ case LoongArch::BNE: case LoongArch::BNE32: ++ case LoongArch::BLT: case LoongArch::BLT32: ++ case LoongArch::BGE: case LoongArch::BGE32: ++ case LoongArch::BLTU: case LoongArch::BLTU32: ++ case LoongArch::BGEU: case LoongArch::BGEU32: ++ return isInt<18>(BrOffset); ++ } ++ ++ llvm_unreachable("Unknown branch instruction!"); ++} ++ ++ ++/// Predicate for distingushing between control transfer instructions and all ++/// other instructions for handling forbidden slots. Consider inline assembly ++/// as unsafe as well. ++bool LoongArchInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { ++ if (MI.isInlineAsm()) ++ return false; ++ ++ return (MI.getDesc().TSFlags & LoongArchII::IsCTI) == 0; ++} ++ ++/// Predicate for distingushing instructions that have forbidden slots. ++bool LoongArchInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { ++ return (MI.getDesc().TSFlags & LoongArchII::HasForbiddenSlot) != 0; ++} ++ ++/// Return the number of bytes of code the specified instruction may be. ++unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { ++ switch (MI.getOpcode()) { ++ default: ++ return MI.getDesc().getSize(); ++ case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. ++ const MachineFunction *MF = MI.getParent()->getParent(); ++ const char *AsmStr = MI.getOperand(0).getSymbolName(); ++ return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); ++ } ++ } ++} ++ ++MachineInstrBuilder ++LoongArchInstrInfo::genInstrWithNewOpc(unsigned NewOpc, ++ MachineBasicBlock::iterator I) const { ++ MachineInstrBuilder MIB; ++ ++ int ZeroOperandPosition = -1; ++ bool BranchWithZeroOperand = false; ++ if (I->isBranch() && !I->isPseudo()) { ++ auto TRI = I->getParent()->getParent()->getSubtarget().getRegisterInfo(); ++ ZeroOperandPosition = I->findRegisterUseOperandIdx(LoongArch::ZERO, false, TRI); ++ BranchWithZeroOperand = ZeroOperandPosition != -1; ++ } ++ ++ MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); ++ ++ if (NewOpc == LoongArch::JIRL) { ++ MIB->removeOperand(0); ++ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { ++ MIB.add(I->getOperand(J)); ++ } ++ MIB.addImm(0); ++ } else { ++ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { ++ if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) ++ continue; ++ ++ MIB.add(I->getOperand(J)); ++ } ++ } ++ ++ MIB.copyImplicitOps(*I); ++ MIB.cloneMemRefs(*I); ++ return MIB; ++} ++ ++bool LoongArchInstrInfo::findCommutedOpIndices(const MachineInstr &MI, ++ unsigned &SrcOpIdx1, ++ unsigned &SrcOpIdx2) const { ++ assert(!MI.isBundle() && ++ "TargetInstrInfo::findCommutedOpIndices() can't handle bundles"); ++ ++ const MCInstrDesc &MCID = MI.getDesc(); ++ if (!MCID.isCommutable()) ++ return false; ++ ++ return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); ++} ++ ++// bstrins, bstrpick have the following constraints: ++// 0 <= lsb <= msb <= High ++static bool verifyBstrInstruction(const MachineInstr &MI, StringRef &ErrInfo, ++ const int64_t High) { ++ MachineOperand MOMsb = MI.getOperand(2); ++ if (!MOMsb.isImm()) { ++ ErrInfo = "Msb operand is not an immediate!"; ++ return false; ++ } ++ MachineOperand MOLsb = MI.getOperand(3); ++ if (!MOLsb.isImm()) { ++ ErrInfo = "Lsb operand is not an immediate!"; ++ return false; ++ } ++ ++ int64_t Lsb = MOLsb.getImm(); ++ if (!((0 <= Lsb) && (Lsb <= High))) { ++ ErrInfo = "Lsb operand is out of range!"; ++ return false; ++ } ++ ++ int64_t Msb = MOMsb.getImm(); ++ if (!((0 <= Msb) && (Msb <= High))) { ++ ErrInfo = "Msb operand is out of range!"; ++ return false; ++ } ++ ++ if (!(Lsb <= Msb)) { ++ ErrInfo = "Lsb operand is not less than or equal to msb operand!"; ++ return false; ++ } ++ ++ return true; ++} ++ ++// Perform target specific instruction verification. ++bool LoongArchInstrInfo::verifyInstruction(const MachineInstr &MI, ++ StringRef &ErrInfo) const { ++ // Verify that bstrins and bstrpick instructions are well formed. ++ switch (MI.getOpcode()) { ++ case LoongArch::BSTRINS_W: ++ case LoongArch::BSTRPICK_W: ++ return verifyBstrInstruction(MI, ErrInfo, 31); ++ case LoongArch::BSTRINS_D: ++ case LoongArch::BSTRPICK_D: ++ return verifyBstrInstruction(MI, ErrInfo, 63); ++ default: ++ return true; ++ } ++ ++ return true; ++} ++ ++std::pair ++LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { ++ return std::make_pair(TF, 0u); ++} ++ ++ArrayRef> ++LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { ++ using namespace LoongArchII; ++ ++ static const std::pair Flags[] = { ++ {MO_PCREL_HI, "larch-pcrel-hi"}, ++ {MO_PCREL_LO, "larch-pcrel-lo"}, ++ {MO_TLSGD_HI, "larch-tlsgd-hi"}, ++ {MO_TLSGD_LO, "larch-tlsgd-lo"}, ++ {MO_TLSIE_HI, "larch-tlsie-hi"}, ++ {MO_TLSIE_LO, "larch-tlsie-lo"}, ++ {MO_TLSLE_HI, "larch-tlsle-hi"}, ++ {MO_TLSLE_LO, "larch-tlsle-lo"}, ++ {MO_ABS_HI, "larch-abs-hi"}, ++ {MO_ABS_LO, "larch-abs-lo"}, ++ {MO_ABS_HIGHER, "larch-abs-higher"}, ++ {MO_ABS_HIGHEST, "larch-abs-highest"}, ++ {MO_GOT_HI, "larch-got-hi"}, ++ {MO_GOT_LO, "larch-got-lo"}, ++ {MO_CALL_HI, "larch-call-hi"}, ++ {MO_CALL_LO, "larch-call-lo"} ++ }; ++ return makeArrayRef(Flags); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +index 0a8c86a5e..53191a94d 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +@@ -1,4 +1,4 @@ +-//=- LoongArchInstrInfo.h - LoongArch Instruction Information ---*- C++ -*-===// ++//===- LoongArchInstrInfo.h - LoongArch Instruction Information -----------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -8,39 +8,239 @@ + // + // This file contains the LoongArch implementation of the TargetInstrInfo class. + // ++// FIXME: We need to override TargetInstrInfo::getInlineAsmLength method in ++// order for LoongArchLongBranch pass to work correctly when the code has inline ++// assembly. The returned value doesn't have to be the asm instruction's exact ++// size in bytes; LoongArchLongBranch only expects it to be the correct upper bound. + //===----------------------------------------------------------------------===// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H + ++#define DBAR_HINT 0x700 ++ ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "LoongArch.h" + #include "LoongArchRegisterInfo.h" ++#include "llvm/ADT/ArrayRef.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" ++#include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineMemOperand.h" + #include "llvm/CodeGen/TargetInstrInfo.h" ++#include + + #define GET_INSTRINFO_HEADER + #include "LoongArchGenInstrInfo.inc" + + namespace llvm { + ++class MachineInstr; ++class MachineOperand; + class LoongArchSubtarget; ++class TargetRegisterClass; ++class TargetRegisterInfo; + + class LoongArchInstrInfo : public LoongArchGenInstrInfo { ++ virtual void anchor(); ++ const LoongArchRegisterInfo RI; ++ const LoongArchSubtarget &Subtarget; ++ + public: +- explicit LoongArchInstrInfo(LoongArchSubtarget &STI); ++ enum BranchType { ++ BT_None, // Couldn't analyze branch. ++ BT_NoBranch, // No branches found. ++ BT_Uncond, // One unconditional branch. ++ BT_Cond, // One conditional branch. ++ BT_CondUncond, // A conditional branch followed by an unconditional branch. ++ BT_Indirect // One indirct branch. ++ }; ++ ++ explicit LoongArchInstrInfo(const LoongArchSubtarget &STI); + +- void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, +- const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, ++ /// isLoadFromStackSlot - If the specified machine instruction is a direct ++ /// load from a stack slot, return the virtual or physical register number of ++ /// the destination along with the FrameIndex of the loaded stack slot. If ++ /// not, return 0. This predicate must return 0 if the instruction has ++ /// any side effects other than loading from the stack slot. ++ unsigned isLoadFromStackSlot(const MachineInstr &MI, ++ int &FrameIndex) const override; ++ ++ /// isStoreToStackSlot - If the specified machine instruction is a direct ++ /// store to a stack slot, return the virtual or physical register number of ++ /// the source reg along with the FrameIndex of the loaded stack slot. If ++ /// not, return 0. This predicate must return 0 if the instruction has ++ /// any side effects other than storing to the stack slot. ++ unsigned isStoreToStackSlot(const MachineInstr &MI, ++ int &FrameIndex) const override; ++ ++ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, ++ const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, + bool KillSrc) const override; + ++ /// Branch Analysis ++ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, ++ MachineBasicBlock *&FBB, ++ SmallVectorImpl &Cond, ++ bool AllowModify) const override; ++ ++ unsigned removeBranch(MachineBasicBlock &MBB, ++ int *BytesRemoved = nullptr) const override; ++ ++ unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, ++ MachineBasicBlock *FBB, ArrayRef Cond, ++ const DebugLoc &DL, ++ int *BytesAdded = nullptr) const override; ++ ++ void insertIndirectBranch(MachineBasicBlock &MBB, ++ MachineBasicBlock &NewDestBB, ++ MachineBasicBlock &RestoreBB, const DebugLoc &DL, ++ int64_t BrOffset, ++ RegScavenger *RS = nullptr) const override; ++ bool ++ reverseBranchCondition(SmallVectorImpl &Cond) const override; ++ ++ BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, ++ MachineBasicBlock *&FBB, ++ SmallVectorImpl &Cond, ++ bool AllowModify, ++ SmallVectorImpl &BranchInstrs) const; ++ ++ /// Get the block that branch instruction jumps to. ++ MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; ++ ++ /// Determine if the branch target is in range. ++ bool isBranchOffsetInRange(unsigned BranchOpc, ++ int64_t BrOffset) const override; ++ ++ /// Predicate to determine if an instruction can go in a forbidden slot. ++ bool SafeInForbiddenSlot(const MachineInstr &MI) const; ++ ++ /// Predicate to determine if an instruction has a forbidden slot. ++ bool HasForbiddenSlot(const MachineInstr &MI) const; ++ ++ /// Insert nop instruction when hazard condition is found ++ void insertNoop(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI) const override; ++ ++ /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As ++ /// such, whenever a client has an instance of instruction info, it should ++ /// always be able to get register info as well (through this method). ++ const LoongArchRegisterInfo &getRegisterInfo() const; ++ ++ bool expandPostRAPseudo(MachineInstr &MI) const override; ++ ++ unsigned getOppositeBranchOpc(unsigned Opc) const; ++ ++ /// Emit a series of instructions to load an immediate. ++ unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator II, ++ const DebugLoc &DL) const; ++ ++ /// Return the number of bytes of code the specified instruction may be. ++ unsigned getInstSizeInBytes(const MachineInstr &MI) const override; ++ + void storeRegToStackSlot(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator MBBI, Register SrcReg, +- bool IsKill, int FrameIndex, ++ MachineBasicBlock::iterator MBBI, ++ Register SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, +- const TargetRegisterInfo *TRI) const override; ++ const TargetRegisterInfo *TRI) const override { ++ storeRegToStack(MBB, MBBI, SrcReg, isKill, FrameIndex, RC, TRI, 0); ++ } ++ + void loadRegFromStackSlot(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator MBBI, Register DstReg, +- int FrameIndex, const TargetRegisterClass *RC, +- const TargetRegisterInfo *TRI) const override; ++ MachineBasicBlock::iterator MBBI, ++ Register DestReg, int FrameIndex, ++ const TargetRegisterClass *RC, ++ const TargetRegisterInfo *TRI) const override { ++ loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0); ++ } ++ ++ void storeRegToStack(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI, ++ Register SrcReg, bool isKill, int FrameIndex, ++ const TargetRegisterClass *RC, ++ const TargetRegisterInfo *TRI, ++ int64_t Offset) const; ++ ++ void loadRegFromStack(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI, ++ Register DestReg, int FrameIndex, ++ const TargetRegisterClass *RC, ++ const TargetRegisterInfo *TRI, ++ int64_t Offset) const; ++ ++ /// Adjust register value(DestReg = SrcReg + Amount). ++ void ++ adjustReg(unsigned DestReg, unsigned SrcReg, int64_t Amount, ++ MachineBasicBlock &MBB, MachineBasicBlock::iterator I, ++ MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags) const; ++ ++ /// Create an instruction which has the same operands and memory operands ++ /// as MI but has a new opcode. ++ MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, ++ MachineBasicBlock::iterator I) const; ++ ++ bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, ++ unsigned &SrcOpIdx2) const override; ++ ++ /// Perform target specific instruction verification. ++ bool verifyInstruction(const MachineInstr &MI, ++ StringRef &ErrInfo) const override; ++ ++ std::pair ++ decomposeMachineOperandsTargetFlags(unsigned TF) const override; ++ ++ ArrayRef> ++ getSerializableDirectMachineOperandTargetFlags() const override; ++ ++protected: ++ /// If the specific machine instruction is a instruction that moves/copies ++ /// value from one register to another register return true along with ++ /// @Source machine operand and @Destination machine operand. ++ Optional ++ isCopyInstrImpl(const MachineInstr &MI) const override; ++ ++private: ++ ++ bool isZeroImm(const MachineOperand &op) const; ++ ++ MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI, ++ MachineMemOperand::Flags Flags) const; ++ ++ unsigned getAnalyzableBrOpc(unsigned Opc) const; ++ ++ void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, ++ MachineBasicBlock *&BB, ++ SmallVectorImpl &Cond) const; ++ ++ MachineInstr * ++ BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, ++ const DebugLoc &DL, ArrayRef Cond) const; ++ ++ void expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; ++ ++ void expandERet(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; ++ ++ std::pair compareOpndSize(unsigned Opc, ++ const MachineFunction &MF) const; ++ ++ /// Expand pseudo Int-to-FP conversion instructions. ++ /// ++ /// For example, the following pseudo instruction ++ /// PseudoCVT_D32_W D2, A5 ++ /// gets expanded into these two instructions: ++ /// MTC1 F4, A5 ++ /// CVT_D32_W D2, F4 ++ /// ++ /// We do this expansion post-RA to avoid inserting a floating point copy ++ /// instruction between MTC1 and CVT_D32_W. ++ void expandCvtFPInt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, ++ unsigned CvtOpc, unsigned MovOpc, bool IsI64) const; ++ ++ void expandEhReturn(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator I) const; + }; + + } // end namespace llvm ++ + #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +index d07d086bd..2d505ee25 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +@@ -1,4 +1,4 @@ +-//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-// ++//===- LoongArchInstrInfo.td - Target Description for LoongArch Target -*- tablegen -*-=// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,929 +6,1883 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file describes the LoongArch instructions in TableGen format. ++// This file contains the LoongArch implementation of the TargetInstrInfo class. + // + //===----------------------------------------------------------------------===// ++include "LoongArchInstrFormats.td" + +-//===----------------------------------------------------------------------===// +-// LoongArch specific DAG Nodes. +-//===----------------------------------------------------------------------===// ++def SDT_Bstrpick : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, ++ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>; ++def SDT_Bstrins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, ++ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, ++ SDTCisSameAs<0, 4>]>; + +-// Target-independent type requirements, but with target-specific formats. +-def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, +- SDTCisVT<1, i32>]>; +-def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, +- SDTCisVT<1, i32>]>; +- +-// Target-dependent type requirements. +-def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>; +-def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [ +- SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> +-]>; +- +-def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [ +- SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>, +- SDTCisSameAs<3, 4> +-]>; +- +-def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [ +- SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3> +-]>; +- +-// TODO: Add LoongArch specific DAG Nodes +-// Target-independent nodes, but with target-specific formats. +-def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, +- [SDNPHasChain, SDNPOutGlue]>; +-def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, +- [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +- +-// Target-dependent nodes. +-def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall, +- [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, +- SDNPVariadic]>; +-def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone, +- [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +-def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>; +-def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>; +-def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>; +-def loongarch_bstrins +- : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>; +-def loongarch_bstrpick +- : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>; ++def LoongArchBstrpick : SDNode<"LoongArchISD::BSTRPICK", SDT_Bstrpick>; + +-//===----------------------------------------------------------------------===// +-// Operand and SDNode transformation definitions. +-//===----------------------------------------------------------------------===// ++def LoongArchBstrins : SDNode<"LoongArchISD::BSTRINS", SDT_Bstrins>; + +-class ImmAsmOperand +- : AsmOperandClass { +- let Name = prefix # "Imm" # width # suffix; +- let DiagnosticType = !strconcat("Invalid", Name); ++def SDT_DBAR : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; ++def LoongArchDBAR : SDNode<"LoongArchISD::DBAR", SDT_DBAR, [SDNPHasChain,SDNPSideEffect]>; ++ ++def SDT_LoongArchEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>; ++ ++def LoongArchehret : SDNode<"LoongArchISD::EH_RETURN", SDT_LoongArchEHRET, ++ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; ++ ++//===---------------------------------------------------------------------===/ ++// Operand, Complex Patterns and Transformations Definitions. ++//===---------------------------------------------------------------------===/ ++ ++def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ ++ return cast(N->getOperand(1))->getVT().bitsLT(MVT::i32); ++}]>; ++ ++def immz : PatLeaf<(imm), [{ return N->getSExtValue() == 0; }]>; ++def immZExt12 : PatLeaf<(imm), [{ return isUInt<12>(N->getZExtValue()); }]>; ++def immSExt12 : PatLeaf<(imm), [{ return isInt<12>(N->getSExtValue()); }]>; ++def immSExt13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; ++ ++def immZExt2Alsl : ImmLeaf(Imm - 1);}]>; ++//class ImmAsmOperand : AsmOperandClass { ++// let RenderMethod = "addImmOperands"; ++// let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; ++// let DiagnosticString = "operand must be an immediate in the range [" # Low # "," # High # "]"; ++//} ++// ++//def Imm8AsmOperand: ImmAsmOperand<8,8> { let Name = "Imm8"; } ++//def imm8 : Operand, ImmLeaf { ++// let ParserMatchClass = Imm8AsmOperand; ++//} ++ ++def HasLSX : Predicate<"Subtarget->hasLSX()">, ++ AssemblerPredicate<(all_of FeatureLSX)>; ++def HasLASX : Predicate<"Subtarget->hasLASX()">, ++ AssemblerPredicate<(all_of FeatureLASX)>; ++ ++class EXT_LSX { ++ list ExtPredicate = [HasLSX]; ++} ++ ++class EXT_LASX { ++ list ExtPredicate = [HasLASX]; ++} ++ ++class SImmOperand : AsmOperandClass { ++ let Name = "SImm" # width; ++ let DiagnosticType = "InvalidSImm" # width; + let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isSImm<" # width # ">"; + } + +-class SImmAsmOperand +- : ImmAsmOperand<"S", width, suffix> { ++def SImm2Operand : SImmOperand<2>; ++def simm2 : Operand, ImmLeaf= -2 && Imm < 2; }]> { ++ let ParserMatchClass = SImm2Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; ++} ++def SImm3Operand : SImmOperand<3>; ++def simm3 : Operand, ImmLeaf= -4 && Imm < 4; }]> { ++ let ParserMatchClass = SImm3Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<3>"; + } + +-class UImmAsmOperand +- : ImmAsmOperand<"U", width, suffix> { ++def SImm5Operand : SImmOperand<5>; ++def simm5 : Operand, ImmLeaf= -16 && Imm < 16; }]> { ++ let ParserMatchClass = SImm5Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<5>"; + } + +-def uimm2 : Operand { +- let ParserMatchClass = UImmAsmOperand<2>; ++def simm5_32 : Operand, ImmLeaf= -16 && Imm < 16; }]> { ++ let ParserMatchClass = SImm5Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<5>"; + } + +-def uimm2_plus1 : Operand { +- let ParserMatchClass = UImmAsmOperand<2, "plus1">; +- let EncoderMethod = "getImmOpValueSub1"; +- let DecoderMethod = "decodeUImmOperand<2, 1>"; ++def SImm8Operand : SImmOperand<8>; ++def simm8 : Operand, ImmLeaf= -128 && Imm < 128; }]> { ++ let ParserMatchClass = SImm8Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; ++} ++def simm8_32 : Operand, ImmLeaf= -128 && Imm < 128; }]> { ++ let ParserMatchClass = SImm8Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; + } + +-def uimm3 : Operand { +- let ParserMatchClass = UImmAsmOperand<3>; ++def SImm12Operand : SImmOperand<12>; ++def simm12 : Operand, ImmLeaf= -2048 && Imm < 2048; }]> { ++ let ParserMatchClass = SImm12Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; ++} ++def simm12_32 : Operand, ImmLeaf= -2048 && Imm < 2048; }]> { ++ let ParserMatchClass = SImm12Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; + } + +-def uimm5 : Operand, ImmLeaf(Imm);}]> { +- let ParserMatchClass = UImmAsmOperand<5>; ++def SImm14Operand : SImmOperand<14>; ++def simm14 : Operand, ImmLeaf= -8192 && Imm < 8192; }]> { ++ let ParserMatchClass = SImm14Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<14>"; + } + +-def uimm6 : Operand, ImmLeaf(Imm);}]> { +- let ParserMatchClass = UImmAsmOperand<6>; ++def SImm15Operand : SImmOperand<15>; ++def simm15 : Operand, ImmLeaf= -16384 && Imm < 16384; }]> { ++ let ParserMatchClass = SImm15Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<15>"; + } + +-def uimm8 : Operand { +- let ParserMatchClass = UImmAsmOperand<8>; ++def SImm16Operand : SImmOperand<16>; ++def simm16 : Operand, ImmLeaf= -32768 && Imm < 32768; }]> { ++ let ParserMatchClass = SImm16Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + } + +-def uimm12 : Operand, ImmLeaf(Imm);}]> { +- let ParserMatchClass = UImmAsmOperand<12>; ++def SImm20Operand : SImmOperand<20>; ++def simm20 : Operand, ImmLeaf= -524288 && Imm < 524288; }]> { ++ let ParserMatchClass = SImm20Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<20>"; ++} ++def simm20_32 : Operand, ImmLeaf= -524288 && Imm < 524288; }]> { ++ let ParserMatchClass = SImm20Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<20>"; + } + +-def uimm14 : Operand { +- let ParserMatchClass = UImmAsmOperand<14>; ++def SImm21Operand : SImmOperand<21>; ++def simm21 : Operand, ImmLeaf= -1048576 && Imm < 1048576; }]> { ++ let ParserMatchClass = SImm21Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<21>"; + } + +-def uimm15 : Operand { +- let ParserMatchClass = UImmAsmOperand<15>; ++def SImm26Operand : SImmOperand<26>; ++def simm26 : Operand, ImmLeaf= -33554432 && Imm < 33554432; }]> { ++ let ParserMatchClass = SImm26Operand; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<26>"; + } + +-def simm12 : Operand, ImmLeaf(Imm);}]> { +- let ParserMatchClass = SImmAsmOperand<12>; +- let DecoderMethod = "decodeSImmOperand<12>"; ++def UImm1Operand : AsmOperandClass { ++ let Name = "UImm1"; ++ let RenderMethod = "addUImmOperands<1>"; ++ let PredicateMethod = "isUImm<1>"; ++ let DiagnosticType = "InvalidImm0_1"; + } + +-def simm14_lsl2 : Operand { +- let ParserMatchClass = SImmAsmOperand<14, "lsl2">; +- let EncoderMethod = "getImmOpValueAsr2"; +- let DecoderMethod = "decodeSImmOperand<14, 2>"; ++def UImm2Operand : AsmOperandClass { ++ let Name = "UImm2"; ++ let RenderMethod = "addUImmOperands<2>"; ++ let PredicateMethod = "isUImm<2>"; ++ let DiagnosticType = "InvalidImm0_3"; + } + +-def simm16 : Operand { +- let ParserMatchClass = SImmAsmOperand<16>; +- let DecoderMethod = "decodeSImmOperand<16>"; ++def UImm3Operand : AsmOperandClass { ++ let Name = "UImm3"; ++ let RenderMethod = "addUImmOperands<3>"; ++ let PredicateMethod = "isUImm<3>"; ++ let DiagnosticType = "InvalidImm0_7"; + } + +-def simm16_lsl2 : Operand, +- ImmLeaf(Imm>>2);}]> { +- let ParserMatchClass = SImmAsmOperand<16, "lsl2">; +- let EncoderMethod = "getImmOpValueAsr2"; +- let DecoderMethod = "decodeSImmOperand<16, 2>"; ++def UImm4Operand : AsmOperandClass { ++ let Name = "UImm4"; ++ let RenderMethod = "addUImmOperands<4>"; ++ let PredicateMethod = "isUImm<4>"; ++ let DiagnosticType = "InvalidImm0_15"; + } + +-def simm16_lsl2_br : Operand { +- let ParserMatchClass = SImmAsmOperand<16, "lsl2">; +- let EncoderMethod = "getImmOpValueAsr2"; +- let DecoderMethod = "decodeSImmOperand<16, 2>"; ++def UImm5Operand : AsmOperandClass { ++ let Name = "UImm5"; ++ let RenderMethod = "addUImmOperands<5>"; ++ let PredicateMethod = "isUImm<5>"; ++ let DiagnosticType = "InvalidImm0_31"; + } + +-def simm20 : Operand { +- let ParserMatchClass = SImmAsmOperand<20>; +- let DecoderMethod = "decodeSImmOperand<20>"; ++def uimm1i : Operand, ImmLeaf= 0 && Imm < 2; }]> { ++ let PrintMethod = "printUImm<1>"; ++ let ParserMatchClass = UImm1Operand; + } + +-def simm21_lsl2 : Operand { +- let ParserMatchClass = SImmAsmOperand<21, "lsl2">; +- let EncoderMethod = "getImmOpValueAsr2"; +- let DecoderMethod = "decodeSImmOperand<21, 2>"; ++def uimm2 : Operand, ImmLeaf= 0 && Imm < 4; }]> { ++ let PrintMethod = "printUImm<2>"; ++ let ParserMatchClass = UImm2Operand; + } + +-def simm26_lsl2 : Operand { +- let ParserMatchClass = SImmAsmOperand<26, "lsl2">; +- let EncoderMethod = "getImmOpValueAsr2"; +- let DecoderMethod = "decodeSImmOperand<26, 2>"; ++def uimm3 : Operand, ImmLeaf= 0 && Imm < 8; }]> { ++ let PrintMethod = "printUImm<3>"; ++ let ParserMatchClass = UImm3Operand; + } + +-// Standalone (codegen-only) immleaf patterns. ++def uimm4i : Operand, ImmLeaf= 0 && Imm < 16; }]> { ++ let PrintMethod = "printUImm<4>"; ++ let ParserMatchClass = UImm4Operand; ++} + +-// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048]. +-def simm12_plus1 : ImmLeaf(Imm) && Imm != -2048) || Imm == 2048;}]>; ++def uimm5 : Operand, ImmLeaf= 0 && Imm < 32; }]> { ++ let PrintMethod = "printUImm<5>"; ++ let ParserMatchClass = UImm5Operand; ++} + +-// Return the negation of an immediate value. +-def NegImm : SDNodeXFormgetTargetConstant(-N->getSExtValue(), SDLoc(N), +- N->getValueType(0)); +-}]>; ++def UImm6Operand : AsmOperandClass { ++ let Name = "UImm6"; ++ let RenderMethod = "addUImmOperands<16>"; ++ let PredicateMethod = "isUImm<6>"; ++ let DiagnosticType = "InvalidImm0_63"; ++} ++def uimm6 : Operand, ImmLeaf= 0 && Imm < 64; }]> { ++ let PrintMethod = "printUImm<6>"; ++ let ParserMatchClass = UImm6Operand; ++} + +-// FP immediate patterns. +-def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>; +-def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>; +-def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; ++def UImm7Operand : AsmOperandClass { ++ let Name = "UImm7"; ++ let RenderMethod = "addUImmOperands<16>"; ++ let PredicateMethod = "isUImm<7>"; ++ let DiagnosticType = "InvalidImm0_127"; ++} + +-def CallSymbol: AsmOperandClass { +- let Name = "CallSymbol"; ++def uimm7i : Operand, ImmLeaf= 0 && Imm < 128; }]> { ++ let PrintMethod = "printUImm<7>"; ++ let ParserMatchClass = UImm7Operand; ++} ++ ++def UImm12Operand : AsmOperandClass { ++ let Name = "UImm12"; ++ let RenderMethod = "addUImmOperands<12>"; ++ let PredicateMethod = "isUImm<12>"; ++ let DiagnosticType = "InvalidImm0_4095"; ++} ++def uimm12 : Operand, ImmLeaf= 0 && Imm < 4096; }]> { ++ let PrintMethod = "printUImm<12>"; ++ let ParserMatchClass = UImm12Operand; ++} ++def uimm12_32 : Operand, ImmLeaf= 0 && Imm < 4096; }]> { ++ let PrintMethod = "printUImm<12>"; ++ let ParserMatchClass = UImm12Operand; ++} ++ ++def UImm15Operand : AsmOperandClass { ++ let Name = "UImm15"; ++ let RenderMethod = "addUImmOperands<15>"; ++ let PredicateMethod = "isUImm<15>"; ++ let DiagnosticType = "InvalidImm0_32767"; ++} ++def uimm15 : Operand, ImmLeaf= 0 && Imm < 32768; }]> { ++ let PrintMethod = "printUImm<15>"; ++ let ParserMatchClass = UImm15Operand; ++} ++ ++def UImm14Operand : AsmOperandClass { ++ let Name = "UImm14"; ++ let RenderMethod = "addUImmOperands<14>"; ++ let PredicateMethod = "isUImm<14>"; ++ let DiagnosticType = "InvalidImm0_16383"; ++} ++def uimm14 : Operand, ImmLeaf= 0 && Imm < 16384; }]> { ++ let PrintMethod = "printUImm<14>"; ++ let ParserMatchClass = UImm14Operand; ++} ++def uimm14_32 : Operand, ImmLeaf= 0 && Imm < 16384; }]> { ++ let PrintMethod = "printUImm<14>"; ++ let ParserMatchClass = UImm14Operand; ++} ++ ++def UImm8Operand : AsmOperandClass { ++ let Name = "UImm8"; ++ let RenderMethod = "addUImmOperands<8>"; ++ let PredicateMethod = "isUImm<8>"; ++ let DiagnosticType = "InvalidImm0_255"; ++} ++def uimm8_64 : Operand, ImmLeaf= 0 && Imm < 256; }]> { ++ let PrintMethod = "printUImm<8>"; ++ let ParserMatchClass = UImm8Operand; ++} ++ ++def uimm8_32 : Operand, ImmLeaf= 0 && Imm < 256; }]> { ++ let PrintMethod = "printUImm<8>"; ++ let ParserMatchClass = UImm8Operand; ++} ++ ++def addr : ++ComplexPattern; ++ ++def addrDefault : ++ComplexPattern; ++ ++def addrRegImm : ++ComplexPattern; ++ ++def addrimm14lsl2 : ComplexPattern; ++ ++class ConstantUImmAsmOperandClass Supers = [], ++ int Offset = 0> : AsmOperandClass { ++ let Name = "ConstantUImm" # Bits # "_" # Offset; ++ let RenderMethod = "addConstantUImmOperands<" # Bits # ", " # Offset # ">"; ++ let PredicateMethod = "isConstantUImm<" # Bits # ", " # Offset # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "UImm" # Bits # "_" # Offset; ++} ++class SImmAsmOperandClass Supers = []> ++ : AsmOperandClass { ++ let Name = "SImm" # Bits; ++ let RenderMethod = "addSImmOperands<" # Bits # ">"; ++ let PredicateMethod = "isSImm<" # Bits # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "SImm" # Bits; ++} ++class UImmAnyAsmOperandClass Supers = []> ++ : AsmOperandClass { ++ let Name = "ImmAny"; ++ let RenderMethod = "addConstantUImmOperands<32>"; ++ let PredicateMethod = "isSImm<" # Bits # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "ImmAny"; ++} ++ ++def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> { ++ let Name = "UImm32_Coerced"; ++ let DiagnosticType = "UImm32_Coerced"; ++} ++def SImm32RelaxedAsmOperandClass ++ : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> { ++ let Name = "SImm32_Relaxed"; ++ let PredicateMethod = "isAnyImm<33>"; ++ let DiagnosticType = "SImm32_Relaxed"; ++} ++def SImm32AsmOperandClass ++ : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>; ++def ConstantUImm26AsmOperandClass ++ : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>; ++ ++def ConstantUImm20AsmOperandClass ++ : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>; ++ ++def ConstantUImm2Plus1AsmOperandClass ++ : ConstantUImmAsmOperandClass<2, [ConstantUImm20AsmOperandClass], 1>; ++ ++class UImmAsmOperandClass Supers = []> ++ : AsmOperandClass { ++ let Name = "UImm" # Bits; ++ let RenderMethod = "addUImmOperands<" # Bits # ">"; ++ let PredicateMethod = "isUImm<" # Bits # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "UImm" # Bits; ++} ++ ++def UImm16RelaxedAsmOperandClass ++ : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> { ++ let Name = "UImm16_Relaxed"; ++ let PredicateMethod = "isAnyImm<16>"; ++ let DiagnosticType = "UImm16_Relaxed"; ++} ++ ++def ConstantSImm14Lsl2AsmOperandClass : AsmOperandClass { ++ let Name = "SImm14Lsl2"; + let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<14, 2>"; ++ let SuperClasses = [UImm16RelaxedAsmOperandClass]; ++ let DiagnosticType = "SImm14_Lsl2"; ++} ++ ++foreach I = {2} in ++ def simm14_lsl # I : Operand { ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<14, " # I # ">"; ++ let ParserMatchClass = ++ !cast("ConstantSImm14Lsl" # I # "AsmOperandClass"); ++ } ++ ++def uimm16_64_relaxed : Operand { ++ let PrintMethod = "printUImm<16>"; ++ let ParserMatchClass = ++ !cast("UImm16RelaxedAsmOperandClass"); ++} ++ ++def uimm2_plus1 : Operand { ++ let PrintMethod = "printUImm<2, 1>"; ++ let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; ++ let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; ++ let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; ++} ++ ++// like simm32 but coerces simm32 to uimm32. ++def uimm32_coerced : Operand { ++ let ParserMatchClass = !cast("UImm32CoercedAsmOperandClass"); ++} ++ ++def imm64: Operand; ++ ++def LoongArchMemAsmOperand : AsmOperandClass { ++ let Name = "Mem"; ++ let ParserMethod = "parseMemOperand"; ++} ++ ++def LoongArchAMemAsmOperand : AsmOperandClass { ++ let Name = "AMem"; ++ let ParserMethod = "parseAMemOperand"; ++ let RenderMethod = "addMemOperands"; ++ let PredicateMethod = "isZeroMemOff"; ++ let DiagnosticType = "MemZeroOff"; ++} ++ ++def LoongArchMemSimm14AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm14"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<14>"; ++ let DiagnosticType = "MemSImm14"; ++} ++ ++foreach I = {2} in ++ def LoongArchMemSimm14Lsl # I # AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm14_" # I; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<14, " # I # ">"; ++ let DiagnosticType = "MemSImm14Lsl" # I; ++ } ++ ++def LoongArchMemSimmPtrAsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimmPtr"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithPtrSizeOffset"; ++ let DiagnosticType = "MemSImmPtr"; ++} ++ ++class mem_generic : Operand { ++ let PrintMethod = "printMemOperand"; ++ let MIOperandInfo = (ops ptr_rc, simm12); ++ let EncoderMethod = "getMemEncoding"; ++ let ParserMatchClass = LoongArchMemAsmOperand; ++ let OperandType = "OPERAND_MEMORY"; ++} ++ ++// Address operand ++def mem : mem_generic; ++ ++def amem : mem_generic { ++ let PrintMethod = "printAMemOperand"; ++ let EncoderMethod = "getAMemEncoding"; ++ let ParserMatchClass = LoongArchAMemAsmOperand; ++} ++ ++def mem_simmptr : mem_generic { ++ let ParserMatchClass = LoongArchMemSimmPtrAsmOperand; ++} ++ ++foreach I = {2} in ++ def mem_simm14_lsl # I : mem_generic { ++ let MIOperandInfo = (ops ptr_rc, !cast("simm14_lsl" # I)); ++ let EncoderMethod = "getSimm14MemEncoding<" # I # ">"; ++ let ParserMatchClass = ++ !cast("LoongArchMemSimm14Lsl" # I # "AsmOperand"); ++ } ++ ++def mem_ea : Operand { ++ let PrintMethod = "printMemOperandEA"; ++ let MIOperandInfo = (ops ptr_rc, simm12); ++ let EncoderMethod = "getMemEncoding"; ++ let OperandType = "OPERAND_MEMORY"; ++} ++ ++def LoongArchJumpTargetAsmOperand : AsmOperandClass { ++ let Name = "JumpTarget"; ++ let ParserMethod = "parseJumpTarget"; + let PredicateMethod = "isImm"; ++ let RenderMethod = "addImmOperands"; + } + +-// A bare symbol used in call only. +-def call_symbol : Operand { +- let ParserMatchClass = CallSymbol; ++def jmptarget : Operand { ++ let EncoderMethod = "getJumpTargetOpValue"; ++ let ParserMatchClass = LoongArchJumpTargetAsmOperand; + } + +-def BaseAddr : ComplexPattern; ++def brtarget : Operand { ++ let EncoderMethod = "getBranchTargetOpValue"; ++ let OperandType = "OPERAND_PCREL"; ++ let DecoderMethod = "DecodeBranchTarget"; ++ let ParserMatchClass = LoongArchJumpTargetAsmOperand; ++} + +-//===----------------------------------------------------------------------===// +-// Instruction Formats +-//===----------------------------------------------------------------------===// ++def calltarget : Operand { ++ let EncoderMethod = "getJumpTargetOpValue"; ++ let ParserMatchClass = LoongArchJumpTargetAsmOperand; ++} + +-include "LoongArchInstrFormats.td" +-include "LoongArchFloatInstrFormats.td" ++// ++//SDNode ++// ++def IsGP64bit : Predicate<"Subtarget->is64Bit()">, ++ AssemblerPredicate<(all_of Feature64Bit)>; ++def IsGP32bit : Predicate<"!Subtarget->is64Bit()">, ++ AssemblerPredicate<(all_of (not Feature64Bit))>; ++def SDT_LoongArchCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; ++def SDT_LoongArchCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; ++ ++def LoongArchRet : SDNode<"LoongArchISD::Ret", SDTNone, ++ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; ++def LoongArchERet : SDNode<"LoongArchISD::ERet", SDTNone, ++ [SDNPHasChain, SDNPOptInGlue, SDNPSideEffect]>; ++ ++def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_LoongArchCallSeqStart, ++ [SDNPHasChain, SDNPSideEffect, SDNPOutGlue]>; ++def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_LoongArchCallSeqEnd, ++ [SDNPHasChain, SDNPSideEffect, ++ SDNPOptInGlue, SDNPOutGlue]>; ++def LoongArchAddress : SDNode<"LoongArchISD::GlobalAddress", SDTIntUnaryOp>; ++ ++// Return RA. ++let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { ++ def RetRA : LoongArchPseudo<(outs), (ins), [(LoongArchRet)]>; ++ ++ let hasSideEffects=1 in ++ def ERet : LoongArchPseudo<(outs), (ins), [(LoongArchERet)]>; ++} + +-//===----------------------------------------------------------------------===// ++let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { ++def ADJCALLSTACKDOWN : LoongArchPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), ++ [(callseq_start timm:$amt1, timm:$amt2)]>; ++def ADJCALLSTACKUP : LoongArchPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), ++ [(callseq_end timm:$amt1, timm:$amt2)]>; ++} ++ ++class LoongArchPat : Pat, PredicateControl; ++ ++def SDT_LoongArchJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; ++ ++def LoongArchJmpLink : SDNode<"LoongArchISD::JmpLink",SDT_LoongArchJmpLink, ++ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, ++ SDNPVariadic]>; ++ ++def LoongArchTailCall : SDNode<"LoongArchISD::TailCall", SDT_LoongArchJmpLink, ++ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; ++ ++class GPR_32 { list GPRPredicates = [IsGP32bit]; } ++class GPR_64 { list GPRPredicates = [IsGP64bit]; } ++ ++//===---------------------------------------------------------------------===/ + // Instruction Class Templates +-//===----------------------------------------------------------------------===// ++//===---------------------------------------------------------------------===/ ++///R2 ++class Int_Reg2 ++ : InstForm<(outs RO:$rd), (ins RO:$rj), ++ !strconcat(opstr, "\t$rd, $rj"), ++ [(set RO:$rd, (OpNode RO:$rj))], ++ FrmR, opstr>; ++ ++class Int_Reg2_Iocsrrd ++ : InstForm<(outs RD:$rd), (ins RS:$rj), ++ !strconcat(opstr, "\t$rd, $rj"), ++ [(set RD:$rd, (OpNode RS:$rj))], ++ FrmR, opstr>; ++ ++class Int_Reg2_Rdtime ++ : InstForm<(outs RO:$rd, RO:$rj), (ins), ++ !strconcat(opstr, "\t$rd, $rj"), ++ [(set (OpNode RO:$rd, RO:$rj))], ++ FrmR, opstr>; ++ ++class Int_Reg2_Iocsrwr ++ : InstForm<(outs), (ins RD:$rd, RS:$rj), ++ !strconcat(opstr, "\t$rd, $rj"), ++ [(set (OpNode RD:$rd, RS:$rj))], ++ FrmR, opstr>; ++ ++class Float_Reg2 ++ : InstForm<(outs RO:$fd), (ins RO:$fj), ++ !strconcat(opstr, "\t$fd, $fj"), ++ [(set RO:$fd, (OpNode RO:$fj))], ++ FrmFR, opstr>; ++ ++class Count1 ++ : InstForm<(outs RO:$rd), (ins RO:$rj), ++ !strconcat(opstr, "\t$rd, $rj"), ++ [(set RO:$rd, (OpNode (not RO:$rj)))], ++ FrmR, opstr>; ++ ++class SignExtInReg ++ : InstForm<(outs RO:$rd), (ins RO:$rj), !strconcat(opstr, "\t$rd, $rj"), ++ [(set RO:$rd, (sext_inreg RO:$rj, vt))], FrmR, opstr>; ++ ++///R3 ++class Int_Reg3 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set RO:$rd, (OpNode RO:$rj, RO:$rk))], ++ FrmR, opstr>; ++ ++class Int_Reg3_Crc ++ : InstForm<(outs RS:$rd), (ins RD:$rj, RS:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set RS:$rd, (OpNode RD:$rj, RS:$rk))], ++ FrmR, opstr>; ++ ++class SetCC_R ++ : InstForm<(outs GPR32Opnd:$rd), (ins RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set GPR32Opnd:$rd, (OpNode RO:$rj, RO:$rk))], ++ FrmR, opstr>; ++ ++class SetCC_I ++ : InstForm<(outs GPR32Opnd:$rd), (ins RO:$rj, ImmOpnd:$imm12), ++ !strconcat(opstr, "\t$rd, $rj, $imm12"), ++ [(set GPR32Opnd:$rd, (OpNode RO:$rj, ImmOpnd:$imm12))], ++ FrmR, opstr>; ++ ++class ATOMIC ++ : InstForm<(outs RD:$rd), (ins RD:$rk, MO:$addr), ++ !strconcat(opstr, "\t$rd, $rk, $addr"), ++ [(set RD:$rd, (OpNode RD:$rk, Addr:$addr))], ++ FrmR, opstr> { ++ let DecoderMethod = "DecodeAMem"; ++ let canFoldAsLoad = 1; ++ string BaseOpcode = opstr; ++ let mayLoad = 1; ++ let mayStore = 1; ++ let Constraints = "@earlyclobber $rd"; ++} + +-class ALU_3R op, string opstr> +- : Fmt3R; +-class ALU_2R op, string opstr> +- : Fmt2R; +- +-class ALU_3RI2 op, string opstr, Operand ImmOpnd> +- : Fmt3RI2; +-class ALU_3RI3 op, string opstr, Operand ImmOpnd> +- : Fmt3RI3; +-class ALU_2RI5 op, string opstr, Operand ImmOpnd> +- : Fmt2RI5; +-class ALU_2RI6 op, string opstr, Operand ImmOpnd> +- : Fmt2RI6; +-class ALU_2RI12 op, string opstr, Operand ImmOpnd> +- : Fmt2RI12; +-class ALU_2RI16 op, string opstr, Operand ImmOpnd> +- : Fmt2RI16; +-class ALU_1RI20 op, string opstr, Operand ImmOpnd> +- : Fmt1RI20; +- +-class MISC_I15 op, string opstr> +- : FmtI15; +- +-class RDTIME_2R op, string opstr> +- : Fmt2R; +- +-class BrCC_2RI16 op, string opstr> +- : Fmt2RI16 { +- let isBranch = 1; +- let isTerminator = 1; ++class Nor ++ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set RO:$rd, (not (or RO:$rj, RO:$rk)))], ++ FrmR, opstr>; ++ ++class Shift_Var ++ : InstForm<(outs RO:$rd), (ins RO:$rj, GPR32Opnd:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set RO:$rd, (OpNode RO:$rj, GPR32Opnd:$rk))], ++ FrmR, opstr>; ++ ++class Float_Reg3 ++ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), ++ !strconcat(opstr, "\t$fd, $fj, $fk"), ++ [(set RO:$fd, (OpNode RO:$fj, RO:$fk))], ++ FrmR, opstr>; ++ ++class Float_Reg3_MA ++ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), ++ !strconcat(opstr, "\t$fd, $fj, $fk"), ++ [(set RO:$fd, (OpNode (fabs RO:$fj), (fabs RO:$fk)))], ++ FrmR, opstr>; ++ ++class Float_Int_Reg3 ++ : InstForm<(outs RD:$fd), (ins RS:$rj, RS:$rk), ++ !strconcat(opstr, "\t$fd, $rj, $rk"), ++ [(set RS:$fd, (OpNode RS:$rj, RS:$rk))], ++ FrmR, opstr>; ++ ++///R4 ++class Mul_Reg4 ++ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk, RO:$fa), ++ !strconcat(opstr, "\t$fd, $fj, $fk, $fa"), ++ [], ++ FrmFR, opstr>; ++ ++class NMul_Reg4 ++ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk, RO:$fa), ++ !strconcat(opstr, "\t$fd, $fj, $fk, $fa"), ++ [], ++ FrmFR, opstr>; ++ ++///R2_IMM5 ++class Shift_Imm32 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm5:$imm5), ++ !strconcat(opstr, "\t$rd, $rj, $imm5"), ++ [(set RO:$rd, (OpNode RO:$rj, uimm5:$imm5))], ++ FrmR, opstr>; ++ ++///R2_IMM6 ++class Shift_Imm64 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm6:$imm6), ++ !strconcat(opstr, "\t$rd, $rj, $imm6"), ++ [(set RO:$rd, (OpNode RO:$rj, uimm6:$imm6))], ++ FrmR, opstr>; ++ ++///LOAD_STORE ++class FLd ++ : InstForm<(outs RD:$rd), (ins MO:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [(set RD:$rd, (OpNode addrDefault:$addr))], ++ FrmR, opstr> { ++ let DecoderMethod = "DecodeFMem"; ++ let mayLoad = 1; ++} ++ ++class Ld ++ : InstForm<(outs RD:$rd), (ins MO:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [(set RD:$rd, (OpNode Addr:$addr))], ++ FrmR, opstr> { ++ let DecoderMethod = "DecodeMem"; ++ let canFoldAsLoad = 1; ++ string BaseOpcode = opstr; ++ let mayLoad = 1; ++} ++ ++class FSt ++ : InstForm<(outs), (ins RD:$rd, MO:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [(OpNode RD:$rd, addrDefault:$addr)], ++ FrmR, opstr> { ++ let DecoderMethod = "DecodeFMem"; ++ let mayStore = 1; ++} ++ ++class St ++ : InstForm<(outs), (ins RS:$rd, MO:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [(OpNode RS:$rd, addr:$addr)], ++ FrmR, opstr> { ++ let DecoderMethod = "DecodeMem"; ++ string BaseOpcode = opstr; ++ let mayStore = 1; ++} ++ ++/// R2_IMM12 ++class Int_Reg2_Imm12 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$imm12), ++ !strconcat(opstr, "\t$rd, $rj, $imm12"), ++ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$imm12))], ++ FrmR, opstr>; ++class RELOC_rrii ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$imm12, ImmOpnd:$i12), ++ !strconcat(opstr, "\t$rd, $rj, $imm12"), ++ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$imm12, ImmOpnd:$i12))], ++ FrmR, opstr>; ++ ++///R2_IMM14 ++class LdPtr ++ : InstForm<(outs RO:$rd), (ins mem_simm14_lsl2:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [], FrmI, opstr>{ ++ let DecoderMethod = "DecodeMemSimm14"; ++ let canFoldAsLoad = 1; ++ string BaseOpcode = opstr; ++ let mayLoad = 1; ++} ++ ++class StPtr ++ : InstForm<(outs), (ins RO:$rd, mem_simm14_lsl2:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [], FrmI, opstr> { ++ let DecoderMethod = "DecodeMemSimm14"; ++ string BaseOpcode = opstr; ++ let mayStore = 1; + } +-class BrCCZ_1RI21 op, string opstr> +- : Fmt1RI21 { +- let isBranch = 1; ++ ++///R2_IMM16 ++class FJirl ++ : InstForm<(outs RO:$rd), (ins RO:$rj, opnd:$offs16), ++ !strconcat(opstr, "\t$rd, $rj, $offs16"), ++ [], FrmJ, opstr>; ++ ++class Beq ++ : InstForm<(outs), (ins RO:$rj, RO:$rd, opnd:$offs16), ++ !strconcat(opstr, "\t$rj, $rd, $offs16"), ++ [(brcond (i32 (cond_op RO:$rj, RO:$rd)), bb:$offs16)], ++ FrmI, opstr> { ++ let isBranch = 1; ++ let isTerminator = 1; ++ bit isCTI = 1; ++} ++ ++///R1_IMM21 ++class Beqz ++ : InstForm<(outs), (ins RO:$rj, opnd:$offs21), ++ !strconcat(opstr, "\t$rj, $offs21"), ++ [(brcond (i32 (cond_op RO:$rj, 0)), bb:$offs21)], ++ FrmI, opstr> { ++ let isBranch = 1; ++ let isTerminator = 1; ++ bit isCTI = 1; ++} ++ ++///IMM26 ++class JumpFB : ++ InstForm<(outs), (ins opnd:$offset26), !strconcat(opstr, "\t$offset26"), ++ [(operator targetoperator:$offset26)], FrmJ, opstr> { ++ let isBranch = 1; ++ let isTerminator=1; ++ let isBarrier=1; ++ let DecoderMethod = "DecodeJumpTarget"; ++ bit isCTI = 1; ++} ++ ++/// R3_SA ++class Reg3_Sa ++ : InstForm<(outs RO:$rd), (ins RO:$rj, RO:$rk, ImmOpnd:$sa), ++ !strconcat(opstr, "\t$rd, $rj, $rk, $sa"), ++ [(set RO:$rd, (OpNode RO:$rj, RO:$rk, ImmOpnd:$sa))], ++ FrmR, opstr>; ++ ++class Reg3_SaU ++ : InstForm<(outs RD:$rd), (ins RS:$rj, RS:$rk, ImmOpnd:$sa), ++ !strconcat(opstr, "\t$rd, $rj, $rk, $sa"), ++ [(set RD:$rd, (OpNode RS:$rj, RS:$rk, ImmOpnd:$sa))], ++ FrmR, opstr>; ++ ++/// Assert ++class Assert ++ : InstForm<(outs), (ins RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$rj, $rk"), ++ [(set (OpNode RO:$rj, RO:$rk))], ++ FrmR, opstr>; ++ ++class Code15 ++ : InstForm<(outs), (ins uimm15:$Code), ++ !strconcat(opstr, "\t$Code"), ++ [(set (OpNode uimm15:$Code))], ++ FrmOther, opstr>; ++ ++class TrapBase ++ : LoongArchPseudo<(outs), (ins), [(trap)]>, ++ PseudoInstExpansion<(RealInst 0)> { ++ let isBarrier = 1; ++ let isTerminator = 1; ++ let isCodeGenOnly = 1; ++ let isCTI = 1; ++} ++ ++class CSR ++ : InstForm<(outs RO:$rd), (ins ImmOpnd:$csr), ++ !strconcat(opstr, "\t$rd, $csr"), ++ [(set RO:$rd, (OpNode ImmOpnd:$csr))], ++ FrmOther, opstr>; ++ ++class CSRW ++ : InstForm<(outs RO:$dst), (ins RO:$rd, ImmOpnd:$csr), ++ !strconcat(opstr, "\t$rd, $csr"), ++ [(set RO:$dst, (OpNode RO:$rd, ImmOpnd:$csr))], ++ FrmOther, opstr>{ ++ let Constraints = "$rd = $dst"; ++} ++ ++class CSRX ++ : InstForm<(outs RO:$dst), (ins RO:$rd, RO:$rj, ImmOpnd:$csr), ++ !strconcat(opstr, "\t$rd, $rj, $csr"), ++ [(set RO:$dst, (OpNode RO:$rd, RO:$rj, ImmOpnd:$csr))], ++ FrmOther, opstr>{ ++ let Constraints = "$rd = $dst"; ++} ++ ++class CAC ++ : InstForm<(outs), (ins uimm5:$op, RO:$rj, ImmOpnd:$si12), ++ !strconcat(opstr, "\t$op, $rj, $si12"), ++ [(set (OpNode uimm5:$op, RO:$rj, ImmOpnd:$si12))], ++ FrmOther, opstr>; ++ ++class LEVEL ++ : InstForm<(outs RO:$rd), (ins RO:$rj, uimm8_64:$level), ++ !strconcat(opstr, "\t$rd, $rj, $level"), ++ [(set RO:$rd, (OpNode RO:$rj, uimm8_64:$level))], ++ FrmOther, opstr>; ++ ++class SEQ ++ : InstForm<(outs), (ins RO:$rj, uimm8_64:$seq), ++ !strconcat(opstr, "\t$rj, $seq"), ++ [(set (OpNode RO:$rj, uimm8_64:$seq))], ++ FrmOther, opstr>; ++ ++class Wait ++ : InstForm<(outs), (ins uimm15:$hint), ++ !strconcat(opstr, "\t$hint"), ++ [(set (OpNode uimm15:$hint))], ++ FrmOther, opstr>; ++ ++class Invtlb ++ : InstForm<(outs), (ins uimm5:$op, RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$op, $rj, $rk"), ++ [(set (OpNode uimm5:$op, RO:$rj, RO:$rk))], ++ FrmOther, opstr>; ++ ++class OP32 ++ : InstForm<(outs), (ins), ++ !strconcat(opstr, ""), ++ [(set (OpNode))], ++ FrmOther, opstr>; ++ ++class Bar ++ : InstForm<(outs), (ins uimm15:$hint), ++ !strconcat(opstr, "\t$hint"), ++ [(set (OpNode uimm15:$hint))], ++ FrmOther, opstr>; ++ ++//class CA op, string opstr> ++// : R3_CA; ++ ++class SI16_R2 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, simm16:$si16), ++ !strconcat(opstr, "\t$rd, $rj, $si16"), ++ [(set RO:$rd, (OpNode RO:$rj, simm16:$si16))], ++ FrmR, opstr>; ++ ++class SI20 ++ : InstForm<(outs RO:$rd), (ins ImmOpnd:$si20), ++ !strconcat(opstr, "\t$rd, $si20"), ++ [(set RO:$rd, (OpNode ImmOpnd:$si20))], ++ FrmR, opstr>; ++let isCodeGenOnly = 1, Constraints = "$dst = $rd" in ++class SI20_R2 ++ : InstForm<(outs RO:$dst), (ins RO:$rd, ImmOpnd:$si20), ++ !strconcat(opstr, "\t$rd, $si20"), ++ [(set RO:$dst, (OpNode RO:$rd, ImmOpnd:$si20))], ++ FrmR, opstr>; ++class RELOC_rii ++ : InstForm<(outs RO:$rd), (ins ImmOpnd:$si20, ImmOpnd:$i20), ++ !strconcat(opstr, "\t$rd, $si20"), ++ [(set RO:$rd, (OpNode ImmOpnd:$si20, ImmOpnd:$i20))], ++ FrmR, opstr>; ++ ++// preld ++class Preld ++ : InstForm<(outs), (ins RO:$rj, MemOpnd:$addr, uimm5:$hint), ++ !strconcat(opstr, "\t$hint, $rj, $addr"), ++ [(set (OpNode RO:$rj, MemOpnd:$addr, uimm5:$hint))], ++ FrmR, opstr>; ++class Preld_Raw ++ : InstForm<(outs), (ins RO:$rj, simm12:$imm12, uimm5:$hint), ++ !strconcat(opstr, "\t$hint, $rj, $imm12"), ++ [], ++ FrmR, opstr>; ++class IsCall { ++ bit isCall = 1; ++ bit isCTI = 1; ++} ++ ++class EffectiveAddress ++ : InstForm<(outs RO:$rd), (ins mem_ea:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), ++ [(set RO:$rd, addr:$addr)], FrmI, ++ !strconcat(opstr, "_lea")> { ++ let isCodeGenOnly = 1; ++ let hasNoSchedulingInfo = 1; ++ let DecoderMethod = "DecodeMem"; ++} ++ ++def PtrRC : Operand { ++ let MIOperandInfo = (ops ptr_rc); ++ let DecoderMethod = "DecodePtrRegisterClass"; ++ let ParserMatchClass = GPR32AsmOperand; ++} ++ ++class Atomic2Ops : ++ LoongArchPseudo<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), ++ [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; ++ ++class Atomic2OpsPostRA : ++ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { ++ let mayLoad = 1; ++ let mayStore = 1; ++} ++ ++class Atomic2OpsSubwordPostRA : ++ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, ++ RC:$shiftamnt), []>; ++class AtomicCmpSwap : ++ LoongArchPseudo<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), ++ [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; ++ ++class AtomicCmpSwapPostRA : ++ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { ++ let mayLoad = 1; ++ let mayStore = 1; ++} ++ ++class AtomicCmpSwapSubwordPostRA : ++ LoongArchPseudo<(outs RC:$dst), (ins PtrRC:$ptr, RC:$mask, RC:$ShiftCmpVal, ++ RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> { ++ let mayLoad = 1; ++ let mayStore = 1; ++} ++ ++class LoongArchInstAlias : ++ InstAlias, PredicateControl; ++ ++//===---------------------------------------------------------------------===/ ++// Instruction Definitions. ++//===---------------------------------------------------------------------===/ ++/// ++/// R2 ++/// ++ ++def CLO_D : Count1<"clo.d", GPR64Opnd, ctlz>, R2I<0b01000>; ++def CLZ_D : Int_Reg2<"clz.d", GPR64Opnd, ctlz>, R2I<0b01001>; ++def CTO_D : Count1<"cto.d", GPR64Opnd, cttz>, R2I<0b01010>; ++def CTZ_D : Int_Reg2<"ctz.d", GPR64Opnd, cttz>, R2I<0b01011>; ++ ++def REVB_4H : Int_Reg2<"revb.4h", GPR64Opnd>, R2I<0b01101>; //[] ++def REVB_2W : Int_Reg2<"revb.2w", GPR64Opnd>, R2I<0b01110>; ++def REVB_D : Int_Reg2<"revb.d", GPR64Opnd>, R2I<0b01111>; ++def REVH_2W : Int_Reg2<"revh.2w", GPR64Opnd>, R2I<0b10000>; ++def REVH_D : Int_Reg2<"revh.d", GPR64Opnd>, R2I<0b10001>; //[] ++ ++def BITREV_8B : Int_Reg2<"bitrev.8b", GPR64Opnd>, R2I<0b10011>; //[] ++def BITREV_D : Int_Reg2<"bitrev.d", GPR64Opnd, bitreverse>, R2I<0b10101>; ++ ++def EXT_W_H : SignExtInReg<"ext.w.h", GPR64Opnd, i16>, R2I<0b10110>; ++def EXT_W_B : SignExtInReg<"ext.w.b", GPR64Opnd, i8>, R2I<0b10111>; ++ ++def RDTIME_D : Int_Reg2_Rdtime<"rdtime.d", GPR64Opnd>, R2I<0b11010>; ++def RDTIMEL_W : Int_Reg2_Rdtime<"rdtimel.w", GPR64Opnd>, R2I<0b11000>; ++def RDTIMEH_W : Int_Reg2_Rdtime<"rdtimeh.w", GPR64Opnd>, R2I<0b11001>; ++/// ++/// R3 ++/// ++def ADD_D : Int_Reg3<"add.d", GPR64Opnd, add>, R3I<0b0100001>; ++def SUB_D : Int_Reg3<"sub.d", GPR64Opnd, sub>, R3I<0b0100011>; ++ ++def SLT : SetCC_R<"slt", GPR64Opnd, setlt>, R3I<0b0100100>; ++def SLTU : SetCC_R<"sltu", GPR64Opnd, setult>, R3I<0b0100101>; ++def MASKEQZ : Int_Reg3<"maskeqz", GPR64Opnd>, R3I<0b0100110>; //[] ++def MASKNEZ : Int_Reg3<"masknez", GPR64Opnd>, R3I<0b0100111>; //[] ++ ++def NOR : Nor<"nor", GPR64Opnd>, R3I<0b0101000>; ++def AND : Int_Reg3<"and", GPR64Opnd, and>, R3I<0b0101001>; ++def OR : Int_Reg3<"or", GPR64Opnd, or>, R3I<0b0101010>; ++def XOR : Int_Reg3<"xor", GPR64Opnd, xor>, R3I<0b0101011>; ++def ORN : Int_Reg3<"orn", GPR64Opnd>, R3I<0b0101100>; ++def ANDN : Int_Reg3<"andn", GPR64Opnd>, R3I<0b0101101>; ++ ++def SLL_D : Shift_Var<"sll.d", GPR64Opnd, shl>, R3I<0b0110001>; ++def SRL_D : Shift_Var<"srl.d", GPR64Opnd, srl>, R3I<0b0110010>; ++def SRA_D : Shift_Var<"sra.d", GPR64Opnd, sra>, R3I<0b0110011>; ++def ROTR_D: Shift_Var<"rotr.d", GPR64Opnd, rotr>, R3I<0b0110111>; ++ ++def MUL_D : Int_Reg3<"mul.d", GPR64Opnd, mul>, R3I<0b0111011>; ++def MULH_D : Int_Reg3<"mulh.d", GPR64Opnd, mulhs>, R3I<0b0111100>; ++def MULH_DU : Int_Reg3<"mulh.du", GPR64Opnd, mulhu>, R3I<0b0111101>; ++def MULW_D_W : Int_Reg3<"mulw.d.w", GPR64Opnd>, R3I<0b0111110>; ++def MULW_D_WU : Int_Reg3<"mulw.d.wu", GPR64Opnd>, R3I<0b0111111>; ++ ++let usesCustomInserter = 1 in { ++def DIV_D : Int_Reg3<"div.d", GPR64Opnd, sdiv>, R3I<0b1000100>; ++def MOD_D : Int_Reg3<"mod.d", GPR64Opnd, srem>, R3I<0b1000101>; ++def DIV_DU : Int_Reg3<"div.du", GPR64Opnd, udiv>, R3I<0b1000110>; ++def MOD_DU : Int_Reg3<"mod.du", GPR64Opnd, urem>, R3I<0b1000111>; ++} ++ ++def CRC_W_D_W : Int_Reg3_Crc<"crc.w.d.w", GPR64Opnd, GPR32Opnd, int_loongarch_crc_w_d_w>, R3I<0b1001011>; ++def CRCC_W_D_W : Int_Reg3_Crc<"crcc.w.d.w", GPR64Opnd, GPR32Opnd, int_loongarch_crcc_w_d_w>, R3I<0b1001111>; ++/// ++/// SLLI ++/// ++def SLLI_D : Shift_Imm64<"slli.d", GPR64Opnd, shl>, R2_IMM6<0b00>; ++def SRLI_D : Shift_Imm64<"srli.d", GPR64Opnd, srl>, R2_IMM6<0b01>; ++def SRAI_D : Shift_Imm64<"srai.d", GPR64Opnd, sra>, R2_IMM6<0b10>; ++def ROTRI_D : Shift_Imm64<"rotri.d", GPR64Opnd, rotr>, R2_IMM6<0b11>; ++/// ++/// Misc ++/// ++def ALSL_WU : Reg3_SaU<"alsl.wu", GPR64Opnd, GPR32Opnd, uimm2_plus1>, R3_SA2<0b00011> { ++ let Pattern = [(set GPR64Opnd:$rd, ++ (i64 (zext (add GPR32Opnd:$rk, (shl GPR32Opnd:$rj, immZExt2Alsl:$sa)))))]; ++} ++ ++def ALSL_D : Reg3_Sa<"alsl.d", GPR64Opnd, uimm2_plus1>, R3_SA2<0b10110> { ++ let Pattern = [(set GPR64Opnd:$rd, ++ (add GPR64Opnd:$rk, (shl GPR64Opnd:$rj, immZExt2Alsl:$sa)))]; ++} ++def BYTEPICK_D : Reg3_Sa<"bytepick.d", GPR64Opnd, uimm3>, R3_SA3; //[] ++ ++def ASRTLE_D : Assert<"asrtle.d", GPR64Opnd, int_loongarch_asrtle_d>, ASSERT<0b10>; ++def ASRTGT_D : Assert<"asrtgt.d", GPR64Opnd, int_loongarch_asrtgt_d>, ASSERT<0b11>; ++ ++def DBCL : Code15<"dbcl">, CODE15<0b1010101>; ++def HYPCALL : Code15<"hypcall">, CODE15<0b1010111>; ++ ++/// ++/// R2_IMM12 ++/// ++def SLTI : SetCC_I<"slti", GPR64Opnd, simm12, setlt>, R2_IMM12<0b000>; ++def SLTUI : SetCC_I<"sltui", GPR64Opnd, simm12, setult>, R2_IMM12<0b001>; ++def ADDI_W64 : Int_Reg2_Imm12<"addi.w", GPR64Opnd, simm12>, R2_IMM12<0b010>; ++def ADDI_D : Int_Reg2_Imm12<"addi.d", GPR64Opnd, simm12, add>, R2_IMM12<0b011>; ++def LU52I_D : Int_Reg2_Imm12<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; ++def ANDI : Int_Reg2_Imm12<"andi", GPR64Opnd, uimm12, and>, R2_IMM12<0b101>; ++def ORI : Int_Reg2_Imm12<"ori", GPR64Opnd, uimm12, or>, R2_IMM12<0b110>; ++def XORI : Int_Reg2_Imm12<"xori", GPR64Opnd, uimm12, xor>, R2_IMM12<0b111>; ++ ++/// ++/// Privilege Instructions ++/// ++def CSRRD : CSR<"csrrd", GPR64Opnd, uimm14, int_loongarch_csrrd_d>, R1_CSR<0b0000000000100>; ++def CSRWR : CSRW<"csrwr", GPR64Opnd, uimm14, int_loongarch_csrwr_d>, R1_CSR<0b0000100000100>; ++def CSRXCHG : CSRX<"csrxchg", GPR64Opnd, uimm14, int_loongarch_csrxchg_d>, R2_CSR<0b00000100>; ++def IOCSRRD_D : Int_Reg2_Iocsrrd<"iocsrrd.d", GPR64Opnd, GPR32Opnd, int_loongarch_iocsrrd_d>, R2P<0b011>; ++def IOCSRWR_D : Int_Reg2_Iocsrwr<"iocsrwr.d", GPR64Opnd, GPR32Opnd, int_loongarch_iocsrwr_d>, R2P<0b111>; ++def CACOP : CAC<"cacop", GPR64Opnd, simm12, int_loongarch_cacop_d>, R1_CACHE; ++def LDDIR : LEVEL<"lddir", GPR64Opnd>, R2_LEVEL<0b00000110010000>; ++def LDPTE : SEQ<"ldpte", GPR64Opnd>, R1_SEQ<0b00000110010001>; ++ ++def IDLE : Wait<"idle">, WAIT_FM; ++def INVTLB : Invtlb<"invtlb", GPR64Opnd>, R2_INVTLB; ++// ++def IOCSRRD_B : Int_Reg2<"iocsrrd.b", GPR64Opnd>, R2P<0b000>; ++def IOCSRRD_H : Int_Reg2<"iocsrrd.h", GPR64Opnd>, R2P<0b001>; ++def IOCSRRD_W : Int_Reg2<"iocsrrd.w", GPR64Opnd>, R2P<0b010>; ++// ++def TLBCLR : OP32<"tlbclr", int_loongarch_tlbclr>, IMM32<0b001000>; ++def TLBFLUSH : OP32<"tlbflush", int_loongarch_tlbflush>, IMM32<0b001001>; ++def TLBSRCH : OP32<"tlbsrch", int_loongarch_tlbsrch>, IMM32<0b001010>; ++def TLBRD : OP32<"tlbrd", int_loongarch_tlbrd>, IMM32<0b001011>; ++def TLBWR : OP32<"tlbwr", int_loongarch_tlbwr>, IMM32<0b001100>; ++def TLBFILL : OP32<"tlbfill", int_loongarch_tlbfill>, IMM32<0b001101>; ++def ERTN : OP32<"ertn">, IMM32<0b001110>; ++ ++/// ++/// R1_IMM20 ++/// ++def ADDU16I_D : SI16_R2<"addu16i.d", GPR64Opnd>, R2_SI16<0b000100>; ++def LU12I_W : SI20<"lu12i.w", GPR64Opnd, simm20>, R1_SI20<0b0001010>; ++def LU32I_D : SI20<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; ++def LU32I_D_R2 : SI20_R2<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; ++def PCADDI : SI20<"pcaddi", GPR64Opnd, simm20>, R1_SI20<0b0001100>; ++def PCALAU12I : SI20<"pcalau12i", GPR64Opnd, simm20>, R1_SI20<0b0001101>; ++def PCADDU12I : SI20<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; ++def PCADDU18I : SI20<"pcaddu18i", GPR64Opnd, simm20>, R1_SI20<0b0001111>; ++ ++ ++def BEQZ : Beqz<"beqz", brtarget, seteq, GPR64Opnd>, R1_IMM21BEQZ<0b010000>; ++def BNEZ : Beqz<"bnez", brtarget, setne, GPR64Opnd>, R1_IMM21BEQZ<0b010001>; ++ ++def JIRL : FJirl<"jirl", simm16, GPR64Opnd>, R2_IMM16JIRL; ++let isCall = 1, isCTI=1, isCodeGenOnly = 1 in { ++def JIRL_CALL : FJirl<"jirl", simm16, GPR64Opnd>, R2_IMM16JIRL; ++} ++ ++def B : JumpFB, IMM26B<0b010100>; ++ ++def BEQ : Beq<"beq", brtarget, seteq, GPR64Opnd>, R2_IMM16BEQ<0b010110>; ++def BNE : Beq<"bne", brtarget, setne, GPR64Opnd>, R2_IMM16BEQ<0b010111>; ++def BLT : Beq<"blt", brtarget, setlt, GPR64Opnd>, R2_IMM16BEQ<0b011000>; ++def BGE : Beq<"bge", brtarget, setge, GPR64Opnd>, R2_IMM16BEQ<0b011001>; ++def BLTU : Beq<"bltu", brtarget, setult, GPR64Opnd>, R2_IMM16BEQ<0b011010>; ++def BGEU : Beq<"bgeu", brtarget, setuge, GPR64Opnd>, R2_IMM16BEQ<0b011011>; ++ ++/// ++/// Mem access ++/// ++class LLBase : ++ InstForm<(outs RO:$rd), (ins MO:$addr), !strconcat(opstr, "\t$rd, $addr"), ++ [], FrmI, opstr> { ++ let DecoderMethod = "DecodeMemSimm14"; ++ let mayLoad = 1; ++} ++ ++class SCBase : ++ InstForm<(outs RO:$dst), (ins RO:$rd, MO:$addr), ++ !strconcat(opstr, "\t$rd, $addr"), [], FrmI> { ++ let DecoderMethod = "DecodeMemSimm14"; ++ let mayStore = 1; ++ let Constraints = "$rd = $dst"; ++} ++ ++class STGT_LE : ++ InstForm<(outs), (ins RO:$rd, RO:$rj, RO:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [], FrmI, opstr>; ++ ++class Float_STGT_LE ++ : InstForm<(outs), (ins RD:$fd, RS:$rj, RS:$rk), ++ !strconcat(opstr, "\t$fd, $rj, $rk"), ++ [], FrmR, opstr>; ++ ++def LL_D : LLBase<"ll.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b010>; ++def SC_D : SCBase<"sc.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b011>; ++ ++def LDPTR_W : LdPtr<"ldptr.w", GPR64Opnd>, LL_SC<0b100>; ++def STPTR_W : StPtr<"stptr.w", GPR64Opnd>, LL_SC<0b101>; ++def LDPTR_D : LdPtr<"ldptr.d", GPR64Opnd>, LL_SC<0b110>; ++def STPTR_D : StPtr<"stptr.d", GPR64Opnd>, LL_SC<0b111>; ++ ++def LD_B : Ld<"ld.b", GPR64Opnd, mem, sextloadi8>, LOAD_STORE<0b0000>; ++def LD_H : Ld<"ld.h", GPR64Opnd, mem, sextloadi16>, LOAD_STORE<0b0001>; ++def LD_W : Ld<"ld.w", GPR64Opnd, mem, sextloadi32>, LOAD_STORE<0b0010>; ++def LD_D : Ld<"ld.d", GPR64Opnd, mem_simmptr, load>, LOAD_STORE<0b0011>; ++def ST_B : St<"st.b", GPR64Opnd, mem, truncstorei8>, LOAD_STORE<0b0100>; ++def ST_H : St<"st.h", GPR64Opnd, mem, truncstorei16>, LOAD_STORE<0b0101>; ++def ST_W : St<"st.w", GPR64Opnd, mem, truncstorei32>, LOAD_STORE<0b0110>; ++def ST_D : St<"st.d", GPR64Opnd, mem_simmptr, store>, LOAD_STORE<0b0111>; ++def LD_BU : Ld<"ld.bu", GPR64Opnd, mem, zextloadi8>, LOAD_STORE<0b1000>; ++def LD_HU : Ld<"ld.hu", GPR64Opnd, mem, zextloadi16>, LOAD_STORE<0b1001>; ++def LD_WU : Ld<"ld.wu", GPR64Opnd, mem, zextloadi32>, LOAD_STORE<0b1010>; ++ ++def AMSWAP_W : ATOMIC<"amswap.w", GPR32Opnd, amem>, AM<0b000000>; ++def AMSWAP_D : ATOMIC<"amswap.d", GPR64Opnd, amem>, AM<0b000001>; ++def AMADD_W : ATOMIC<"amadd.w", GPR32Opnd, amem>, AM<0b000010>; ++def AMADD_D : ATOMIC<"amadd.d", GPR64Opnd, amem>, AM<0b000011>; ++def AMAND_W : ATOMIC<"amand.w", GPR32Opnd, amem>, AM<0b000100>; ++def AMAND_D : ATOMIC<"amand.d", GPR64Opnd, amem>, AM<0b000101>; ++def AMOR_W : ATOMIC<"amor.w", GPR32Opnd, amem>, AM<0b000110>; ++def AMOR_D : ATOMIC<"amor.d", GPR64Opnd, amem>, AM<0b000111>; ++def AMXOR_W : ATOMIC<"amxor.w", GPR32Opnd, amem>, AM<0b001000>; ++def AMXOR_D : ATOMIC<"amxor.d", GPR64Opnd, amem>, AM<0b001001>; ++def AMMAX_W : ATOMIC<"ammax.w", GPR32Opnd, amem>, AM<0b001010>; ++def AMMAX_D : ATOMIC<"ammax.d", GPR64Opnd, amem>, AM<0b001011>; ++def AMMIN_W : ATOMIC<"ammin.w", GPR32Opnd, amem>, AM<0b001100>; ++def AMMIN_D : ATOMIC<"ammin.d", GPR64Opnd, amem>, AM<0b001101>; ++def AMMAX_WU : ATOMIC<"ammax.wu", GPR32Opnd, amem>, AM<0b001110>; ++def AMMAX_DU : ATOMIC<"ammax.du", GPR64Opnd, amem>, AM<0b001111>; ++def AMMIN_WU : ATOMIC<"ammin.wu", GPR32Opnd, amem>, AM<0b010000>; ++def AMMIN_DU : ATOMIC<"ammin.du", GPR64Opnd, amem>, AM<0b010001>; ++ ++ ++def AMSWAP_DB_W : ATOMIC<"amswap_db.w", GPR32Opnd, amem>, AM<0b010010>; ++def AMSWAP_DB_D : ATOMIC<"amswap_db.d", GPR64Opnd, amem>, AM<0b010011>; ++def AMADD_DB_W : ATOMIC<"amadd_db.w", GPR32Opnd, amem>, AM<0b010100>; ++def AMADD_DB_D : ATOMIC<"amadd_db.d", GPR64Opnd, amem>, AM<0b010101>; ++def AMAND_DB_W : ATOMIC<"amand_db.w", GPR32Opnd, amem>, AM<0b010110>; ++def AMAND_DB_D : ATOMIC<"amand_db.d", GPR64Opnd, amem>, AM<0b010111>; ++def AMOR_DB_W : ATOMIC<"amor_db.w", GPR32Opnd, amem>, AM<0b011000>; ++def AMOR_DB_D : ATOMIC<"amor_db.d", GPR64Opnd, amem>, AM<0b011001>; ++def AMXOR_DB_W : ATOMIC<"amxor_db.w", GPR32Opnd, amem>, AM<0b011010>; ++def AMXOR_DB_D : ATOMIC<"amxor_db.d", GPR64Opnd, amem>, AM<0b011011>; ++def AMMAX_DB_W : ATOMIC<"ammax_db.w", GPR32Opnd, amem>, AM<0b011100>; ++def AMMAX_DB_D : ATOMIC<"ammax_db.d", GPR64Opnd, amem>, AM<0b011101>; ++def AMMIN_DB_W : ATOMIC<"ammin_db.w", GPR32Opnd, amem>, AM<0b011110>; ++def AMMIN_DB_D : ATOMIC<"ammin_db.d", GPR64Opnd, amem>, AM<0b011111>; ++def AMMAX_DB_WU : ATOMIC<"ammax_db.wu", GPR32Opnd, amem>, AM<0b100000>; ++def AMMAX_DB_DU : ATOMIC<"ammax_db.du", GPR64Opnd, amem>, AM<0b100001>; ++def AMMIN_DB_WU : ATOMIC<"ammin_db.wu", GPR32Opnd, amem>, AM<0b100010>; ++def AMMIN_DB_DU : ATOMIC<"ammin_db.du", GPR64Opnd, amem>, AM<0b100011>; ++ ++def LDGT_B : Int_Reg3<"ldgt.b", GPR64Opnd>, R3MI<0b11110000>; ++def LDGT_H : Int_Reg3<"ldgt.h", GPR64Opnd>, R3MI<0b11110001>; ++def LDGT_W : Int_Reg3<"ldgt.w", GPR64Opnd>, R3MI<0b11110010>; ++def LDGT_D : Int_Reg3<"ldgt.d", GPR64Opnd>, R3MI<0b11110011>; ++def LDLE_B : Int_Reg3<"ldle.b", GPR64Opnd>, R3MI<0b11110100>; ++def LDLE_H : Int_Reg3<"ldle.h", GPR64Opnd>, R3MI<0b11110101>; ++def LDLE_W : Int_Reg3<"ldle.w", GPR64Opnd>, R3MI<0b11110110>; ++def LDLE_D : Int_Reg3<"ldle.d", GPR64Opnd>, R3MI<0b11110111>; ++def STGT_B : STGT_LE<"stgt.b", GPR64Opnd>, R3MI<0b11111000>; ++def STGT_H : STGT_LE<"stgt.h", GPR64Opnd>, R3MI<0b11111001>; ++def STGT_W : STGT_LE<"stgt.w", GPR64Opnd>, R3MI<0b11111010>; ++def STGT_D : STGT_LE<"stgt.d", GPR64Opnd>, R3MI<0b11111011>; ++def STLE_B : STGT_LE<"stle.b", GPR64Opnd>, R3MI<0b11111100>; ++def STLE_H : STGT_LE<"stle.h", GPR64Opnd>, R3MI<0b11111101>; ++def STLE_W : STGT_LE<"stle.w", GPR64Opnd>, R3MI<0b11111110>; ++def STLE_D : STGT_LE<"stle.d", GPR64Opnd>, R3MI<0b11111111>; ++ ++let isCodeGenOnly = 1 in { ++def PRELD : Preld<"preld", mem, GPR64Opnd>, PRELD_FM; ++} ++ ++def PRELD_Raw : Preld_Raw<"preld", GPR64Opnd>, PRELD_FM; ++ ++let isCall=1, isCTI=1, Defs = [RA] in { ++ class JumpLink : ++ InstForm<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), ++ [(LoongArchJmpLink tglobaladdr:$target)], FrmJ, opstr> { ++ let DecoderMethod = "DecodeJumpTarget"; ++ } ++} ++def LONG_BRANCH_PCADDU12I : LoongArchPseudo<(outs GPR64Opnd:$dst), ++ (ins brtarget:$tgt), []>, GPR_64; ++ ++def LONG_BRANCH_ADDID2Op : LoongArchPseudo<(outs GPR64Opnd:$dst), ++ (ins GPR64Opnd:$src, brtarget:$tgt), []>, GPR_64; ++ ++def LONG_BRANCH_ADDID : LoongArchPseudo<(outs GPR64Opnd:$dst), ++ (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64; ++ ++def LEA_ADDI_D: EffectiveAddress<"addi.d", GPR64Opnd>, LEA_ADDI_FM<0b011>, GPR_64; ++ ++class PseudoReturnBase : LoongArchPseudo<(outs), (ins RO:$rs), ++ []> { + let isTerminator = 1; ++ let isBarrier = 1; ++ let isReturn = 1; ++ let isCodeGenOnly = 1; ++ let hasCtrlDep = 1; ++ let hasExtraSrcRegAllocReq = 1; ++ bit isCTI = 1; ++} ++ ++def PseudoReturn64 : PseudoReturnBase; ++//def PseudoReturn : PseudoReturnBase; ++ ++ ++let isCall=1, isCTI=1, Defs=[RA], isCodeGenOnly=1 in { ++def PseudoCall : LoongArchPseudo<(outs), (ins calltarget:$target), ++ []>; + } +-class Br_I26 op, string opstr> +- : FmtI26 { +- let isBranch = 1; ++ ++let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in ++def PseudoTailCall : LoongArchPseudo<(outs), (ins calltarget:$target), ++ []>; ++ ++class PseudoTailBase : LoongArchPseudo<(outs), (ins opnd:$offset26), ++ []> { + let isTerminator = 1; ++ let isBarrier = 1; ++ let isReturn = 1; ++ let isCodeGenOnly = 1; + } ++def PseudoTailReturn : PseudoTailBase; + +-let mayLoad = 1 in { +-class LOAD_3R op, string opstr> +- : Fmt3R; +-class LOAD_2RI12 op, string opstr> +- : Fmt2RI12; +-class LOAD_2RI14 op, string opstr> +- : Fmt2RI14; +-} // mayLoad = 1 +- +-let mayStore = 1 in { +-class STORE_3R op, string opstr> +- : Fmt3R; +-class STORE_2RI12 op, string opstr> +- : Fmt2RI12; +-class STORE_2RI14 op, string opstr> +- : Fmt2RI14; +-} // mayStore = 1 +- +-let mayLoad = 1, mayStore = 1 in +-class AM_3R op, string opstr> +- : Fmt3R; +- +-let mayLoad = 1 in +-class LLBase op, string opstr> +- : Fmt2RI14; +- +-let mayStore = 1, Constraints = "$rd = $dst" in +-class SCBase op, string opstr> +- : Fmt2RI14; +- +-class IOCSRRD op, string opstr> +- : Fmt2R; +- +-class IOCSRWR op, string opstr> +- : Fmt2R; + +-//===----------------------------------------------------------------------===// +-// Basic Integer Instructions +-//===----------------------------------------------------------------------===// ++def : LoongArchPat<(LoongArchTailCall tglobaladdr:$dst), ++ (PseudoTailCall tglobaladdr:$dst)>; + +-// Arithmetic Operation Instructions +-def ADD_W : ALU_3R<0b00000000000100000, "add.w">; +-def SUB_W : ALU_3R<0b00000000000100010, "sub.w">; +-def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>; +-def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>; +-def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>; +-def SLT : ALU_3R<0b00000000000100100, "slt">; +-def SLTU : ALU_3R<0b00000000000100101, "sltu">; +-def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>; +-def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>; +-def PCADDI : ALU_1RI20<0b0001100, "pcaddi", simm20>; +-def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>; +-def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20>; +-def AND : ALU_3R<0b00000000000101001, "and">; +-def OR : ALU_3R<0b00000000000101010, "or">; +-def NOR : ALU_3R<0b00000000000101000, "nor">; +-def XOR : ALU_3R<0b00000000000101011, "xor">; +-def ANDN : ALU_3R<0b00000000000101101, "andn">; +-def ORN : ALU_3R<0b00000000000101100, "orn">; +-def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>; +-def ORI : ALU_2RI12<0b0000001110, "ori", uimm12>; +-def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>; +-def MUL_W : ALU_3R<0b00000000000111000, "mul.w">; +-def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">; +-def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">; +-let usesCustomInserter = true in { +-def DIV_W : ALU_3R<0b00000000001000000, "div.w">; +-def MOD_W : ALU_3R<0b00000000001000001, "mod.w">; +-def DIV_WU : ALU_3R<0b00000000001000010, "div.wu">; +-def MOD_WU : ALU_3R<0b00000000001000011, "mod.wu">; +-} // usesCustomInserter = true +- +-// Bit-shift Instructions +-def SLL_W : ALU_3R<0b00000000000101110, "sll.w">; +-def SRL_W : ALU_3R<0b00000000000101111, "srl.w">; +-def SRA_W : ALU_3R<0b00000000000110000, "sra.w">; +-def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">; +- +-def SLLI_W : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>; +-def SRLI_W : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>; +-def SRAI_W : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>; +-def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>; +- +-// Bit-manipulation Instructions +-def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">; +-def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">; +-def CLO_W : ALU_2R<0b0000000000000000000100, "clo.w">; +-def CLZ_W : ALU_2R<0b0000000000000000000101, "clz.w">; +-def CTO_W : ALU_2R<0b0000000000000000000110, "cto.w">; +-def CTZ_W : ALU_2R<0b0000000000000000000111, "ctz.w">; +-def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>; +-def REVB_2H : ALU_2R<0b0000000000000000001100, "revb.2h">; +-def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">; +-def BITREV_W : ALU_2R<0b0000000000000000010100, "bitrev.w">; +-let Constraints = "$rd = $dst" in { +-def BSTRINS_W : FmtBSTR_W<0b000000000110, (outs GPR:$dst), +- (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw), +- "bstrins.w", "$rd, $rj, $msbw, $lsbw">; +-} +-def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd), +- (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw), +- "bstrpick.w", "$rd, $rj, $msbw, $lsbw">; +-def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">; +-def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">; +- +-// Branch Instructions +-def BEQ : BrCC_2RI16<0b010110, "beq">; +-def BNE : BrCC_2RI16<0b010111, "bne">; +-def BLT : BrCC_2RI16<0b011000, "blt">; +-def BGE : BrCC_2RI16<0b011001, "bge">; +-def BLTU : BrCC_2RI16<0b011010, "bltu">; +-def BGEU : BrCC_2RI16<0b011011, "bgeu">; +-def BEQZ : BrCCZ_1RI21<0b010000, "beqz">; +-def BNEZ : BrCCZ_1RI21<0b010001, "bnez">; +-def B : Br_I26<0b010100, "b">; +- +-let isCall = 1 in +-def BL : FmtI26<0b010101, (outs), (ins simm26_lsl2:$imm26), "bl", "$imm26">; +-def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd), +- (ins GPR:$rj, simm16_lsl2:$imm16), "jirl", +- "$rd, $rj, $imm16">; +- +-// Common Memory Access Instructions +-def LD_B : LOAD_2RI12<0b0010100000, "ld.b">; +-def LD_H : LOAD_2RI12<0b0010100001, "ld.h">; +-def LD_W : LOAD_2RI12<0b0010100010, "ld.w">; +-def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">; +-def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">; +-def ST_B : STORE_2RI12<0b0010100100, "st.b">; +-def ST_H : STORE_2RI12<0b0010100101, "st.h">; +-def ST_W : STORE_2RI12<0b0010100110, "st.w">; +-def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld", +- "$imm5, $rj, $imm12">; +- +-// Atomic Memory Access Instructions +-def LL_W : LLBase<0b00100000, "ll.w">; +-def SC_W : SCBase<0b00100001, "sc.w">; +- +-// Barrier Instructions +-def DBAR : MISC_I15<0b00111000011100100, "dbar">; +-def IBAR : MISC_I15<0b00111000011100101, "ibar">; +- +-// Other Miscellaneous Instructions +-def SYSCALL : MISC_I15<0b00000000001010110, "syscall">; +-def BREAK : MISC_I15<0b00000000001010100, "break">; +-def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">; +-def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">; +-def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">; +- +-/// LA64 instructions +- +-let Predicates = [IsLA64] in { +- +-// Arithmetic Operation Instructions for 64-bits +-def ADD_D : ALU_3R<0b00000000000100001, "add.d">; +-def SUB_D : ALU_3R<0b00000000000100011, "sub.d">; +-def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>; +-def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>; +-def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>; +-def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>; +-let Constraints = "$rd = $dst" in { +-def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst), +- (ins GPR:$rd, simm20:$imm20), "lu32i.d", +- "$rd, $imm20">; +-} +-def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>; +-def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>; +-def MUL_D : ALU_3R<0b00000000000111011, "mul.d">; +-def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">; +-def MULH_DU : ALU_3R<0b00000000000111101, "mulh.du">; +-def MULW_D_W : ALU_3R<0b00000000000111110, "mulw.d.w">; +-def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">; +-let usesCustomInserter = true in { +-def DIV_D : ALU_3R<0b00000000001000100, "div.d">; +-def MOD_D : ALU_3R<0b00000000001000101, "mod.d">; +-def DIV_DU : ALU_3R<0b00000000001000110, "div.du">; +-def MOD_DU : ALU_3R<0b00000000001000111, "mod.du">; +-} // usesCustomInserter = true +- +-// Bit-shift Instructions for 64-bits +-def SLL_D : ALU_3R<0b00000000000110001, "sll.d">; +-def SRL_D : ALU_3R<0b00000000000110010, "srl.d">; +-def SRA_D : ALU_3R<0b00000000000110011, "sra.d">; +-def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">; +-def SLLI_D : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>; +-def SRLI_D : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>; +-def SRAI_D : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>; +-def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>; +- +-// Bit-manipulation Instructions for 64-bits +-def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">; +-def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">; +-def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">; +-def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">; +-def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>; +-def REVB_4H : ALU_2R<0b0000000000000000001101, "revb.4h">; +-def REVB_2W : ALU_2R<0b0000000000000000001110, "revb.2w">; +-def REVB_D : ALU_2R<0b0000000000000000001111, "revb.d">; +-def REVH_2W : ALU_2R<0b0000000000000000010000, "revh.2w">; +-def REVH_D : ALU_2R<0b0000000000000000010001, "revh.d">; +-def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">; +-def BITREV_D : ALU_2R<0b0000000000000000010101, "bitrev.d">; +-let Constraints = "$rd = $dst" in { +-def BSTRINS_D : FmtBSTR_D<0b0000000010, (outs GPR:$dst), +- (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), +- "bstrins.d", "$rd, $rj, $msbd, $lsbd">; +-} +-def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd), +- (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd), +- "bstrpick.d", "$rd, $rj, $msbd, $lsbd">; +- +-// Common Memory Access Instructions for 64-bits +-def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">; +-def LD_D : LOAD_2RI12<0b0010100011, "ld.d">; +-def ST_D : STORE_2RI12<0b0010100111, "st.d">; +-def LDX_B : LOAD_3R<0b00111000000000000, "ldx.b">; +-def LDX_H : LOAD_3R<0b00111000000001000, "ldx.h">; +-def LDX_W : LOAD_3R<0b00111000000010000, "ldx.w">; +-def LDX_D : LOAD_3R<0b00111000000011000, "ldx.d">; +-def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">; +-def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">; +-def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">; +-def STX_B : STORE_3R<0b00111000000100000, "stx.b">; +-def STX_H : STORE_3R<0b00111000000101000, "stx.h">; +-def STX_W : STORE_3R<0b00111000000110000, "stx.w">; +-def STX_D : STORE_3R<0b00111000000111000, "stx.d">; +-def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">; +-def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">; +-def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">; +-def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">; +-def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx", +- "$imm5, $rj, $rk">; +- +-// Bound Check Memory Access Instructions +-def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">; +-def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">; +-def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">; +-def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">; +-def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">; +-def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">; +-def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">; +-def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">; +-def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">; +-def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">; +-def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">; +-def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">; +-def STLE_B : STORE_3R<0b00111000011111100, "stle.b">; +-def STLE_H : STORE_3R<0b00111000011111101, "stle.h">; +-def STLE_W : STORE_3R<0b00111000011111110, "stle.w">; +-def STLE_D : STORE_3R<0b00111000011111111, "stle.d">; +- +-// Atomic Memory Access Instructions for 64-bits +-def AMSWAP_W : AM_3R<0b00111000011000000, "amswap.w">; +-def AMSWAP_D : AM_3R<0b00111000011000001, "amswap.d">; +-def AMADD_W : AM_3R<0b00111000011000010, "amadd.w">; +-def AMADD_D : AM_3R<0b00111000011000011, "amadd.d">; +-def AMAND_W : AM_3R<0b00111000011000100, "amand.w">; +-def AMAND_D : AM_3R<0b00111000011000101, "amand.d">; +-def AMOR_W : AM_3R<0b00111000011000110, "amor.w">; +-def AMOR_D : AM_3R<0b00111000011000111, "amor.d">; +-def AMXOR_W : AM_3R<0b00111000011001000, "amxor.w">; +-def AMXOR_D : AM_3R<0b00111000011001001, "amxor.d">; +-def AMMAX_W : AM_3R<0b00111000011001010, "ammax.w">; +-def AMMAX_D : AM_3R<0b00111000011001011, "ammax.d">; +-def AMMIN_W : AM_3R<0b00111000011001100, "ammin.w">; +-def AMMIN_D : AM_3R<0b00111000011001101, "ammin.d">; +-def AMMAX_WU : AM_3R<0b00111000011001110, "ammax.wu">; +-def AMMAX_DU : AM_3R<0b00111000011001111, "ammax.du">; +-def AMMIN_WU : AM_3R<0b00111000011010000, "ammin.wu">; +-def AMMIN_DU : AM_3R<0b00111000011010001, "ammin.du">; +-def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">; +-def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">; +-def AMADD_DB_W : AM_3R<0b00111000011010100, "amadd_db.w">; +-def AMADD_DB_D : AM_3R<0b00111000011010101, "amadd_db.d">; +-def AMAND_DB_W : AM_3R<0b00111000011010110, "amand_db.w">; +-def AMAND_DB_D : AM_3R<0b00111000011010111, "amand_db.d">; +-def AMOR_DB_W : AM_3R<0b00111000011011000, "amor_db.w">; +-def AMOR_DB_D : AM_3R<0b00111000011011001, "amor_db.d">; +-def AMXOR_DB_W : AM_3R<0b00111000011011010, "amxor_db.w">; +-def AMXOR_DB_D : AM_3R<0b00111000011011011, "amxor_db.d">; +-def AMMAX_DB_W : AM_3R<0b00111000011011100, "ammax_db.w">; +-def AMMAX_DB_D : AM_3R<0b00111000011011101, "ammax_db.d">; +-def AMMIN_DB_W : AM_3R<0b00111000011011110, "ammin_db.w">; +-def AMMIN_DB_D : AM_3R<0b00111000011011111, "ammin_db.d">; +-def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">; +-def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">; +-def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">; +-def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">; +-def LL_D : LLBase<0b00100010, "ll.d">; +-def SC_D : SCBase<0b00100011, "sc.d">; +- +-// CRC Check Instructions +-def CRC_W_B_W : ALU_3R<0b00000000001001000, "crc.w.b.w">; +-def CRC_W_H_W : ALU_3R<0b00000000001001001, "crc.w.h.w">; +-def CRC_W_W_W : ALU_3R<0b00000000001001010, "crc.w.w.w">; +-def CRC_W_D_W : ALU_3R<0b00000000001001011, "crc.w.d.w">; +-def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">; +-def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">; +-def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">; +-def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">; +- +-// Other Miscellaneous Instructions for 64-bits +-def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk), +- "asrtle.d", "$rj, $rk">; +-def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk), +- "asrtgt.d", "$rj, $rk">; +-def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">; +-} // Predicates = [IsLA64] ++def : LoongArchPat<(LoongArchTailCall texternalsym:$dst), ++ (PseudoTailCall texternalsym:$dst)>; + +-//===----------------------------------------------------------------------===// +-// Pseudo-instructions and codegen patterns +-// +-// Naming convention: For 'generic' pattern classes, we use the naming +-// convention PatTy1Ty2. +-//===----------------------------------------------------------------------===// ++let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, isIndirectBranch = 1, Uses = [SP] in ++def PseudoTAILIndirect : LoongArchPseudo<(outs), (ins GPRTC64Opnd:$rj), [(LoongArchTailCall GPRTC64Opnd:$rj)]>, ++ PseudoInstExpansion<(JIRL ZERO_64, GPR64Opnd:$rj, 0)>; + +-/// Generic pattern classes +- +-class PatGprGpr +- : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; +-class PatGprGpr_32 +- : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; +- +-class PatGprImm +- : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), +- (Inst GPR:$rj, ImmOpnd:$imm)>; +-class PatGprImm_32 +- : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), +- (Inst GPR:$rj, ImmOpnd:$imm)>; +- +-/// Simple arithmetic operations +- +-// Match both a plain shift and one where the shift amount is masked (this is +-// typically introduced when the legalizer promotes the shift amount and +-// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the +-// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64). +-def shiftMaskGRLen +- : ComplexPattern; +-def shiftMask32 : ComplexPattern; +- +-def sexti32 : ComplexPattern; +-def zexti32 : ComplexPattern; +- +-class shiftop +- : PatFrag<(ops node:$val, node:$count), +- (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>; +-class shiftopw +- : PatFrag<(ops node:$val, node:$count), +- (operator node:$val, (i64 (shiftMask32 node:$count)))>; +- +-let Predicates = [IsLA32] in { +-def : PatGprGpr; +-def : PatGprImm; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-} // Predicates = [IsLA32] +- +-let Predicates = [IsLA64] in { +-def : PatGprGpr; +-def : PatGprGpr_32; +-def : PatGprImm; +-def : PatGprImm_32; +-def : PatGprGpr; +-def : PatGprGpr_32; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the +-// product are used. +-def : PatGprGpr; +-def : PatGprGpr; +-def : PatGprGpr; +-// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed +-// multiplication. +-def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))), +- (MULW_D_W GPR:$rj, GPR:$rk)>; +-// Select MULW_D_WU for calculating the full 64 bits product of i32xi32 +-// unsigned multiplication. +-def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)), +- (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))), +- (MULW_D_WU GPR:$rj, GPR:$rk)>; +-} // Predicates = [IsLA64] +- +-def : PatGprGpr; +-def : PatGprImm; +-def : PatGprGpr; +-def : PatGprImm; +-def : PatGprGpr; +-def : PatGprImm; +- +-/// Shift +- +-let Predicates = [IsLA32] in { +-def : PatGprGpr, SLL_W>; +-def : PatGprGpr, SRA_W>; +-def : PatGprGpr, SRL_W>; +-def : PatGprImm; +-def : PatGprImm; +-def : PatGprImm; +-} // Predicates = [IsLA32] +- +-let Predicates = [IsLA64] in { +-def : PatGprGpr, SLL_W>; +-def : PatGprGpr, SRA_W>; +-def : PatGprGpr, SRL_W>; +-def : PatGprGpr, SLL_D>; +-def : PatGprGpr, SRA_D>; +-def : PatGprGpr, SRL_D>; +-def : PatGprImm; +-def : PatGprImm; +-def : PatGprImm; +-} // Predicates = [IsLA64] +- +-/// sext and zext +- +-def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>; +-def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>; +- +-let Predicates = [IsLA64] in { +-def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; +-} // Predicates = [IsLA64] +- +-/// Setcc +- +-def : PatGprGpr; +-def : PatGprImm; +-def : PatGprGpr; +-def : PatGprImm; +- +-// Define pattern expansions for setcc operations that aren't directly +-// handled by a LoongArch instruction. +-def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>; +-def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>; +-let Predicates = [IsLA32] in { +-def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), +- (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; +-} // Predicates = [IsLA32] +-let Predicates = [IsLA64] in { +-def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), +- (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; +-} // Predicates = [IsLA64] +-def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>; +-def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>; +-let Predicates = [IsLA32] in { +-def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), +- (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>; +-} // Predicates = [IsLA32] +-let Predicates = [IsLA64] in { +-def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), +- (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>; +-} // Predicates = [IsLA64] +-def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>; +-def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>; +-def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>; +-def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>; +-def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>; +-def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>; +- +-/// Select +- +-def : Pat<(select GPR:$cond, GPR:$t, GPR:$f), +- (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>; +- +-/// Branches and jumps +- +-class BccPat +- : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16), +- (Inst GPR:$rj, GPR:$rd, bb:$imm16)>; +- +-def : BccPat; +-def : BccPat; +-def : BccPat; +-def : BccPat; +-def : BccPat; +-def : BccPat; +- +-class BccSwapPat +- : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16), +- (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>; +- +-// Condition codes that don't have matching LoongArch branch instructions, but +-// are trivially supported by swapping the two input operands. +-def : BccSwapPat; +-def : BccSwapPat; +-def : BccSwapPat; +-def : BccSwapPat; +- +-// An extra pattern is needed for a brcond without a setcc (i.e. where the +-// condition was calculated elsewhere). +-def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>; +- +-let isBarrier = 1, isBranch = 1, isTerminator = 1 in +-def PseudoBR : Pseudo<(outs), (ins simm26_lsl2:$imm26), [(br bb:$imm26)]>, +- PseudoInstExpansion<(B simm26_lsl2:$imm26)>; +- +-let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in +-def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16), []>, +- PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; +- +-def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>; +-def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)), +- (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>; +- +-let isCall = 1, Defs = [R1] in +-def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { +- let AsmString = "bl\t$func"; +-} +- +-def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; +-def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; +- +-let isCall = 1, Defs = [R1] in +-def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj), +- [(loongarch_call GPR:$rj)]>, +- PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; +- +-let isBarrier = 1, isReturn = 1, isTerminator = 1 in +-def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, +- PseudoInstExpansion<(JIRL R0, R1, 0)>; +- +-/// BSTRINS and BSTRPICK +- +-let Predicates = [IsLA32] in { +-def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd), +- (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; +-def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd), +- (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; +-} // Predicates = [IsLA32] +- +-let Predicates = [IsLA64] in { +-def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), +- (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; +-def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd), +- (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; +-} // Predicates = [IsLA64] +- +-/// Loads +- +-multiclass LdPat { +- def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; +- def : Pat<(vt (LoadOp (add BaseAddr:$rj, simm12:$imm12))), +- (Inst BaseAddr:$rj, simm12:$imm12)>; +-} +- +-defm : LdPat; +-defm : LdPat; +-defm : LdPat; +-defm : LdPat; +-defm : LdPat, Requires<[IsLA32]>; +-defm : LdPat; +-defm : LdPat; +-let Predicates = [IsLA64] in { +-defm : LdPat; +-defm : LdPat; +-defm : LdPat; +-defm : LdPat; +-} // Predicates = [IsLA64] +- +-/// Stores +- +-multiclass StPat { +- def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), +- (Inst StTy:$rd, BaseAddr:$rj, 0)>; +- def : Pat<(StoreOp (vt StTy:$rd), (add BaseAddr:$rj, simm12:$imm12)), +- (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; +-} +- +-defm : StPat; +-defm : StPat; +-defm : StPat, Requires<[IsLA32]>; +-let Predicates = [IsLA64] in { +-defm : StPat; +-defm : StPat; +-} // Predicates = [IsLA64] +- +-/// Atomic loads and stores +- +-def : Pat<(atomic_fence timm, timm), (DBAR 0)>; +- +-defm : LdPat; +-defm : LdPat; +-defm : LdPat; +- +-defm : StPat; +-defm : StPat; +-defm : StPat, Requires<[IsLA32]>; +-let Predicates = [IsLA64] in { +-defm : LdPat; +-defm : StPat; +-defm : StPat; +-} // Predicates = [IsLA64] +- +-/// Other pseudo-instructions +- +-// Pessimistically assume the stack pointer will be clobbered +-let Defs = [R3], Uses = [R3] in { +-def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), +- [(callseq_start timm:$amt1, timm:$amt2)]>; +-def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), +- [(callseq_end timm:$amt1, timm:$amt2)]>; +-} // Defs = [R3], Uses = [R3] + +-//===----------------------------------------------------------------------===// +-// Assembler Pseudo Instructions +-//===----------------------------------------------------------------------===// ++def : LoongArchPat<(LoongArchJmpLink tglobaladdr:$dst), ++ (PseudoCall tglobaladdr:$dst)>; ++ ++def : LoongArchPat<(LoongArchJmpLink (i32 texternalsym:$dst)), ++ (PseudoCall texternalsym:$dst)>; ++def : LoongArchPat<(LoongArchJmpLink (i64 texternalsym:$dst)), ++ (PseudoCall texternalsym:$dst)>; ++ ++def : LoongArchPat<(LoongArchJmpLink (i64 texternalsym:$dst)), ++ (PseudoCall texternalsym:$dst)>; ++ ++def BL : JumpLink<"bl", calltarget>, FJ<0b010101>; ++ ++class IsAsCheapAsAMove { ++ bit isAsCheapAsAMove = 1; ++} ++class LoadUpper: ++ InstForm<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), ++ [], FrmI, opstr>, IsAsCheapAsAMove { ++ let hasSideEffects = 0; ++ let isReMaterializable = 1; ++ let mayLoad = 1; ++} ++ ++let isCodeGenOnly = 1 in { ++def LAPCREL : LoadUpper<"la.pcrel", GPR64Opnd, uimm16_64_relaxed>, LUI_FM, GPR_64; ++} ++ ++def NOP : LoongArchPseudo<(outs), (ins), []>, ++ PseudoInstExpansion<(ANDI ZERO_64, ZERO_64, 0)>; ++ ++def : LoongArchInstAlias<"nop", (ANDI ZERO_64, ZERO_64, 0), 1>; ++def : LoongArchInstAlias<"jr $rd", (JIRL ZERO_64, GPR64Opnd:$rd, 0), 1>; ++def : LoongArchInstAlias<"move $dst, $src", ++ (OR GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, GPR_64; ++ ++def UImm12RelaxedAsmOperandClass ++: UImmAsmOperandClass<12, [ConstantUImm20AsmOperandClass]> { ++ let Name = "UImm12_Relaxed"; ++ let PredicateMethod = "isAnyImm<12>"; ++ let DiagnosticType = "UImm12_Relaxed"; ++} ++ ++def SImm12RelaxedAsmOperandClass ++: SImmAsmOperandClass<12, [UImm12RelaxedAsmOperandClass]> { ++ let Name = "SImm12_Relaxed"; ++ let PredicateMethod = "isAnyImm<12>"; ++ let DiagnosticType = "SImm12_Relaxed"; ++} ++ ++def simm12_relaxed : Operand { ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<12>"; ++ let ParserMatchClass = !cast("SImm12RelaxedAsmOperandClass"); ++} ++ ++def : LoongArchPat<(i64 (anyext GPR32:$src)), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>,GPR_64; ++ ++let usesCustomInserter = 1 in { ++ def ATOMIC_LOAD_ADD_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_SUB_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_AND_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_OR_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_XOR_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_NAND_I64 : Atomic2Ops; ++ def ATOMIC_SWAP_I64 : Atomic2Ops; ++ def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap; ++ ++ def ATOMIC_LOAD_MAX_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_MIN_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_UMAX_I64 : Atomic2Ops; ++ def ATOMIC_LOAD_UMIN_I64 : Atomic2Ops; ++} ++ ++def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_SUB_I64_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_AND_I64_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_OR_I64_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_XOR_I64_POSTRA : Atomic2OpsPostRA; ++def ATOMIC_LOAD_NAND_I64_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA; ++ ++def ATOMIC_LOAD_MAX_I64_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_MIN_I64_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_UMAX_I64_POSTRA : Atomic2OpsPostRA; ++ ++def ATOMIC_LOAD_UMIN_I64_POSTRA : Atomic2OpsPostRA; ++ ++def : LoongArchPat<(atomic_load_8 addr:$a), (LD_B addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_load_16 addr:$a), (LD_H addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_load_32 addrimm14lsl2:$a), (LDPTR_W addrimm14lsl2:$a)>, GPR_64; ++def : LoongArchPat<(atomic_load_32 addr:$a), (LD_W addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_load_64 addrimm14lsl2:$a), (LDPTR_D addrimm14lsl2:$a)>, GPR_64; ++def : LoongArchPat<(atomic_load_64 addr:$a), (LD_D addr:$a)>, GPR_64; ++ ++def : LoongArchPat<(atomic_store_8 addr:$a, GPR64:$v), ++ (ST_B GPR64:$v, addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_store_16 addr:$a, GPR64:$v), ++ (ST_H GPR64:$v, addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_store_32 addrimm14lsl2:$a, GPR64:$v), ++ (STPTR_W GPR64:$v, addrimm14lsl2:$a)>, GPR_64; ++def : LoongArchPat<(atomic_store_32 addr:$a, GPR64:$v), ++ (ST_W GPR64:$v, addr:$a)>, GPR_64; ++def : LoongArchPat<(atomic_store_64 addrimm14lsl2:$a, GPR64:$v), ++ (STPTR_D GPR64:$v, addrimm14lsl2:$a)>, GPR_64; ++def : LoongArchPat<(atomic_store_64 addr:$a, GPR64:$v), ++ (ST_D GPR64:$v, addr:$a)>, GPR_64; ++ ++def : LoongArchPat<(bswap GPR64:$rt), (REVH_D (REVB_4H GPR64:$rt))>; ++ ++def immZExt5 : ImmLeaf; + +-def : InstAlias<"nop", (ANDI R0, R0, 0)>; +-def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; ++def immZExtRange2To64 : PatLeaf<(imm), [{ ++ return isUInt<7>(N->getZExtValue()) && (N->getZExtValue() >= 2) && ++ (N->getZExtValue() <= 64); ++}]>; ++ ++// bstrins and bstrpick ++class InsBase ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd, RO:$src), ++ !strconcat(opstr, "\t$rd, $rj, $msbd, $lsbd"), ++ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd, RO:$src))], ++ FrmR, opstr> { ++ let Constraints = "$src = $rd"; ++ } ++ ++class InsBase_32 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw, RO:$src), ++ !strconcat(opstr, "\t$rd, $rj, $msbw, $lsbw"), ++ [(set RO:$rd, (OpNode RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw, RO:$src))], ++ FrmR, opstr> { ++ let Constraints = "$src = $rd"; ++} ++ ++class PickBase ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd), ++ !strconcat(opstr, "\t$rd, $rj, $msbd, $lsbd"), ++ [(set RO:$rd, (Op RO:$rj, ImmOpnd:$msbd, ImmOpnd:$lsbd))], ++ FrmR, opstr>; ++ ++class PickBase_32 ++ : InstForm<(outs RO:$rd), (ins RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw), ++ !strconcat(opstr, "\t$rd, $rj, $msbw, $lsbw"), ++ [(set RO:$rd, (Op RO:$rj, ImmOpnd:$msbw, ImmOpnd:$lsbw))], ++ FrmR, opstr>; ++ ++ def BSTRINS_D : InsBase<"bstrins.d", GPR64Opnd, uimm6, LoongArchBstrins>, ++ INSERT_BIT64<0>; ++ def BSTRPICK_D : PickBase<"bstrpick.d", GPR64Opnd, uimm6, LoongArchBstrpick>, ++ INSERT_BIT64<1>; ++ ++let isCodeGenOnly = 1 in { ++ def ZEXT64_32 : InstForm<(outs GPR64Opnd:$rd), ++ (ins GPR32Opnd:$rj, uimm6:$msbd, ++ uimm6:$lsbd), ++ "bstrpick.d $rd, $rj, $msbd, $lsbd", [], FrmR, "bstrpick.d">, ++ INSERT_BIT64<1>; ++} ++ ++//32-to-64-bit extension ++def : LoongArchPat<(i64 (zext GPR32:$src)), (ZEXT64_32 GPR32:$src, 31, 0)>; ++def : LoongArchPat<(i64 (extloadi1 addr:$src)), (LD_B addr:$src)>, ++ GPR_64; ++def : LoongArchPat<(i64 (extloadi8 addr:$src)), (LD_B addr:$src)>, ++ GPR_64; ++def : LoongArchPat<(i64 (extloadi16 addr:$src)), (LD_H addr:$src)>, ++ GPR_64; ++def : LoongArchPat<(i64 (extloadi32 addr:$src)), (LD_W addr:$src)>, ++ GPR_64; ++ ++class LDX_FT_LA : ++ InstForm<(outs DRC:$rd), (ins PtrRC:$rj, PtrRC:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(set DRC:$rd, (OpNode (add iPTR:$rj, iPTR:$rk)))], ++ FrmR, opstr> { ++ let AddedComplexity = 20; ++ let canFoldAsLoad = 1; ++ string BaseOpcode = opstr; ++ let mayLoad = 1; ++} ++ ++class STX_FT_LA : ++ InstForm<(outs), (ins DRC:$rd, PtrRC:$rj, PtrRC:$rk), ++ !strconcat(opstr, "\t$rd, $rj, $rk"), ++ [(OpNode DRC:$rd, (add iPTR:$rj, iPTR:$rk))], ++ FrmI, opstr> { ++ string BaseOpcode = opstr; ++ let mayStore = 1; ++ let AddedComplexity = 20; ++} ++ ++ ++def LDX_B : LDX_FT_LA<"ldx.b", GPR64Opnd, sextloadi8>, ++ R3MI<0b00000000>; ++def LDX_H : LDX_FT_LA<"ldx.h", GPR64Opnd, sextloadi16>, ++ R3MI<0b00001000>; ++def LDX_W : LDX_FT_LA<"ldx.w", GPR64Opnd, sextloadi32>, ++ R3MI<0b00010000>; ++def LDX_D : LDX_FT_LA<"ldx.d", GPR64Opnd, load>, ++ R3MI<0b00011000>; ++def STX_B : STX_FT_LA<"stx.b", GPR64Opnd, truncstorei8>, ++ R3MI<0b00100000>; ++def STX_H : STX_FT_LA<"stx.h", GPR64Opnd, truncstorei16>, ++ R3MI<0b00101000>; ++def STX_W : STX_FT_LA<"stx.w", GPR64Opnd, truncstorei32>, ++ R3MI<0b00110000>; ++def STX_D : STX_FT_LA<"stx.d", GPR64Opnd, store>, ++ R3MI<0b00111000>; ++def LDX_BU : LDX_FT_LA<"ldx.bu", GPR64Opnd, extloadi8>, ++ R3MI<0b01000000>; ++def LDX_HU : LDX_FT_LA<"ldx.hu", GPR64Opnd, extloadi16>, ++ R3MI<0b01001000>; ++def LDX_WU : LDX_FT_LA<"ldx.wu", GPR64Opnd, zextloadi32>, ++ R3MI<0b01010000>; ++ ++//def : LoongArchPat<(bswap GPR64:$rj), (REVH_D (REVB_4H GPR64:$rj))>; ++//def : LoongArchPat<(bswap GPR64:$rj), (ROTRI_D (REVB_2W GPR64:$rj), 32)>; ++def : LoongArchPat<(bswap GPR64:$rj), (REVB_D GPR64:$rj)>; ++ ++let isCodeGenOnly = 1 in { ++ def SLLI_D_64_32 : Shift_Imm64<"", GPR64Opnd>, R2_IMM6<0b00>, GPR_64 { ++ let imm6 = 0; ++ let AsmString = "slli.d\t$rd, $rj, 32"; ++ let InOperandList = (ins GPR32:$rj); ++ let OutOperandList = (outs GPR64:$rd); ++ } ++ ++ let isMoveReg = 1, imm5 = 0, ++ AsmString = "slli.w\t$rd, $rj, 0", ++ OutOperandList = (outs GPR64:$rd) in { ++ let InOperandList = (ins GPR32:$rj) in ++ def SLLI_W_64_32 : Shift_Imm32<"", GPR32Opnd>, R2_IMM5<0b00>, GPR_64; ++ let InOperandList = (ins GPR64:$rj) in ++ def SLLI_W_64_64 : Shift_Imm32<"", GPR32Opnd>, R2_IMM5<0b00>, GPR_64; ++ } ++ ++ let AsmString = "sltui\t$rd, $rj, $imm12", ++ OutOperandList = (outs GPR64:$rd) in { ++ let InOperandList = (ins GPR64:$rj, simm12:$imm12) in ++ def SLTUI_64 : SetCC_I<"", GPR64Opnd, simm12>, R2_IMM12<0b001>, GPR_64; ++ } ++} ++ ++// 32-to-64-bit extension ++//def : LoongArchPat<(i64 (zext GPR32:$src)), (SRLI_D (SLLI_D_64_32 GPR32:$src), 32)>, GPR_64; ++def : LoongArchPat<(i64 (sext GPR32:$src)), (SLLI_W_64_32 GPR32:$src)>, GPR_64; ++def : LoongArchPat<(i64 (sext_inreg GPR64:$src, i32)), (SLLI_W_64_64 GPR64:$src)>, GPR_64; ++ ++let Uses = [A0, A1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { ++ def LoongArcheh_return32 : LoongArchPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), ++ [(LoongArchehret GPR32:$spoff, GPR32:$dst)]>; ++ def LoongArcheh_return64 : LoongArchPseudo<(outs), (ins GPR64:$spoff,GPR64:$dst), ++ [(LoongArchehret GPR64:$spoff, GPR64:$dst)]>; ++} ++ ++def : LoongArchPat<(select i32:$cond, i64:$t, i64:$f), ++ (OR (MASKEQZ i64:$t, (SLLI_W_64_32 i32:$cond)), ++ (MASKNEZ i64:$f, (SLLI_W_64_32 i32:$cond)))>; ++// setcc patterns ++multiclass SeteqPats { ++ def : LoongArchPat<(seteq RC:$lhs, 0), ++ (SLTiuOp RC:$lhs, 1)>; ++ def : LoongArchPat<(setne RC:$lhs, 0), ++ (SLTuOp ZEROReg, RC:$lhs)>; ++ def : LoongArchPat<(seteq RC:$lhs, RC:$rhs), ++ (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>; ++ def : LoongArchPat<(setne RC:$lhs, RC:$rhs), ++ (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; ++} ++ ++multiclass SetlePats { ++ def : LoongArchPat<(setle RC:$lhs, RC:$rhs), ++ (XORiOp (SLTOp RC:$rhs, RC:$lhs), 1)>; ++ def : LoongArchPat<(setule RC:$lhs, RC:$rhs), ++ (XORiOp (SLTuOp RC:$rhs, RC:$lhs), 1)>; ++} ++ ++multiclass SetgtPats { ++ def : LoongArchPat<(setgt RC:$lhs, RC:$rhs), ++ (SLTOp RC:$rhs, RC:$lhs)>; ++ def : LoongArchPat<(setugt RC:$lhs, RC:$rhs), ++ (SLTuOp RC:$rhs, RC:$lhs)>; ++} ++ ++multiclass SetgePats { ++ def : LoongArchPat<(setge RC:$lhs, RC:$rhs), ++ (XORiOp (SLTOp RC:$lhs, RC:$rhs), 1)>; ++ def : LoongArchPat<(setuge RC:$lhs, RC:$rhs), ++ (XORiOp (SLTuOp RC:$lhs, RC:$rhs), 1)>; ++} ++ ++multiclass SetgeImmPats { ++ def : LoongArchPat<(setge RC:$lhs, immSExt12:$rhs), ++ (XORiOp (SLTiOp RC:$lhs, immSExt12:$rhs), 1)>; ++ def : LoongArchPat<(setuge RC:$lhs, immSExt12:$rhs), ++ (XORiOp (SLTiuOp RC:$lhs, immSExt12:$rhs), 1)>; ++} ++ ++class LoadRegImmPat : ++ LoongArchPat<(ValTy (Node addrRegImm:$a)), (LoadInst addrRegImm:$a)>; ++ ++class StoreRegImmPat : ++ LoongArchPat<(Node ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>; ++ ++class LoadRegImm14Lsl2Pat : ++ LoongArchPat<(ValTy (Node addrimm14lsl2:$a)), (LoadInst addrimm14lsl2:$a)>; ++ ++class StoreRegImm14Lsl2Pat : ++ LoongArchPat<(Node ValTy:$v, addrimm14lsl2:$a), (StoreInst ValTy:$v, addrimm14lsl2:$a)>; ++ ++// Patterns for loads/stores with a reg+imm operand. ++// let AddedComplexity = 40 so that these instructions are selected instead of ++// LDX/STX which needs one more register and an ANDI instruction. ++let AddedComplexity = 40 in { ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : LoadRegImmPat; ++ def : StoreRegImmPat; ++ def : StoreRegImmPat; ++ def : StoreRegImmPat; ++ def : StoreRegImmPat; ++ ++ def : LoadRegImm14Lsl2Pat; ++ def : LoadRegImm14Lsl2Pat; ++ def : StoreRegImm14Lsl2Pat; ++ def : StoreRegImm14Lsl2Pat; ++} + + //===----------------------------------------------------------------------===// +-// Basic Floating-Point Instructions ++// Base Extension Support + //===----------------------------------------------------------------------===// + +-include "LoongArchFloat32InstrInfo.td" +-include "LoongArchFloat64InstrInfo.td" ++include "LoongArch32InstrInfo.td" ++include "LoongArchInstrInfoF.td" ++include "LoongArchLSXInstrFormats.td" ++include "LoongArchLSXInstrInfo.td" ++include "LoongArchLASXInstrFormats.td" ++include "LoongArchLASXInstrInfo.td" ++ ++defm : SeteqPats, GPR_64; ++defm : SetlePats, GPR_64; ++defm : SetgtPats, GPR_64; ++defm : SetgePats, GPR_64; ++defm : SetgeImmPats, GPR_64; ++ ++/// ++/// for relocation ++/// ++let isCodeGenOnly = 1 in { ++def PCADDU12I_ri : SI20<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; ++def PCADDU12I_rii : RELOC_rii<"pcaddu12i", GPR64Opnd, simm20>, R1_SI20<0b0001110>; ++def ORI_rri : Int_Reg2_Imm12<"ori", GPR64Opnd, uimm12, or>, R2_IMM12<0b110>; ++def ORI_rrii : RELOC_rrii<"ori", GPR64Opnd, uimm12>, R2_IMM12<0b110>; ++def LU12I_W_ri : SI20<"lu12i.w", GPR64Opnd, simm20>, R1_SI20<0b0001010>; ++def LU32I_D_ri : SI20<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; ++def LU32I_D_rii : RELOC_rii<"lu32i.d", GPR64Opnd, simm20>, R1_SI20<0b0001011>; ++def LU52I_D_rri : Int_Reg2_Imm12<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; ++def LU52I_D_rrii : RELOC_rrii<"lu52i.d", GPR64Opnd, simm12>, R2_IMM12<0b100>; ++def ADDI_D_rri : Int_Reg2_Imm12<"addi.d", GPR64Opnd, simm12, add>, R2_IMM12<0b011>; ++def ADDI_D_rrii : RELOC_rrii<"addi.d", GPR64Opnd, simm12>, R2_IMM12<0b011>; ++def LD_D_rri : Ld<"ld.d", GPR64Opnd, mem_simmptr, load>, LOAD_STORE<0b0011>; ++def LD_D_rrii : RELOC_rrii<"ld.d", GPR64Opnd, simm12>, LOAD_STORE_RRI<0b0011>; ++def ADD_D_rrr : Int_Reg3<"add.d", GPR64Opnd, add>, R3I<0b0100001>; ++def LDX_D_rrr : LDX_FT_LA<"ldx.d", GPR64Opnd, load>, ++ R3MI<0b00011000>; ++} + + //===----------------------------------------------------------------------===// +-// Privilege Instructions ++// Assembler Pseudo Instructions + //===----------------------------------------------------------------------===// +- +-// CSR Access Instructions +-def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num), +- "csrrd", "$rd, $csr_num">; +-let Constraints = "$rd = $dst" in { +-def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst), +- (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">; +-def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst), +- (ins GPR:$rd, GPR:$rj, uimm14:$csr_num), +- "csrxchg", "$rd, $rj, $csr_num">; +-} // Constraints = "$rd = $dst" +- +-// IOCSR Access Instructions +-def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">; +-def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">; +-def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">; +-def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">; +-def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">; +-def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">; +-let Predicates = [IsLA64] in { +-def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">; +-def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">; +-} // Predicates = [IsLA64] +- +-// Cache Maintenance Instructions +-def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop", +- "$op, $rj, $imm12">; +- +-// TLB Maintenance Instructions +-def TLBSRCH : FmtI32<0b00000110010010000010100000000000, "tlbsrch">; +-def TLBRD : FmtI32<0b00000110010010000010110000000000, "tlbrd">; +-def TLBWR : FmtI32<0b00000110010010000011000000000000, "tlbwr">; +-def TLBFILL : FmtI32<0b00000110010010000011010000000000, "tlbfill">; +-def TLBCLR : FmtI32<0b00000110010010000010000000000000, "tlbclr">; +-def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">; +-def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb", +- "$op, $rj, $rk">; +- +-// Software Page Walking Instructions +-def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd), +- (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">; +-def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">; +- +- +-// Other Miscellaneous Instructions +-def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">; +-def DBCL : MISC_I15<0b00000000001010101, "dbcl">; +-def IDLE : MISC_I15<0b00000110010010001, "idle">; ++def LoadImm32 : LoongArchAsmPseudoInst<(outs GPR32Opnd:$rd), ++ (ins uimm32_coerced:$imm32), ++ "li.w\t$rd, $imm32">; ++def LoadImm64 : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "li.d\t$rd, $imm64">; ++// load address ++def LoadAddrLocal : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.local\t$rd, $imm64">; ++def : InstAlias<"la.pcrel $rd, $imm", ++ (LoadAddrLocal GPR64Opnd:$rd, imm64:$imm), 1>; ++def LoadAddrGlobal : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.global\t$rd, $imm64">; ++def LoadAddrGlobal_Alias : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la\t$rd, $imm64">; ++def : InstAlias<"la.got $rd, $imm", ++ (LoadAddrGlobal GPR64Opnd:$rd, imm64:$imm), 1>; ++ ++def LoadAddrTLS_LE : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.tls.le\t$rd, $imm64">; ++def LoadAddrTLS_IE : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.tls.ie\t$rd, $imm64">; ++def LoadAddrTLS_GD : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.tls.gd\t$rd, $imm64">; ++def LoadAddrTLS_LD : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins imm64:$imm64), ++ "la.tls.ld\t$rd, $imm64">; ++ ++// load address with a temp reg ++def LoadAddrLocalRR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins GPR64Opnd:$rt, imm64:$imm64), ++ "la.local\t$rd, $rt, $imm64">; ++def LoadAddrGlobalRR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins GPR64Opnd:$rt, imm64:$imm64), ++ "la.global\t$rd, $rt, $imm64">; ++def LoadAddrTLS_IE_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins GPR64Opnd:$rt, imm64:$imm64), ++ "la.tls.ie\t$rd, $rt, $imm64">; ++def LoadAddrTLS_GD_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins GPR64Opnd:$rt, imm64:$imm64), ++ "la.tls.gd\t$rd, $rt, $imm64">; ++def LoadAddrTLS_LD_RR : LoongArchAsmPseudoInst<(outs GPR64Opnd:$rd), ++ (ins GPR64Opnd:$rt, imm64:$imm64), ++ "la.tls.ld\t$rd, $rt, $imm64">; ++ ++// trap when div zero ++def PseudoTEQ : LoongArchPseudo<(outs), (ins GPR64Opnd:$rt), []>; ++ ++ ++def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, immSExt12:$imm12)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ADDI_W GPR32:$src, immSExt12:$imm12), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (ADD_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SUB_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (MUL_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SLLI_W GPR32:$src, immZExt5:$imm5), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SLL_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRLI_W GPR32:$src, immZExt5:$imm5), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRL_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRAI_W GPR32:$src, immZExt5:$imm5), sub_32)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))), ++ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), ++ (SRA_W GPR32:$src, GPR32:$src2), sub_32)>; ++ ++ ++def : LoongArchPat<(i64 (xor GPR64:$rj, (i64 -1))), ++ (NOR ZERO_64, GPR64:$rj)>; ++ ++def : LoongArchPat<(and GPR64:$rj, (i64 (xor GPR64:$rk, (i64 -1)))), ++ (ANDN GPR64:$rj, GPR64:$rk)>; ++ ++def : LoongArchPat<(i64 (or GPR64:$rj, (xor GPR64:$rk, (i64 -1)))), ++ (ORN GPR64:$rj, GPR64:$rk)>; ++ ++def : LoongArchPat<(i64 (zext (i32 (seteq GPR64:$rj, (i64 0))))), ++ (SLTUI_64 GPR64:$rj, (i64 1))>; ++ ++ ++def : LoongArchPat<(i64 (zext (i32 (srl GPR32:$src, immZExt5:$imm5)))), ++ (BSTRPICK_D (INSERT_SUBREG ++ (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32), ++ (i32 31), immZExt5:$imm5)>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td +new file mode 100644 +index 000000000..4df5fc88e +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td +@@ -0,0 +1,630 @@ ++//===- LoongArchInstrInfoF.td - Target Description for LoongArch Target -*- tablegen -*-=// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains the LoongArch implementation of the TargetInstrInfo class. ++// ++//===----------------------------------------------------------------------===// ++// FP immediate patterns. ++def fpimm0 : PatLeaf<(fpimm), [{ ++ return N->isExactlyValue(+0.0); ++}]>; ++ ++def fpimm0neg : PatLeaf<(fpimm), [{ ++ return N->isExactlyValue(-0.0); ++}]>; ++ ++def fpimm1 : PatLeaf<(fpimm), [{ ++ return N->isExactlyValue(+1.0); ++}]>; ++ ++def IsNotSoftFloat : Predicate<"!Subtarget->useSoftFloat()">, ++ AssemblerPredicate<(all_of FeatureSoftFloat)>; ++ ++class HARDFLOAT { list HardFloatPredicate = [IsNotSoftFloat]; } ++ ++def SDT_LoongArchTruncIntFP : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>; ++ ++def LoongArchTruncIntFP : SDNode<"LoongArchISD::TruncIntFP", SDT_LoongArchTruncIntFP>; ++ ++def SDT_LoongArchFPBrcond : SDTypeProfile<0, 3, [SDTCisInt<0>, ++ SDTCisVT<1, i32>, ++ SDTCisVT<2, OtherVT>]>; ++ ++def LoongArchFPBrcond : SDNode<"LoongArchISD::FPBrcond", SDT_LoongArchFPBrcond, ++ [SDNPHasChain, SDNPOptInGlue]>; ++ ++def SDT_LoongArchCMovFP : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, i32>, ++ SDTCisSameAs<1, 3>]>; ++ ++def LoongArchCMovFP_T : SDNode<"LoongArchISD::CMovFP_T", SDT_LoongArchCMovFP, [SDNPInGlue]>; ++ ++def LoongArchCMovFP_F : SDNode<"LoongArchISD::CMovFP_F", SDT_LoongArchCMovFP, [SDNPInGlue]>; ++ ++def SDT_LoongArchFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, ++ SDTCisVT<2, i32>]>; ++ ++def LoongArchFPCmp : SDNode<"LoongArchISD::FPCmp", SDT_LoongArchFPCmp, [SDNPOutGlue]>; ++ ++def SDT_LoongArchFSEL : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, ++ SDTCisVT<2, i32>, ++ SDTCisSameAs<1, 3>]>; ++ ++def LoongArchFSEL : SDNode<"LoongArchISD::FSEL", SDT_LoongArchFSEL, ++ [SDNPInGlue]>; ++ ++//===---------------------------------------------------------------------===/ ++//Instruction Class Templates ++//===---------------------------------------------------------------------===/ ++ ++class Float_MOVF ++ : InstForm<(outs RO:$rd), (ins RC:$fj), ++ !strconcat(opstr, "\t$rd, $fj"), ++ [(set RO:$rd, (OpNode RC:$fj))], ++ FrmFR, opstr>, HARDFLOAT { ++ let isMoveReg = 1; ++} ++ ++class Float_MOVT ++ : InstForm<(outs RO:$fd), (ins RC:$rj), ++ !strconcat(opstr, "\t$fd, $rj"), ++ [(set RO:$fd, (OpNode RC:$rj))], ++ FrmFR, opstr>, HARDFLOAT { ++ let isMoveReg = 1; ++} ++ ++class Float_CVT ++ : InstForm<(outs RO:$fd), (ins RS:$fj), ++ !strconcat(opstr, "\t$fd, $fj"), ++ [(set RO:$fd, (OpNode RS:$fj))], ++ FrmFR, opstr>, ++ HARDFLOAT { ++ let hasSideEffects = 0; ++} ++ ++/// float mov ++class Gpr_2_Fcsr ++ : InstForm<(outs FCSROpnd:$fcsr), (ins RO:$rj), ++ !strconcat(opstr, "\t$fcsr, $rj"), ++ [(set FCSROpnd:$fcsr, (OpNode RO:$rj))], ++ FrmR, opstr>; ++class Fcsr_2_Gpr ++ : InstForm<(outs RO:$rd), (ins FCSROpnd:$fcsr), ++ !strconcat(opstr, "\t$rd, $fcsr"), ++ [(set RO:$rd, (OpNode FCSROpnd:$fcsr))], ++ FrmR, opstr>; ++class Fgr_2_Fcfr ++ : InstForm<(outs FCFROpnd:$cd), (ins RO:$fj), ++ !strconcat(opstr, "\t$cd, $fj"), ++ [(set FCFROpnd:$cd, (OpNode RO:$fj))], ++ FrmR, opstr>; ++class Fcfr_2_Fgr ++ : InstForm<(outs RO:$fd), (ins FCFROpnd:$cj), ++ !strconcat(opstr, "\t$fd, $cj"), ++ [(set RO:$fd, (OpNode FCFROpnd:$cj))], ++ FrmR, opstr>; ++class Gpr_2_Fcfr ++ : InstForm<(outs FCFROpnd:$cd), (ins RO:$rj), ++ !strconcat(opstr, "\t$cd, $rj"), ++ [(set FCFROpnd:$cd, (OpNode RO:$rj))], ++ FrmR, opstr>; ++class Fcfr_2_Gpr ++ : InstForm<(outs RO:$rd), (ins FCFROpnd:$cj), ++ !strconcat(opstr, "\t$rd, $cj"), ++ [(set RO:$rd, (OpNode FCFROpnd:$cj))], ++ FrmR, opstr>; ++ ++class FLDX : ++ InstForm<(outs DRC:$fd), (ins PtrRC:$rj, PtrRC:$rk), ++ !strconcat(opstr, "\t$fd, $rj, $rk"), ++ [(set DRC:$fd, (OpNode (add iPTR:$rj, iPTR:$rk)))], ++ FrmR, opstr> { ++ let AddedComplexity = 20; ++} ++ ++class FSTX : ++ InstForm<(outs), (ins DRC:$fd, PtrRC:$rj, PtrRC:$rk), ++ !strconcat(opstr, "\t$fd, $rj, $rk"), ++ [(OpNode DRC:$fd, (add iPTR:$rj, iPTR:$rk))], ++ FrmR, opstr> { ++ let AddedComplexity = 20; ++} ++ ++/// f{maxa/mina}.{s/d} ++class Float_Reg3_Fmaxa ++ : InstForm<(outs RO:$fd), (ins RO:$fj, RO:$fk), ++ !strconcat(opstr, "\t$fd, $fj, $fk"), ++ [], FrmR, opstr>; ++/// frecip ++class Float_Reg2_Frecip ++ : InstForm<(outs RO:$fd), (ins RO:$fj), ++ !strconcat(opstr, "\t$fd, $fj"), ++ [(set RO:$fd, (OpNode fpimm1, RO:$fj))], ++ FrmR, opstr>; ++/// frsqrt ++class Float_Reg2_Frsqrt ++ : InstForm<(outs RO:$fd), (ins RO:$fj), ++ !strconcat(opstr, "\t$fd, $fj"), ++ [(set RO:$fd, (OpNode fpimm1, (fsqrt RO:$fj)))], ++ FrmR, opstr>; ++ ++class BceqzBr : ++ InstForm<(outs), (ins FCFROpnd:$cj, opnd:$offset), ++ !strconcat(opstr, "\t$cj, $offset"), ++ [(LoongArchFPBrcond Op, FCFROpnd:$cj, bb:$offset)], ++ FrmFI, opstr>, HARDFLOAT { ++ let isBranch = 1; ++ let isTerminator = 1; ++ let hasFCCRegOperand = 1; ++} ++ ++class FCMP_COND ++ : InstForm<(outs FCFROpnd:$cd), (ins RO:$fj, RO:$fk), ++ !strconcat("fcmp.", CondStr, ".", TypeStr, "\t$cd, $fj, $fk"), ++ [(set FCFROpnd:$cd, (OpNode RO:$fj, RO:$fk))], ++ FrmOther, ++ !strconcat("fcmp.", CondStr, ".", TypeStr)> { ++ bit isCTI = 1; // for what? from Mips32r6InstrInfo.td line 219 ++} ++ ++class FIELD_CMP_COND Val> { ++ bits<5> Value = Val; ++} ++def FIELD_CMP_COND_CAF : FIELD_CMP_COND<0x0>; ++def FIELD_CMP_COND_CUN : FIELD_CMP_COND<0x8>; ++def FIELD_CMP_COND_CEQ : FIELD_CMP_COND<0x4>; ++def FIELD_CMP_COND_CUEQ : FIELD_CMP_COND<0xC>; ++def FIELD_CMP_COND_CLT : FIELD_CMP_COND<0x2>; ++def FIELD_CMP_COND_CULT : FIELD_CMP_COND<0xA>; ++def FIELD_CMP_COND_CLE : FIELD_CMP_COND<0x6>; ++def FIELD_CMP_COND_CULE : FIELD_CMP_COND<0xE>; ++def FIELD_CMP_COND_CNE : FIELD_CMP_COND<0x10>; ++def FIELD_CMP_COND_COR : FIELD_CMP_COND<0x14>; ++def FIELD_CMP_COND_CUNE : FIELD_CMP_COND<0x18>; ++def FIELD_CMP_COND_SAF : FIELD_CMP_COND<0x1>; ++def FIELD_CMP_COND_SUN : FIELD_CMP_COND<0x9>; ++def FIELD_CMP_COND_SEQ : FIELD_CMP_COND<0x5>; ++def FIELD_CMP_COND_SUEQ : FIELD_CMP_COND<0xD>; ++def FIELD_CMP_COND_SLT : FIELD_CMP_COND<0x3>; ++def FIELD_CMP_COND_SULT : FIELD_CMP_COND<0xB>; ++def FIELD_CMP_COND_SLE : FIELD_CMP_COND<0x7>; ++def FIELD_CMP_COND_SULE : FIELD_CMP_COND<0xF>; ++def FIELD_CMP_COND_SNE : FIELD_CMP_COND<0x11>; ++def FIELD_CMP_COND_SOR : FIELD_CMP_COND<0x15>; ++def FIELD_CMP_COND_SUNE : FIELD_CMP_COND<0x19>; ++ ++multiclass FCMP_COND_M op, string TypeStr, ++ RegisterOperand RO> { ++ def FCMP_CAF_#NAME : FCMP_COND<"caf", TypeStr, RO>, ++ R2_COND; ++ def FCMP_CUN_#NAME : FCMP_COND<"cun", TypeStr, RO, setuo>, ++ R2_COND; ++ def FCMP_CEQ_#NAME : FCMP_COND<"ceq", TypeStr, RO, setoeq>, ++ R2_COND; ++ def FCMP_CUEQ_#NAME : FCMP_COND<"cueq", TypeStr, RO, setueq>, ++ R2_COND; ++ def FCMP_CLT_#NAME : FCMP_COND<"clt", TypeStr, RO, setolt>, ++ R2_COND; ++ def FCMP_CULT_#NAME : FCMP_COND<"cult", TypeStr, RO, setult>, ++ R2_COND; ++ def FCMP_CLE_#NAME : FCMP_COND<"cle", TypeStr, RO, setole>, ++ R2_COND; ++ def FCMP_CULE_#NAME : FCMP_COND<"cule", TypeStr, RO, setule>, ++ R2_COND; ++ def FCMP_CNE_#NAME : FCMP_COND<"cne", TypeStr, RO, setone>, ++ R2_COND; ++ def FCMP_COR_#NAME : FCMP_COND<"cor", TypeStr, RO, seto>, ++ R2_COND; ++ def FCMP_CUNE_#NAME : FCMP_COND<"cune", TypeStr, RO, setune>, ++ R2_COND; ++ ++ def FCMP_SAF_#NAME : FCMP_COND<"saf", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SUN_#NAME : FCMP_COND<"sun", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SEQ_#NAME : FCMP_COND<"seq", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SUEQ_#NAME : FCMP_COND<"sueq", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SLT_#NAME : FCMP_COND<"slt", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SULT_#NAME : FCMP_COND<"sult", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SLE_#NAME : FCMP_COND<"sle", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SULE_#NAME : FCMP_COND<"sule", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SNE_#NAME : FCMP_COND<"sne", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SOR_#NAME : FCMP_COND<"sor", TypeStr, RO>, ++ R2_COND; ++ def FCMP_SUNE_#NAME : FCMP_COND<"sune", TypeStr, RO>, ++ R2_COND; ++} ++ ++//// comparisons supported via another comparison ++//multiclass FCmp_Pats { ++// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), ++// (!cast("FCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), ++// (!cast("FCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), ++// (!cast("FCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), ++// (!cast("FCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), ++// (!cast("FCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), ++// (NOROp ++// (!cast("FCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), ++// ZEROReg)>; ++//} ++ ++ ++/// ++/// R2 ++/// ++def FABS_S : Float_Reg2<"fabs.s", FGR32Opnd, fabs>, R2F<0b0100000001>; ++def FABS_D : Float_Reg2<"fabs.d", FGR64Opnd, fabs>, R2F<0b0100000010>; ++def FNEG_S : Float_Reg2<"fneg.s", FGR32Opnd, fneg>, R2F<0b0100000101>; ++def FNEG_D : Float_Reg2<"fneg.d", FGR64Opnd, fneg>, R2F<0b0100000110>; ++def FLOGB_S : Float_Reg2<"flogb.s", FGR32Opnd>, R2F<0b0100001001>; ++def FLOGB_D : Float_Reg2<"flogb.d", FGR64Opnd>, R2F<0b0100001010>; ++def FCLASS_S : Float_Reg2<"fclass.s", FGR32Opnd>, R2F<0b0100001101>; ++def FCLASS_D : Float_Reg2<"fclass.d", FGR64Opnd>, R2F<0b0100001110>; ++def FSQRT_S : Float_Reg2<"fsqrt.s", FGR32Opnd, fsqrt>, R2F<0b0100010001>; ++def FSQRT_D : Float_Reg2<"fsqrt.d", FGR64Opnd, fsqrt>, R2F<0b0100010010>; ++def FRECIP_S : Float_Reg2_Frecip<"frecip.s", FGR32Opnd, fdiv>, R2F<0b0100010101>; ++def FRECIP_D : Float_Reg2_Frecip<"frecip.d", FGR64Opnd, fdiv>, R2F<0b0100010110>; ++def FRSQRT_S : Float_Reg2_Frsqrt<"frsqrt.s", FGR32Opnd, fdiv>, R2F<0b0100011001>; ++def FRSQRT_D : Float_Reg2_Frsqrt<"frsqrt.d", FGR64Opnd, fdiv>, R2F<0b0100011010>; ++def FMOV_S : Float_Reg2<"fmov.s", FGR32Opnd>, R2F<0b0100100101>; ++def FMOV_D : Float_Reg2<"fmov.d", FGR64Opnd>, R2F<0b0100100110>; ++ ++def MOVGR2FR_W : Float_MOVT<"movgr2fr.w", FGR32Opnd, GPR32Opnd, bitconvert>, MOVFI<0b0100101001>; ++def MOVGR2FR_D : Float_MOVT<"movgr2fr.d", FGR64Opnd, GPR64Opnd, bitconvert>, MOVFI<0b0100101010>; ++def MOVGR2FRH_W : Float_MOVT<"movgr2frh.w", FGR64Opnd, GPR32Opnd>, MOVFI<0b0100101011>; //not realize ++def MOVFR2GR_S : Float_MOVF<"movfr2gr.s", GPR32Opnd, FGR32Opnd, bitconvert>, MOVIF<0b0100101101>; ++def MOVFR2GR_D : Float_MOVF<"movfr2gr.d", GPR64Opnd, FGR64Opnd, bitconvert>, MOVIF<0b0100101110>; ++def MOVFRH2GR_S : Float_MOVF<"movfrh2gr.s", GPR32Opnd, FGR32Opnd>, MOVIF<0b0100101111>; //not realize ++ ++let isCodeGenOnly = 1 in { ++ def MOVFR2GR_DS : Float_MOVF<"movfr2gr.s", GPR64Opnd, FGR32Opnd>, MOVIF<0b0100101101>; ++} ++ ++def FCVT_S_D : Float_CVT<"fcvt.s.d", FGR32Opnd, FGR64Opnd>, R2F<0b1001000110>; ++def FCVT_D_S : Float_CVT<"fcvt.d.s", FGR64Opnd, FGR32Opnd>, R2F<0b1001001001>; ++ ++def FTINTRM_W_S : Float_Reg2<"ftintrm.w.s", FGR32Opnd>, R2F<0b1010000001>; ++def FTINTRM_W_D : Float_Reg2<"ftintrm.w.d", FGR64Opnd>, R2F<0b1010000010>; ++def FTINTRM_L_S : Float_Reg2<"ftintrm.l.s", FGR32Opnd>, R2F<0b1010001001>; ++def FTINTRM_L_D : Float_Reg2<"ftintrm.l.d", FGR64Opnd>, R2F<0b1010001010>; ++def FTINTRP_W_S : Float_Reg2<"ftintrp.w.s", FGR32Opnd>, R2F<0b1010010001>; ++def FTINTRP_W_D : Float_Reg2<"ftintrp.w.d", FGR64Opnd>, R2F<0b1010010010>; ++def FTINTRP_L_S : Float_Reg2<"ftintrp.l.s", FGR32Opnd>, R2F<0b1010011001>; ++def FTINTRP_L_D : Float_Reg2<"ftintrp.l.d", FGR64Opnd>, R2F<0b1010011010>; ++def FTINTRZ_W_S : Float_Reg2<"ftintrz.w.s", FGR32Opnd>, R2F<0b1010100001>; ++def FTINTRZ_L_D : Float_Reg2<"ftintrz.l.d", FGR64Opnd>, R2F<0b1010101010>; ++def FTINTRNE_W_S : Float_Reg2<"ftintrne.w.s", FGR32Opnd>, R2F<0b1010110001>; ++def FTINTRNE_W_D : Float_Reg2<"ftintrne.w.d", FGR64Opnd>, R2F<0b1010110010>; ++def FTINTRNE_L_S : Float_Reg2<"ftintrne.l.s", FGR32Opnd>, R2F<0b1010111001>; ++def FTINTRNE_L_D : Float_Reg2<"ftintrne.l.d", FGR64Opnd>, R2F<0b1010111010>; ++ ++def FTINT_W_S : Float_CVT<"ftint.w.s", FGR32Opnd, FGR32Opnd>, R2F<0b1011000001>; ++def FTINT_W_D : Float_CVT<"ftint.w.d", FGR32Opnd, FGR64Opnd>, R2F<0b1011000010>; ++def FTINT_L_S : Float_CVT<"ftint.l.s", FGR64Opnd, FGR32Opnd>, R2F<0b1011001001>; ++def FTINT_L_D : Float_CVT<"ftint.l.d", FGR64Opnd, FGR64Opnd>, R2F<0b1011001010>; ++def FFINT_S_W : Float_CVT<"ffint.s.w", FGR32Opnd, FGR32Opnd>, R2F<0b1101000100>; ++def FFINT_S_L : Float_CVT<"ffint.s.l", FGR32Opnd, FGR64Opnd>, R2F<0b1101000110>; ++def FFINT_D_W : Float_CVT<"ffint.d.w", FGR64Opnd, FGR32Opnd>, R2F<0b1101001000>; ++def FFINT_D_L : Float_CVT<"ffint.d.l", FGR64Opnd, FGR64Opnd>, R2F<0b1101001010>; ++ ++def FRINT_S : Float_Reg2<"frint.s", FGR32Opnd, frint>, R2F<0b1110010001>; ++def FRINT_D : Float_Reg2<"frint.d", FGR64Opnd, frint>, R2F<0b1110010010>; ++ ++/// ++/// R3 ++/// ++def FADD_S : Float_Reg3<"fadd.s", FGR32Opnd, fadd>, R3F<0b000001>; ++def FADD_D : Float_Reg3<"fadd.d", FGR64Opnd, fadd>, R3F<0b000010>; ++def FSUB_S : Float_Reg3<"fsub.s", FGR32Opnd, fsub>, R3F<0b000101>; ++def FSUB_D : Float_Reg3<"fsub.d", FGR64Opnd, fsub>, R3F<0b000110>; ++def FMUL_S : Float_Reg3<"fmul.s", FGR32Opnd, fmul>, R3F<0b001001>; ++def FMUL_D : Float_Reg3<"fmul.d", FGR64Opnd, fmul>, R3F<0b001010>; ++def FDIV_S : Float_Reg3<"fdiv.s", FGR32Opnd, fdiv>, R3F<0b001101>; ++def FDIV_D : Float_Reg3<"fdiv.d", FGR64Opnd, fdiv>, R3F<0b001110>; ++def FMAX_S : Float_Reg3<"fmax.s", FGR32Opnd, fmaxnum_ieee>, R3F<0b010001>; ++def FMAX_D : Float_Reg3<"fmax.d", FGR64Opnd, fmaxnum_ieee>, R3F<0b010010>; ++def FMIN_S : Float_Reg3<"fmin.s", FGR32Opnd, fminnum_ieee>, R3F<0b010101>; ++def FMIN_D : Float_Reg3<"fmin.d", FGR64Opnd, fminnum_ieee>, R3F<0b010110>; ++def FMAXA_S : Float_Reg3_Fmaxa<"fmaxa.s", FGR32Opnd>, R3F<0b011001>; ++def FMAXA_D : Float_Reg3_Fmaxa<"fmaxa.d", FGR64Opnd>, R3F<0b011010>; ++def FMINA_S : Float_Reg3_Fmaxa<"fmina.s", FGR32Opnd>, R3F<0b011101>; ++def FMINA_D : Float_Reg3_Fmaxa<"fmina.d", FGR64Opnd>, R3F<0b011110>; ++def FSCALEB_S : Float_Reg3<"fscaleb.s", FGR32Opnd>, R3F<0b100001>; ++def FSCALEB_D : Float_Reg3<"fscaleb.d", FGR64Opnd>, R3F<0b100010>; ++def FCOPYSIGN_S : Float_Reg3<"fcopysign.s", FGR32Opnd, fcopysign>, R3F<0b100101>; ++def FCOPYSIGN_D : Float_Reg3<"fcopysign.d", FGR64Opnd, fcopysign>, R3F<0b100110>; ++/// ++/// R4_IMM21 ++/// ++def FMADD_S : Mul_Reg4<"fmadd.s", FGR32Opnd>, R4MUL<0b0001>; ++def FMADD_D : Mul_Reg4<"fmadd.d", FGR64Opnd>, R4MUL<0b0010>; ++def FMSUB_S : Mul_Reg4<"fmsub.s", FGR32Opnd>, R4MUL<0b0101>; ++def FMSUB_D : Mul_Reg4<"fmsub.d", FGR64Opnd>, R4MUL<0b0110>; ++def FNMADD_S : NMul_Reg4<"fnmadd.s", FGR32Opnd>, R4MUL<0b1001>; ++def FNMADD_D : NMul_Reg4<"fnmadd.d", FGR64Opnd>, R4MUL<0b1010>; ++def FNMSUB_S : NMul_Reg4<"fnmsub.s", FGR32Opnd>, R4MUL<0b1101>; ++def FNMSUB_D : NMul_Reg4<"fnmsub.d", FGR64Opnd>, R4MUL<0b1110>; ++ ++ ++// fmadd: fj * fk + fa ++def : LoongArchPat<(fma FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa), ++ (FMADD_D $fj, $fk, $fa)>; ++ ++def : LoongArchPat<(fma FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa), ++ (FMADD_S $fj, $fk, $fa)>; ++ ++ ++// fmsub: fj * fk - fa ++def : LoongArchPat<(fma FGR64Opnd:$fj, FGR64Opnd:$fk, (fneg FGR64Opnd:$fa)), ++ (FMSUB_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; ++ ++def : LoongArchPat<(fma FGR32Opnd:$fj, FGR32Opnd:$fk, (fneg FGR32Opnd:$fa)), ++ (FMSUB_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; ++ ++ ++// fnmadd: -(fj * fk + fa) ++def : LoongArchPat<(fma (fneg FGR64Opnd:$fj), FGR64Opnd:$fk, (fneg FGR64Opnd:$fa)), ++ (FNMADD_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; ++ ++def : LoongArchPat<(fma (fneg FGR32Opnd:$fj), FGR32Opnd:$fk, (fneg FGR32Opnd:$fa)), ++ (FNMADD_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; ++ ++// fnmsub: -(fj * fk - fa) ++def : LoongArchPat<(fma (fneg FGR64Opnd:$fj), FGR64Opnd:$fk, FGR64Opnd:$fa), ++ (FNMSUB_D FGR64Opnd:$fj, FGR64Opnd:$fk, FGR64Opnd:$fa)>; ++ ++def : LoongArchPat<(fma (fneg FGR32Opnd:$fj), FGR32Opnd:$fk, FGR32Opnd:$fa), ++ (FNMSUB_S FGR32Opnd:$fj, FGR32Opnd:$fk, FGR32Opnd:$fa)>; ++ ++let Pattern = [] in { ++defm S : FCMP_COND_M<0b01, "s", FGR32Opnd>; ++defm D : FCMP_COND_M<0b10, "d", FGR64Opnd>; ++} ++// ++//defm S : FCmp_Pats; ++//defm D : FCmp_Pats; ++ ++/// ++/// Float point branching ++/// ++def LoongArch_BRANCH_F : PatLeaf<(i32 0)>; ++def LoongArch_BRANCH_T : PatLeaf<(i32 1)>; ++ ++def BCEQZ : BceqzBr<"bceqz", brtarget, LoongArch_BRANCH_F>, R1_BCEQZ<0>; ++def BCNEZ : BceqzBr<"bcnez", brtarget, LoongArch_BRANCH_T>, R1_BCEQZ<1>; ++ ++/// ++/// FMOV ++/// ++def MOVGR2FCSR : Gpr_2_Fcsr<"movgr2fcsr", GPR64Opnd>, MOVGPR2FCSR; ++def MOVFCSR2GR : Fcsr_2_Gpr<"movfcsr2gr", GPR64Opnd>, MOVFCSR2GPR; ++def MOVFR2CF : Fgr_2_Fcfr<"movfr2cf", FGR64Opnd>, MOVFGR2FCFR; ++def MOVCF2FR : Fcfr_2_Fgr<"movcf2fr", FGR64Opnd>, MOVFCFR2FGR; ++def MOVGR2CF : Gpr_2_Fcfr<"movgr2cf", GPR64Opnd>, MOVGPR2FCFR; ++def MOVCF2GR : Fcfr_2_Gpr<"movcf2gr", GPR64Opnd>, MOVFCFR2GPR; ++ ++let isCodeGenOnly = 1 in { ++ def MOVFR2CF32 : Fgr_2_Fcfr<"movfr2cf", FGR32Opnd>, MOVFGR2FCFR; ++ def MOVCF2FR32 : Fcfr_2_Fgr<"movcf2fr", FGR32Opnd>, MOVFCFR2FGR; ++ def MOVGR2CF32 : Gpr_2_Fcfr<"movgr2cf", GPR32Opnd>, MOVGPR2FCFR; ++ def MOVCF2GR32 : Fcfr_2_Gpr<"movcf2gr", GPR32Opnd>, MOVFCFR2GPR; ++} ++ ++class Sel_Reg4 ++ : InstForm<(outs RO:$fd), (ins FCFROpnd:$ca, RO:$fj, RO:$fk), ++ !strconcat(opstr, "\t$fd, $fj, $fk, $ca"), ++ [(set RO:$fd, (LoongArchFSEL RO:$fj, FCFROpnd:$ca, RO:$fk))], ++ FrmR, opstr>{ ++ let Defs = [FCC0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6]; ++ let hasFCCRegOperand = 1; ++ } ++ ++def FSEL_T_S : Sel_Reg4<"fsel", FGR32Opnd>, R4SEL; ++let isCodeGenOnly = 1 in { ++ def FSEL_T_D : Sel_Reg4<"fsel", FGR64Opnd>, R4SEL; ++} ++ ++/// ++/// Mem access ++/// ++def FLD_S : FLd<"fld.s", FGR32Opnd, mem, load>, LOAD_STORE<0b1100>; ++def FST_S : FSt<"fst.s", FGR32Opnd, mem, store>, LOAD_STORE<0b1101>; ++def FLD_D : FLd<"fld.d", FGR64Opnd, mem, load>, LOAD_STORE<0b1110>; ++def FST_D : FSt<"fst.d", FGR64Opnd, mem, store>, LOAD_STORE<0b1111>; ++ ++def FLDX_S : FLDX<"fldx.s", FGR32Opnd, load>, R3MF<0b01100000>; ++def FLDX_D : FLDX<"fldx.d", FGR64Opnd, load>, R3MF<0b01101000>; ++def FSTX_S : FSTX<"fstx.s", FGR32Opnd, store>, R3MF<0b01110000>; ++def FSTX_D : FSTX<"fstx.d", FGR64Opnd, store>, R3MF<0b01111000>; ++ ++def FLDGT_S : Float_Int_Reg3<"fldgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101000>; ++def FLDGT_D : Float_Int_Reg3<"fldgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101001>; ++def FLDLE_S : Float_Int_Reg3<"fldle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101010>; ++def FLDLE_D : Float_Int_Reg3<"fldle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101011>; ++def FSTGT_S : Float_STGT_LE<"fstgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101100>; ++def FSTGT_D : Float_STGT_LE<"fstgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101101>; ++def FSTLE_S : Float_STGT_LE<"fstle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101110>; ++def FSTLE_D : Float_STGT_LE<"fstle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101111>; ++ ++let isPseudo = 1, isCodeGenOnly = 1 in { ++ def PseudoFFINT_S_W : Float_CVT<"", FGR32Opnd, GPR32Opnd>; ++ def PseudoFFINT_D_W : Float_CVT<"", FGR64Opnd, GPR32Opnd>; ++ def PseudoFFINT_S_L : Float_CVT<"", FGR64Opnd, GPR64Opnd>; ++ def PseudoFFINT_D_L : Float_CVT<"", FGR64Opnd, GPR64Opnd>; ++} ++ ++def : LoongArchPat<(f32 (fpround FGR64Opnd:$src)), ++ (FCVT_S_D FGR64Opnd:$src)>; ++def : LoongArchPat<(f64 (fpextend FGR32Opnd:$src)), ++ (FCVT_D_S FGR32Opnd:$src)>; ++ ++def : LoongArchPat<(f32 (sint_to_fp GPR32Opnd:$src)), ++ (PseudoFFINT_S_W GPR32Opnd:$src)>; ++def : LoongArchPat<(f64 (sint_to_fp GPR32Opnd:$src)), ++ (PseudoFFINT_D_W GPR32Opnd:$src)>; ++def : LoongArchPat<(f32 (sint_to_fp GPR64Opnd:$src)), ++ (EXTRACT_SUBREG (PseudoFFINT_S_L GPR64Opnd:$src), sub_lo)>; ++def : LoongArchPat<(f64 (sint_to_fp GPR64Opnd:$src)), ++ (PseudoFFINT_D_L GPR64Opnd:$src)>; ++ ++def : LoongArchPat<(f32 fpimm0), (MOVGR2FR_W ZERO)>; ++def : LoongArchPat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W ZERO))>; ++def : LoongArchPat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W ZERO, 1)))>; ++def : LoongArchPat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D ZERO_64, 1)))>; ++ ++// Patterns for loads/stores with a reg+imm operand. ++let AddedComplexity = 40 in { ++ def : LoadRegImmPat; ++ def : StoreRegImmPat; ++ def : LoadRegImmPat; ++ def : StoreRegImmPat; ++} ++ ++def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), ++ (FTINTRZ_W_S FGR32Opnd:$src)>; ++ ++def : LoongArchPat<(LoongArchTruncIntFP FGR64Opnd:$src), ++ (FTINTRZ_L_D FGR64Opnd:$src)>; ++ ++def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), ++ (FCVT_D_S (FTINTRZ_W_S FGR32Opnd:$src))>; ++ ++def : LoongArchPat<(f32 (fcopysign FGR32Opnd:$lhs, FGR64Opnd:$rhs)), ++ (FCOPYSIGN_S FGR32Opnd:$lhs, (FCVT_S_D FGR64Opnd:$rhs))>; ++def : LoongArchPat<(f64 (fcopysign FGR64Opnd:$lhs, FGR32Opnd:$rhs)), ++ (FCOPYSIGN_D FGR64Opnd:$lhs, (FCVT_D_S FGR32Opnd:$rhs))>; ++ ++let PrintMethod = "printFCCOperand",EncoderMethod = "getFCMPEncoding" in ++ def condcode : Operand; ++ ++class CEQS_FT : ++ InstForm<(outs), (ins RC:$fj, RC:$fk, condcode:$cond), ++ !strconcat("fcmp.$cond.", typestr, "\t$$fcc0, $fj, $fk"), ++ [(OpNode RC:$fj, RC:$fk, imm:$cond)], FrmFR, ++ !strconcat("fcmp.$cond.", typestr)>, HARDFLOAT { ++ let Defs = [FCC0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6, FCC7]; ++ let isCodeGenOnly = 1; ++ let hasFCCRegOperand = 1; ++} ++ ++def FCMP_S32 : CEQS_FT<"s", FGR32, LoongArchFPCmp>, CEQS_FM<0b01> { ++ bits<3> cd = 0; ++} ++def FCMP_D64 : CEQS_FT<"d", FGR64, LoongArchFPCmp>, CEQS_FM<0b10>{ ++ bits<3> cd = 0; ++} ++ ++ ++//multiclass FCmp_Pats2 { ++// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), ++// (!cast("SFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), ++// (!cast("SFCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), ++// (!cast("SFCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), ++// (!cast("SFCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), ++// (!cast("SFCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), ++// (NOROp ++// (!cast("SFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), ++// ZEROReg)>; ++// ++// def : LoongArchPat<(seteq VT:$lhs, VT:$rhs), ++// (!cast("DFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setgt VT:$lhs, VT:$rhs), ++// (!cast("DFCMP_CLE_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setge VT:$lhs, VT:$rhs), ++// (!cast("DFCMP_CLT_"#NAME) VT:$rhs, VT:$lhs)>; ++// def : LoongArchPat<(setlt VT:$lhs, VT:$rhs), ++// (!cast("DFCMP_CLT_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setle VT:$lhs, VT:$rhs), ++// (!cast("DFCMP_CLE_"#NAME) VT:$lhs, VT:$rhs)>; ++// def : LoongArchPat<(setne VT:$lhs, VT:$rhs), ++// (NOROp ++// (!cast("DFCMP_CEQ_"#NAME) VT:$lhs, VT:$rhs), ++// ZEROReg)>; ++// } ++// ++//defm S : FCmp_Pats2; ++//defm D : FCmp_Pats2; ++ ++let usesCustomInserter = 1 in { ++ class Select_Pseudo : ++ LoongArchPseudo<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), ++ [(set RC:$dst, (select GPR32Opnd:$cond, RC:$T, RC:$F))]>; ++ ++ class SelectFP_Pseudo_T : ++ LoongArchPseudo<(outs RC:$dst), (ins FCFROpnd:$cond, RC:$T, RC:$F), ++ [(set RC:$dst, (LoongArchCMovFP_T RC:$T, FCFROpnd:$cond, RC:$F))]>; ++ ++ class SelectFP_Pseudo_F : ++ LoongArchPseudo<(outs RC:$dst), (ins FCFROpnd:$cond, RC:$T, RC:$F), ++ [(set RC:$dst, (LoongArchCMovFP_F RC:$T, FCFROpnd:$cond, RC:$F))]>; ++} ++ ++def PseudoSELECT_I : Select_Pseudo; ++def PseudoSELECT_I64 : Select_Pseudo; ++def PseudoSELECT_S : Select_Pseudo; ++def PseudoSELECT_D64 : Select_Pseudo; ++ ++def PseudoSELECTFP_T_I : SelectFP_Pseudo_T; ++def PseudoSELECTFP_T_I64 : SelectFP_Pseudo_T; ++ ++def PseudoSELECTFP_F_I : SelectFP_Pseudo_F; ++def PseudoSELECTFP_F_I64 : SelectFP_Pseudo_F; ++ ++class ABSS_FT : ++ InstForm<(outs DstRC:$fd), (ins SrcRC:$fj), !strconcat(opstr, "\t$fd, $fj"), ++ [(set DstRC:$fd, (OpNode SrcRC:$fj))], FrmFR, opstr>; ++ ++def TRUNC_W_D : ABSS_FT<"ftintrz.w.d", FGR32Opnd, FGR64Opnd>, R2F<0b1010100010>; ++ ++def FTINTRZ_L_S : ABSS_FT<"ftintrz.l.s", FGR64Opnd, FGR32Opnd>, R2F<0b1010101001>; ++ ++def : LoongArchPat<(LoongArchTruncIntFP FGR64Opnd:$src), ++ (TRUNC_W_D FGR64Opnd:$src)>; ++ ++def : LoongArchPat<(LoongArchTruncIntFP FGR32Opnd:$src), ++ (FTINTRZ_L_S FGR32Opnd:$src)>; ++ ++def : Pat<(fcanonicalize FGR32Opnd:$src), (FMAX_S $src, $src)>; ++def : Pat<(fcanonicalize FGR64Opnd:$src), (FMAX_D $src, $src)>; ++ ++def : LoongArchPat<(i64 (sext (i32 (bitconvert FGR32Opnd:$src)))), ++ (MOVFR2GR_DS FGR32Opnd:$src)>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td +new file mode 100644 +index 000000000..8e255f857 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrFormats.td +@@ -0,0 +1,448 @@ ++//===- LoongArchLASXInstrFormats.td - LoongArch LASX Instruction Formats ---*- tablegen -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++class LASXInst : InstLA<(outs), (ins), "", [], FrmOther>, ++ EXT_LASX { ++} ++ ++class LASXCBranch : LASXInst { ++} ++ ++class LASXSpecial : LASXInst { ++} ++ ++class LASXPseudo pattern>: ++ LoongArchPseudo { ++ let Predicates = [HasLASX]; ++} ++ ++class LASX_3R op>: LASXInst { ++ bits<5> xk; ++ bits<5> xj; ++ bits<5> xd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = xk; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_4R op>: LASXInst { ++ bits<5> xa; ++ bits<5> xk; ++ bits<5> xj; ++ bits<5> xd; ++ ++ let Inst{31-20} = op; ++ let Inst{19-15} = xa; ++ let Inst{14-10} = xk; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_XVFCMP op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<5> xk; ++ bits<5> cond; ++ ++ let Inst{31-20} = op; ++ let Inst{19-15} = cond; ++ let Inst{14-10} = xk; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I12_S op>: LASXInst { ++ bits<5> xd; ++ bits<17> addr; ++ ++ let Inst{31-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI12_S op>: LASXInst { ++ bits<5> xd; ++ bits<17> addr; ++ ++ let Inst{31-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI11_S op>: LASXInst { ++ bits<5> xd; ++ bits<16> addr; ++ ++ let Inst{31-21} = op; ++ let Inst{20-10} = addr{10-0}; ++ let Inst{9-5} = addr{15-11}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI10_S op>: LASXInst { ++ bits<5> xd; ++ bits<15> addr; ++ ++ let Inst{31-20} = op; ++ let Inst{19-10} = addr{9-0}; ++ let Inst{9-5} = addr{14-10}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI9_S op>: LASXInst { ++ bits<5> xd; ++ bits<14> addr; ++ ++ let Inst{31-19} = op; ++ let Inst{18-10} = addr{8-0}; ++ let Inst{9-5} = addr{13-9}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI8_idx5 op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<5> idx; ++ ++ let Inst{31-23} = op; ++ let Inst{22-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI8_idx2 op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<2> idx; ++ ++ let Inst{31-20} = op; ++ let Inst{19-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI8_idx3 op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<3> idx; ++ ++ let Inst{31-21} = op; ++ let Inst{20-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SI8_idx4 op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<4> idx; ++ ++ let Inst{31-22} = op; ++ let Inst{21-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_3R_2GP op>: LASXInst { ++ bits<5> rk; ++ bits<5> rj; ++ bits<5> xd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_3R_1GP op>: LASXInst { ++ bits<5> rk; ++ bits<5> xj; ++ bits<5> xd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I5 op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<5> si5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = si5; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I5_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<5> ui5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = ui5; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I5_mode_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> mode; ++ bits<5> ui5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = ui5; ++ let Inst{9-5} = mode; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_2R op>: LASXInst { ++ bits<5> xj; ++ bits<5> xd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_SET op>: LASXInst { ++ bits<5> xj; ++ bits<3> cd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = xj; ++ let Inst{4-3} = 0b00; ++ let Inst{2-0} = cd; ++} ++ ++class LASX_2R_1GP op>: LASXInst { ++ bits<5> rj; ++ bits<5> xd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I3_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I4_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I6_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<6> ui6; ++ ++ let Inst{31-16} = op; ++ let Inst{15-10} = ui6; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I2_R_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I3_R_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_ELM_COPY_U3 op>: LASXInst { ++ bits<5> rd; ++ bits<5> xj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = rd; ++} ++ ++class LASX_ELM_COPY_U2 op>: LASXInst { ++ bits<5> rd; ++ bits<5> xj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = rd; ++} ++ ++class LASX_I1_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I2_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I7_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<7> ui7; ++ ++ let Inst{31-17} = op; ++ let Inst{16-10} = ui7; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_1R_I13 op>: LASXInst { ++ bits<13> i13; ++ bits<5> xd; ++ ++ let Inst{31-18} = op; ++ let Inst{17-5} = i13; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I8_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> xj; ++ bits<8> ui8; ++ ++ let Inst{31-18} = op; ++ let Inst{17-10} = ui8; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = xd; ++} ++ ++ ++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ++class LASX_I1_R_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_I4_R_U op>: LASXInst { ++ bits<5> xd; ++ bits<5> rj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_ELM_COPY_B op>: LASXInst { ++ bits<5> rd; ++ bits<5> xj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = rd; ++} ++ ++class LASX_ELM_COPY_D op>: LASXInst { ++ bits<5> rd; ++ bits<5> xj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = xj; ++ let Inst{4-0} = rd; ++} ++ ++class LASX_Addr_SI8_idx1 op>: LASXInst { ++ bits<5> xd; ++ bits<13> addr; ++ bits<1> idx; ++ ++ let Inst{31-19} = op; ++ let Inst{18-11} = addr{7-0}; ++ let Inst{10} = idx; ++ let Inst{9-5} = addr{12-8}; ++ let Inst{4-0} = xd; ++} ++ ++class LASX_1R_I13_I10 op>: LASXInst { ++ bits<10> i10; ++ bits<5> xd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-5} = i10; ++ let Inst{4-0} = xd; ++} ++ ++ ++ ++ ++ ++ +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +new file mode 100644 +index 000000000..2677a79fa +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +@@ -0,0 +1,5673 @@ ++//===- LoongArchLASXInstrInfo.td - loongson LASX instructions -*- tablegen ------------*-=// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file describes loongson ASX instructions. ++// ++//===----------------------------------------------------------------------===// ++def SDT_XVPERMI : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, ++ SDTCisSameAs<0, 1>, ++ SDTCisVT<2, i32>]>; ++def SDT_XVSHFI : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>, ++ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, ++ SDTCisVT<3, i32>]>; ++def SDT_XVBROADCAST : SDTypeProfile<1, 1, [SDTCisVec<0>]>; ++ ++def SDT_INSVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, ++ SDTCisSameAs<1, 2>, ++ SDTCisVT<3, i32>]>; ++ ++def SDT_XVPICKVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, ++ SDTCisSameAs<1, 2>, ++ SDTCisVT<3, i32>]>; ++ ++def SDT_XVSHUF4I : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisInt<0>, ++ SDTCisSameAs<0, 1>, ++ SDTCisSameAs<0, 2>, ++ SDTCisVT<3, i32>]>; ++ ++def LoongArchXVSHUFI : SDNode<"LoongArchISD::XVSHFI", SDT_XVSHFI>; ++ ++def LoongArchXVSELI : SDNode<"LoongArchISD::XVSELI", SDT_XVSHFI>; ++ ++def LoongArchXVPERMI : SDNode<"LoongArchISD::XVPERMI", SDT_XVPERMI>; ++ ++def LoongArchXVBROADCAST : SDNode<"LoongArchISD::XVBROADCAST", SDT_XVBROADCAST>; ++ ++def LoongArchINSVE : SDNode<"LoongArchISD::INSVE", SDT_INSVE>; ++ ++def LoongArchXVSHUF4I : SDNode<"LoongArchISD::XVSHUF4I", SDT_XVSHUF4I>; ++ ++def LoongArchXVPICKVE : SDNode<"LoongArchISD::XVPICKVE", SDT_INSVE>; ++ ++def xvbroadcast_v32i8 : PatFrag<(ops node:$v1), ++ (v32i8 (LoongArchXVBROADCAST node:$v1))>; ++def xvbroadcast_v16i16 : PatFrag<(ops node:$v1), ++ (v16i16 (LoongArchXVBROADCAST node:$v1))>; ++def xvbroadcast_v8i32 : PatFrag<(ops node:$v1), ++ (v8i32 (LoongArchXVBROADCAST node:$v1))>; ++def xvbroadcast_v4i64 : PatFrag<(ops node:$v1), ++ (v4i64 (LoongArchXVBROADCAST node:$v1))>; ++ ++ ++def vfseteq_v8f32 : vfsetcc_type; ++def vfseteq_v4f64 : vfsetcc_type; ++def vfsetge_v8f32 : vfsetcc_type; ++def vfsetge_v4f64 : vfsetcc_type; ++def vfsetgt_v8f32 : vfsetcc_type; ++def vfsetgt_v4f64 : vfsetcc_type; ++def vfsetle_v8f32 : vfsetcc_type; ++def vfsetle_v4f64 : vfsetcc_type; ++def vfsetlt_v8f32 : vfsetcc_type; ++def vfsetlt_v4f64 : vfsetcc_type; ++def vfsetne_v8f32 : vfsetcc_type; ++def vfsetne_v4f64 : vfsetcc_type; ++def vfsetoeq_v8f32 : vfsetcc_type; ++def vfsetoeq_v4f64 : vfsetcc_type; ++def vfsetoge_v8f32 : vfsetcc_type; ++def vfsetoge_v4f64 : vfsetcc_type; ++def vfsetogt_v8f32 : vfsetcc_type; ++def vfsetogt_v4f64 : vfsetcc_type; ++def vfsetole_v8f32 : vfsetcc_type; ++def vfsetole_v4f64 : vfsetcc_type; ++def vfsetolt_v8f32 : vfsetcc_type; ++def vfsetolt_v4f64 : vfsetcc_type; ++def vfsetone_v8f32 : vfsetcc_type; ++def vfsetone_v4f64 : vfsetcc_type; ++def vfsetord_v8f32 : vfsetcc_type; ++def vfsetord_v4f64 : vfsetcc_type; ++def vfsetun_v8f32 : vfsetcc_type; ++def vfsetun_v4f64 : vfsetcc_type; ++def vfsetueq_v8f32 : vfsetcc_type; ++def vfsetueq_v4f64 : vfsetcc_type; ++def vfsetuge_v8f32 : vfsetcc_type; ++def vfsetuge_v4f64 : vfsetcc_type; ++def vfsetugt_v8f32 : vfsetcc_type; ++def vfsetugt_v4f64 : vfsetcc_type; ++def vfsetule_v8f32 : vfsetcc_type; ++def vfsetule_v4f64 : vfsetcc_type; ++def vfsetult_v8f32 : vfsetcc_type; ++def vfsetult_v4f64 : vfsetcc_type; ++def vfsetune_v8f32 : vfsetcc_type; ++def vfsetune_v4f64 : vfsetcc_type; ++ ++def xvsplati8 : PatFrag<(ops node:$e0), ++ (v32i8 (build_vector ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0))>; ++def xvsplati16 : PatFrag<(ops node:$e0), ++ (v16i16 (build_vector ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0))>; ++def xvsplati32 : PatFrag<(ops node:$e0), ++ (v8i32 (build_vector ++ node:$e0, node:$e0, node:$e0, node:$e0, ++ node:$e0, node:$e0, node:$e0, node:$e0))>; ++def xvsplati64 : PatFrag<(ops node:$e0), ++ (v4i64 (build_vector ++ node:$e0, node:$e0, node:$e0, node:$e0))>; ++def xvsplatf32 : PatFrag<(ops node:$e0), ++ (v8f32 (build_vector node:$e0, node:$e0, ++ node:$e0, node:$e0))>; ++def xvsplatf64 : PatFrag<(ops node:$e0), ++ (v4f64 (build_vector node:$e0, node:$e0))>; ++ ++def xvsplati8_uimm3 : SplatComplexPattern; ++def xvsplati16_uimm4 : SplatComplexPattern; ++ ++def xvsplati64_uimm6 : SplatComplexPattern; ++ ++def xvsplati8_simm5 : SplatComplexPattern; ++def xvsplati16_simm5 : SplatComplexPattern; ++def xvsplati32_simm5 : SplatComplexPattern; ++def xvsplati64_simm5 : SplatComplexPattern; ++ ++def xvsplat_imm_eq_1 : PatLeaf<(build_vector), [{ ++ APInt Imm; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ return selectVSplat(N, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; ++}]>; ++ ++def xvsplati64_imm_eq_1 : PatLeaf<(bitconvert (v8i32 (build_vector))), [{ ++ APInt Imm; ++ SDNode *BV = N->getOperand(0).getNode(); ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; ++}]>; ++ ++def xvbitclr_b : PatFrag<(ops node:$xk, node:$xa), ++ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), ++ immAllOnesV))>; ++def xvbitclr_h : PatFrag<(ops node:$xk, node:$xa), ++ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), ++ immAllOnesV))>; ++def xvbitclr_w : PatFrag<(ops node:$xk, node:$xa), ++ (and node:$xk, (xor (shl vsplat_imm_eq_1, node:$xa), ++ immAllOnesV))>; ++def xvbitclr_d : PatFrag<(ops node:$xk, node:$xa), ++ (and node:$xk, (xor (shl (v4i64 vsplati64_imm_eq_1), ++ node:$xa), ++ (bitconvert (v8i32 immAllOnesV))))>; ++ ++ ++ ++def xvsplati8_uimm5 : SplatComplexPattern; ++def xvsplati16_uimm5 : SplatComplexPattern; ++def xvsplati32_uimm5 : SplatComplexPattern; ++def xvsplati64_uimm5 : SplatComplexPattern; ++def xvsplati8_uimm8 : SplatComplexPattern; ++def xvsplati16_uimm8 : SplatComplexPattern; ++def xvsplati32_uimm8 : SplatComplexPattern; ++def xvsplati64_uimm8 : SplatComplexPattern; ++ ++ ++ ++def xvsplati8_uimm4 : SplatComplexPattern; ++def xvsplati16_uimm3 : SplatComplexPattern; ++def xvsplati32_uimm2 : SplatComplexPattern; ++def xvsplati64_uimm1 : SplatComplexPattern; ++ ++ ++// Patterns. ++class LASXPat pred = [HasLASX]> : ++ Pat, Requires; ++ ++class LASX_4RF { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk, ROXA:$xa); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk, $xa"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk, ROXA:$xa))]; ++} ++ ++class LASX_3RF { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; ++} ++ ++class LASX_3R_SETCC_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, ROXK:$xk, CC)))]; ++} ++ ++class LASX_LD { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); ++ list Pattern = [(set ROXD:$xd, (TyNode (OpNode Addr:$addr)))]; ++ string DecoderMethod = "DecodeLASX256Mem"; ++} ++ ++class LASX_ST { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); ++ list Pattern = [(OpNode (TyNode ROXD:$xd), Addr:$addr)]; ++ string DecoderMethod = "DecodeLASX256Mem"; ++} ++ ++class LASX_I8_U5_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm5:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt5:$idx)]; ++ string DecoderMethod = "DecodeLASX256memstl"; ++} ++ ++class LASX_I8_U2_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm2:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt2:$idx)]; ++ string DecoderMethod = "DecodeLASX256memstl"; ++} ++ ++class LASX_I8_U3_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm3:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt3:$idx)]; ++ string DecoderMethod = "DecodeLASX256memstl"; ++} ++ ++class LASX_I8_U4_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, ImmOp:$si8, uimm4:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, Imm:$si8, immZExt4:$idx)]; ++ string DecoderMethod = "DecodeLASX256memstl"; ++} ++ ++class LASX_SDX_LA { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, RORK:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk"); ++ list Pattern = [(OpNode ROXD:$xd, iPTR:$rj, RORK:$rk)]; ++} ++ ++class LASX_3R_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; ++} ++ ++class LASX_LDX_LA { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins PtrRC:$rj, RORK:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk"); ++ list Pattern = [(set ROXD:$xd, (OpNode iPTR:$rj, RORK:$rk))]; ++} ++ ++class LASX_3R_4R_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, ++ ROXK:$xk))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++ ++class LASX_3R_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, GPR32Opnd:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $rk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, GPR32Opnd:$rk))]; ++} ++ ++ ++class LASX_3R_VREPLVE_DESC_BASE_N { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, GPR64Opnd:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $rk"); ++ list Pattern = []; ++} ++ ++ ++class LASX_VEC_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]; ++} ++ ++ ++ ++class LASX_3RF_DESC_BASE : ++ LASX_3R_DESC_BASE; ++ ++ ++class LASX_3R_DESC_BASE1 { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xk, ROXK:$xj))]; ++} ++ ++class LASX_3RF_DESC_BASE1 : ++ LASX_3R_DESC_BASE1; ++ ++ ++ ++class LASX_3R_VSHF_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ROXK:$xk); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $xk"); ++ list Pattern = [(set ROXD:$xd, (LoongArchVSHF ROXD:$xd_in, ROXJ:$xj, ++ ROXK:$xk))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_I5_SETCC_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); ++ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, SplatImm:$si5, CC)))]; ++} ++ ++class LASX_I5_SETCC_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$si5))]; ++} ++ ++ ++class LASX_I5_U_SETCC_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (VT (vsetcc ROXJ:$xj, SplatImm:$ui5, CC)))]; ++} ++ ++class LASX_I5_U_SETCC_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; ++} ++ ++class LASX_VEC_PSEUDO_BASE : ++ LASXPseudo<(outs ROXD:$xd), (ins ROXJ:$xj, ROXK:$xk), ++ [(set ROXD:$xd, (OpNode ROXJ:$xj, ROXK:$xk))]>; ++ ++ ++class LASX_I5_U_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui5))]; ++} ++ ++ ++class LASX_I5_U_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; ++} ++ ++class LASX_U5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt5:$ui5))]; ++} ++ ++class LASX_U5N_DESC_BASE : ++ LASX_U5_DESC_BASE; ++ ++class LASX_U5_4R_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt5:$ui5))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj))]; ++} ++ ++class LASX_SET_DESC_BASE { ++ dag OutOperandList = (outs FCFROpnd:$cd); ++ dag InOperandList = (ins ROXD:$xj); ++ string AsmString = !strconcat(instr_asm, "\t$cd, $xj"); ++ list Pattern = []; ++} ++ ++class LASX_2RF_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj))]; ++} ++ ++class LASX_I5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$si5))]; ++} ++ ++class LASX_I5_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $si5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$si5))]; ++} ++ ++ ++class LASX_2R_REPL_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROS:$rj); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj"); ++ list Pattern = [(set ROXD:$xd, (VT (OpNode ROS:$rj)))]; ++} ++ ++class LASX_XVEXTEND_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); ++ list Pattern = [(set ROXD:$xd, (DTy (OpNode (STy ROXJ:$xj))))]; ++} ++ ++class LASX_RORI_U3_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; ++} ++ ++class LASX_RORI_U4_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; ++} ++ ++class LASX_RORI_U5_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; ++} ++ ++class LASX_RORI_U6_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; ++} ++ ++class LASX_BIT_3_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; ++} ++ ++class LASX_BIT_4_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; ++} ++ ++class LASX_BIT_5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; ++} ++ ++class LASX_BIT_6_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; ++} ++ ++class LASX_BIT_2_4O_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui2"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui2))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_BIT_2_4ON : ++ LASX_BIT_2_4O_DESC_BASE; ++ ++class LASX_BIT_3_4O_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui3))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_BIT_3_4ON : ++ LASX_BIT_3_4O_DESC_BASE; ++ ++class LASX_INSERT_U3_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROS:$rj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (VTy (insertelt (VTy ROXD:$xd_in), ROS:$rj, Imm:$ui3)))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_INSERT_U2_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROS:$rj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $ui2"); ++ list Pattern = [(set ROXD:$xd, (VTy (insertelt (VTy ROXD:$xd_in), ROS:$rj, Imm:$ui2)))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_COPY_U2_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $xj, $ui2"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROXJ:$xj), Imm:$ui2))]; ++} ++ ++class LASX_COPY_U3_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $xj, $ui3"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROXJ:$xj), Imm:$ui3))]; ++} ++ ++class LASX_ELM_U4_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt4:$ui4))]; ++} ++ ++class LASX_ELM_U3_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm3:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt3:$ui3))]; ++} ++ ++class LASX_ELM_U2_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm2:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui2"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt2:$ui2))]; ++} ++ ++class LASX_ELM_U1_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm1:$ui1); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui1"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt1:$ui1))]; ++} ++ ++class LASX_XVBROADCAST_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj"); ++ list Pattern = [(set ROXD:$xd, (OpNode (TyNode ROXJ:$xj)))]; ++} ++ ++class LASX_2R_U3_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm3:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt3:$ui3))]; ++} ++ ++class LASX_2R_U4_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt4:$ui4))]; ++} ++ ++class LASX_2R_U5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt5:$ui5))]; ++} ++ ++class LASX_2R_U6_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm6:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt6:$ui6))]; ++} ++ ++class LASX_BIT_U3_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui3))]; ++} ++ ++class LASX_BIT_U4_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui4))]; ++} ++ ++class LASX_BIT_U5_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui5))]; ++} ++ ++class LASX_BIT_U6_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui6))]; ++} ++ ++class LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui3"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui3))]; ++} ++ ++class LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui4))]; ++} ++ ++class LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui5))]; ++} ++ ++class LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, Imm:$ui6))]; ++} ++ ++class LASX_U4_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in,ROXJ:$xj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in,ROXJ:$xj, Imm:$ui4))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_N4_U5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui5))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_U6_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, Imm:$ui6))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_D_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm7:$ui7); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui7"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt7:$ui7))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U4_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui4"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt4:$ui4))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U5_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui5"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt5:$ui5))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U6_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm6:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui6"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt6:$ui6))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U7_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm7:$ui7); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui7"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt7:$ui7))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U8_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt8:$ui8))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_2R_3R_U8_SELECT { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, vsplat_uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, xvsplati8_uimm8:$ui8, ROXJ:$xj))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_I8_O4_SHF_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXD:$xd_in, ROXJ:$xj, immZExt8:$ui8))]; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class LASX_I8_SHF_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt8:$ui8))]; ++} ++ ++class LASX_2R_U8_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, immZExt8:$ui8))]; ++} ++ ++class LASX_I13_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins immOp:$i13); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $i13"); ++ list Pattern = [(set ROXD:$xd, (OpNode (Ty simm13:$i13)))]; ++ string DecoderMethod = "DecodeLASX256Mem13"; ++} ++ ++class LASX_I13_DESC_BASE_10 { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ImmOp:$i10); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $i10"); ++ bit hasSideEffects = 0; ++ string DecoderMethod = "DecodeLASX256Mem10"; ++ list Pattern = [(set ROXD:$xd, (OpNode Imm:$i10))]; ++ } ++ ++class LASX_BIT_U8_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXJ:$xj, SplatImm.OpClass:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = [(set ROXD:$xd, (OpNode ROXJ:$xj, SplatImm:$ui8))]; ++} ++ ++class LASX_2RN_3R_U8_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins ROXD:$xd_in, ROXJ:$xj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8"); ++ list Pattern = []; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++ ++//encoding ++ ++def XVFMADD_S : LASX_4R<0b000010100001>, ++ LASX_4RF<"xvfmadd.s", int_loongarch_lasx_xvfmadd_s, LASX256WOpnd>; ++ ++def XVFMADD_D : LASX_4R<0b000010100010>, ++ LASX_4RF<"xvfmadd.d", int_loongarch_lasx_xvfmadd_d, LASX256DOpnd>; ++ ++ ++def XVFMSUB_S : LASX_4R<0b000010100101>, ++ LASX_4RF<"xvfmsub.s", int_loongarch_lasx_xvfmsub_s, LASX256WOpnd>; ++ ++def XVFMSUB_D : LASX_4R<0b000010100110>, ++ LASX_4RF<"xvfmsub.d", int_loongarch_lasx_xvfmsub_d, LASX256DOpnd>; ++ ++ ++def XVFNMADD_S : LASX_4R<0b000010101001>, ++ LASX_4RF<"xvfnmadd.s", int_loongarch_lasx_xvfnmadd_s, LASX256WOpnd>; ++ ++def XVFNMADD_D : LASX_4R<0b000010101010>, ++ LASX_4RF<"xvfnmadd.d", int_loongarch_lasx_xvfnmadd_d, LASX256DOpnd>; ++ ++ ++def XVFNMSUB_S : LASX_4R<0b000010101101>, ++ LASX_4RF<"xvfnmsub.s", int_loongarch_lasx_xvfnmsub_s, LASX256WOpnd>; ++ ++def XVFNMSUB_D : LASX_4R<0b000010101110>, ++ LASX_4RF<"xvfnmsub.d", int_loongarch_lasx_xvfnmsub_d, LASX256DOpnd>; ++ ++ ++// xvfmadd: xj * xk + xa ++def : LASXPat<(fma v4f64:$xj, v4f64:$xk, v4f64:$xa), ++ (XVFMADD_D $xj, $xk, $xa)>; ++ ++def : LASXPat<(fma v8f32:$xj, v8f32:$xk, v8f32:$xa), ++ (XVFMADD_S $xj, $xk, $xa)>; ++ ++ ++// xvfmsub: xj * xk - xa ++def : LASXPat<(fma v4f64:$xj, v4f64:$xk, (fneg v4f64:$xa)), ++ (XVFMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; ++ ++def : LASXPat<(fma v8f32:$xj, v8f32:$xk, (fneg v8f32:$xa)), ++ (XVFMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; ++ ++ ++// xvfnmadd: -(xj * xk + xa) ++def : LASXPat<(fma (fneg v4f64:$xj), v4f64:$xk, (fneg v4f64:$xa)), ++ (XVFNMADD_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; ++ ++def : LASXPat<(fma (fneg v8f32:$xj), v8f32:$xk, (fneg v8f32:$xa)), ++ (XVFNMADD_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; ++ ++// xvfnmsub: -(xj * xk - xa) ++def : LASXPat<(fma (fneg v4f64:$xj), v4f64:$xk, v4f64:$xa), ++ (XVFNMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>; ++ ++def : LASXPat<(fma (fneg v8f32:$xj), v8f32:$xk, v8f32:$xa), ++ (XVFNMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>; ++ ++ ++def XVFCMP_CAF_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.caf.s", int_loongarch_lasx_xvfcmp_caf_s, LASX256WOpnd>{ ++ bits<5> cond=0x0; ++ } ++ ++def XVFCMP_CAF_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.caf.d", int_loongarch_lasx_xvfcmp_caf_d, LASX256DOpnd>{ ++ bits<5> cond=0x0; ++ } ++ ++def XVFCMP_COR_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cor.s", vfsetord_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x14; ++ } ++ ++def XVFCMP_COR_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cor.d", vfsetord_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x14; ++ } ++ ++def XVFCMP_CUN_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cun.s", vfsetun_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x8; ++ } ++ ++def XVFCMP_CUN_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cun.d", vfsetun_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x8; ++ } ++ ++def XVFCMP_CUNE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cune.s", vfsetune_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x18; ++ } ++ ++def XVFCMP_CUNE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cune.d", vfsetune_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x18; ++ } ++ ++def XVFCMP_CUEQ_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cueq.s", vfsetueq_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0xc; ++ } ++ ++def XVFCMP_CUEQ_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cueq.d", vfsetueq_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0xc; ++ } ++ ++def XVFCMP_CEQ_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.ceq.s", vfsetoeq_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x4; ++ } ++ ++def XVFCMP_CEQ_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.ceq.d", vfsetoeq_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x4; ++ } ++ ++def XVFCMP_CNE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cne.s", vfsetone_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x10; ++ } ++ ++def XVFCMP_CNE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cne.d", vfsetone_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x10; ++ } ++ ++def XVFCMP_CLT_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.clt.s", vfsetolt_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x2; ++ } ++ ++def XVFCMP_CLT_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.clt.d", vfsetolt_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x2; ++ } ++ ++def XVFCMP_CULT_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cult.s", vfsetult_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0xa; ++ } ++ ++def XVFCMP_CULT_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cult.d", vfsetult_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0xa; ++ } ++ ++def XVFCMP_CLE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cle.s", vfsetole_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0x6; ++ } ++ ++def XVFCMP_CLE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cle.d", vfsetole_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0x6; ++ } ++ ++def XVFCMP_CULE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.cule.s", vfsetule_v8f32, LASX256WOpnd>{ ++ bits<5> cond=0xe; ++ } ++ ++def XVFCMP_CULE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.cule.d", vfsetule_v4f64, LASX256DOpnd>{ ++ bits<5> cond=0xe; ++ } ++ ++def XVFCMP_SAF_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.saf.s", int_loongarch_lasx_xvfcmp_saf_s, LASX256WOpnd>{ ++ bits<5> cond=0x1; ++ } ++ ++def XVFCMP_SAF_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.saf.d", int_loongarch_lasx_xvfcmp_saf_d, LASX256DOpnd>{ ++ bits<5> cond=0x1; ++ } ++ ++def XVFCMP_SOR_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sor.s", int_loongarch_lasx_xvfcmp_sor_s, LASX256WOpnd>{ ++ bits<5> cond=0x15; ++ } ++ ++def XVFCMP_SOR_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sor.d", int_loongarch_lasx_xvfcmp_sor_d, LASX256DOpnd>{ ++ bits<5> cond=0x15; ++ } ++ ++def XVFCMP_SUN_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sun.s", int_loongarch_lasx_xvfcmp_sun_s, LASX256WOpnd>{ ++ bits<5> cond=0x9; ++ } ++ ++def XVFCMP_SUN_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sun.d", int_loongarch_lasx_xvfcmp_sun_d, LASX256DOpnd>{ ++ bits<5> cond=0x9; ++ } ++ ++def XVFCMP_SUNE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sune.s", int_loongarch_lasx_xvfcmp_sune_s, LASX256WOpnd>{ ++ bits<5> cond=0x19; ++ } ++ ++def XVFCMP_SUNE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sune.d", int_loongarch_lasx_xvfcmp_sune_d, LASX256DOpnd>{ ++ bits<5> cond=0x19; ++ } ++ ++def XVFCMP_SUEQ_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sueq.s", int_loongarch_lasx_xvfcmp_sueq_s, LASX256WOpnd>{ ++ bits<5> cond=0xd; ++ } ++ ++def XVFCMP_SUEQ_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sueq.d", int_loongarch_lasx_xvfcmp_sueq_d, LASX256DOpnd>{ ++ bits<5> cond=0xd; ++ } ++ ++def XVFCMP_SEQ_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.seq.s", int_loongarch_lasx_xvfcmp_seq_s, LASX256WOpnd>{ ++ bits<5> cond=0x5; ++ } ++ ++def XVFCMP_SEQ_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.seq.d", int_loongarch_lasx_xvfcmp_seq_d, LASX256DOpnd>{ ++ bits<5> cond=0x5; ++ } ++ ++def XVFCMP_SNE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sne.s", int_loongarch_lasx_xvfcmp_sne_s, LASX256WOpnd>{ ++ bits<5> cond=0x11; ++ } ++ ++def XVFCMP_SNE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sne.d", int_loongarch_lasx_xvfcmp_sne_d, LASX256DOpnd>{ ++ bits<5> cond=0x11; ++ } ++ ++def XVFCMP_SLT_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.slt.s", int_loongarch_lasx_xvfcmp_slt_s, LASX256WOpnd>{ ++ bits<5> cond=0x3; ++ } ++ ++def XVFCMP_SLT_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.slt.d", int_loongarch_lasx_xvfcmp_slt_d, LASX256DOpnd>{ ++ bits<5> cond=0x3; ++ } ++ ++def XVFCMP_SULT_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sult.s", int_loongarch_lasx_xvfcmp_sult_s, LASX256WOpnd>{ ++ bits<5> cond=0xb; ++ } ++ ++def XVFCMP_SULT_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sult.d", int_loongarch_lasx_xvfcmp_sult_d, LASX256DOpnd>{ ++ bits<5> cond=0xb; ++ } ++ ++def XVFCMP_SLE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sle.s", int_loongarch_lasx_xvfcmp_sle_s, LASX256WOpnd>{ ++ bits<5> cond=0x7; ++ } ++ ++def XVFCMP_SLE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sle.d", int_loongarch_lasx_xvfcmp_sle_d, LASX256DOpnd>{ ++ bits<5> cond=0x7; ++ } ++ ++def XVFCMP_SULE_S : LASX_XVFCMP<0b000011001001>, ++ LASX_3RF<"xvfcmp.sule.s", int_loongarch_lasx_xvfcmp_sule_s, LASX256WOpnd>{ ++ bits<5> cond=0xf; ++ } ++ ++def XVFCMP_SULE_D : LASX_XVFCMP<0b000011001010>, ++ LASX_3RF<"xvfcmp.sule.d", int_loongarch_lasx_xvfcmp_sule_d, LASX256DOpnd>{ ++ bits<5> cond=0xf; ++ } ++ ++ ++def XVBITSEL_V : LASX_4R<0b000011010010>, ++ LASX_4RF<"xvbitsel.v", int_loongarch_lasx_xvbitsel_v, LASX256BOpnd>; ++ ++class LASX_BSEL_PSEUDO_BASE : ++ LASXPseudo<(outs RO:$xd), (ins RO:$xd_in, RO:$xs, RO:$xt), ++ [(set RO:$xd, (Ty (vselect RO:$xd_in, RO:$xt, RO:$xs)))]>, ++ PseudoInstExpansion<(XVBITSEL_V LASX256BOpnd:$xd, LASX256BOpnd:$xs, ++ LASX256BOpnd:$xt, LASX256BOpnd:$xd_in)> { ++ let Constraints = "$xd_in = $xd"; ++} ++ ++def XBSEL_B_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++def XBSEL_H_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++def XBSEL_W_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++def XBSEL_D_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++def XBSEL_FW_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++def XBSEL_FD_PSEUDO : LASX_BSEL_PSEUDO_BASE; ++ ++ ++ ++def XVSHUF_B : LASX_4R<0b000011010110>, ++ LASX_4RF<"xvshuf.b", int_loongarch_lasx_xvshuf_b, LASX256BOpnd>; ++ ++ ++def XVLD : LASX_I12_S<0b0010110010>, ++ LASX_LD<"xvld", load, v32i8, LASX256BOpnd, mem>; ++ ++def XVST : LASX_I12_S<0b0010110011>, ++ LASX_ST<"xvst", store, v32i8, LASX256BOpnd, mem_simm12>; ++ ++ ++class LASX_LD_DESC_BASE { ++ dag OutOperandList = (outs ROXD:$xd); ++ dag InOperandList = (ins MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$xd, $addr"); ++ list Pattern = [(set ROXD:$xd, (OpNode (TyNode (load Addr:$addr))))]; ++ string DecoderMethod = "DecodeLASX256memlsl"; ++} ++ ++ ++def XVLDREPL_B : LASX_SI12_S<0b0011001010>, ++ LASX_LD_DESC_BASE<"xvldrepl.b", xvbroadcast_v32i8, v32i8, LASX256BOpnd>; ++ ++def XVLDREPL_H : LASX_SI11_S<0b00110010010>, ++ LASX_LD_DESC_BASE<"xvldrepl.h", xvbroadcast_v16i16, v16i16, LASX256HOpnd, mem_simm11_lsl1, addrimm11lsl1>; ++ ++def XVLDREPL_W : LASX_SI10_S<0b001100100010>, ++ LASX_LD_DESC_BASE<"xvldrepl.w", xvbroadcast_v8i32, v8i32, LASX256WOpnd, mem_simm10_lsl2, addrimm10lsl2>; ++ ++def XVLDREPL_D : LASX_SI9_S<0b0011001000010>, ++ LASX_LD_DESC_BASE<"xvldrepl.d", xvbroadcast_v4i64, v4i64, LASX256DOpnd, mem_simm9_lsl3, addrimm9lsl3>; ++ ++ ++def XVSTELM_B : LASX_SI8_idx5<0b001100111>, ++ LASX_I8_U5_DESC_BASE<"xvstelm.b", int_loongarch_lasx_xvstelm_b, simm8_32, immSExt8, LASX256BOpnd, GPR32Opnd>; ++ ++def XVSTELM_H : LASX_SI8_idx4<0b0011001101>, ++ LASX_I8_U4_DESC_BASE<"xvstelm.h", int_loongarch_lasx_xvstelm_h, immSExt8_1_O, immSExt8, LASX256HOpnd, GPR32Opnd>; ++ ++def XVSTELM_W : LASX_SI8_idx3<0b00110011001>, ++ LASX_I8_U3_DESC_BASE<"xvstelm.w", int_loongarch_lasx_xvstelm_w, immSExt8_2_O, immSExt8, LASX256WOpnd, GPR32Opnd>; ++ ++def XVSTELM_D : LASX_SI8_idx2<0b001100110001>, ++ LASX_I8_U2_DESC_BASE<"xvstelm.d", int_loongarch_lasx_xvstelm_d, immSExt8_3_O, immSExt8, LASX256DOpnd, GPR32Opnd>; ++ ++let mayLoad = 1, canFoldAsLoad = 1 in { ++ def XVLDX : LASX_3R_2GP<0b00111000010010000>, ++ LASX_LDX_LA<"xvldx", int_loongarch_lasx_xvldx, GPR64Opnd, LASX256BOpnd>; ++} ++ ++let mayStore = 1 in{ ++ def XVSTX : LASX_3R_2GP<0b00111000010011000>, ++ LASX_SDX_LA<"xvstx", int_loongarch_lasx_xvstx, GPR64Opnd, LASX256BOpnd>; ++} ++ ++ ++def XVSEQ_B : LASX_3R<0b01110100000000000>, IsCommutable, ++ LASX_3R_SETCC_DESC_BASE<"xvseq.b", SETEQ, v32i8, LASX256BOpnd>; ++ ++def XVSEQ_H : LASX_3R<0b01110100000000001>, IsCommutable, ++ LASX_3R_SETCC_DESC_BASE<"xvseq.h", SETEQ, v16i16, LASX256HOpnd>; ++ ++def XVSEQ_W : LASX_3R<0b01110100000000010>, IsCommutable, ++ LASX_3R_SETCC_DESC_BASE<"xvseq.w", SETEQ, v8i32, LASX256WOpnd> ; ++ ++def XVSEQ_D : LASX_3R<0b01110100000000011>, IsCommutable, ++ LASX_3R_SETCC_DESC_BASE<"xvseq.d", SETEQ, v4i64, LASX256DOpnd>; ++ ++ ++def XVSLE_B : LASX_3R<0b01110100000000100>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.b", SETLE, v32i8, LASX256BOpnd>; ++ ++def XVSLE_H : LASX_3R<0b01110100000000101>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.h", SETLE, v16i16, LASX256HOpnd>; ++ ++def XVSLE_W : LASX_3R<0b01110100000000110>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.w", SETLE, v8i32, LASX256WOpnd>; ++ ++def XVSLE_D : LASX_3R<0b01110100000000111>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.d", SETLE, v4i64, LASX256DOpnd>; ++ ++ ++def XVSLE_BU : LASX_3R<0b01110100000001000>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.bu", SETULE, v32i8, LASX256BOpnd>; ++ ++def XVSLE_HU : LASX_3R<0b01110100000001001>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.hu", SETULE, v16i16, LASX256HOpnd>; ++ ++def XVSLE_WU : LASX_3R<0b01110100000001010>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.wu", SETULE, v8i32, LASX256WOpnd>; ++ ++def XVSLE_DU : LASX_3R<0b01110100000001011>, ++ LASX_3R_SETCC_DESC_BASE<"xvsle.du", SETULE, v4i64, LASX256DOpnd>; ++ ++ ++def XVSLT_B : LASX_3R<0b01110100000001100>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.b", SETLT, v32i8, LASX256BOpnd>; ++ ++def XVSLT_H : LASX_3R<0b01110100000001101>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.h", SETLT, v16i16, LASX256HOpnd>; ++ ++def XVSLT_W : LASX_3R<0b01110100000001110>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.w", SETLT, v8i32, LASX256WOpnd>; ++ ++def XVSLT_D : LASX_3R<0b01110100000001111>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.d", SETLT, v4i64, LASX256DOpnd>; ++ ++ ++def XVSLT_BU : LASX_3R<0b01110100000010000>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.bu", SETULT, v32i8, LASX256BOpnd>; ++ ++def XVSLT_HU : LASX_3R<0b01110100000010001>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.hu", SETULT, v16i16, LASX256HOpnd>; ++ ++def XVSLT_WU : LASX_3R<0b01110100000010010>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.wu", SETULT, v8i32, LASX256WOpnd>; ++ ++def XVSLT_DU : LASX_3R<0b01110100000010011>, ++ LASX_3R_SETCC_DESC_BASE<"xvslt.du", SETULT, v4i64, LASX256DOpnd>; ++ ++ ++def XVADD_B : LASX_3R<0b01110100000010100>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadd.b", add, LASX256BOpnd>; ++ ++def XVADD_H : LASX_3R<0b01110100000010101>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadd.h", add, LASX256HOpnd>; ++ ++def XVADD_W : LASX_3R<0b01110100000010110>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadd.w", add, LASX256WOpnd>; ++ ++def XVADD_D : LASX_3R<0b01110100000010111>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadd.d", add, LASX256DOpnd>; ++ ++ ++def XVSUB_B : LASX_3R<0b01110100000011000>, ++ LASX_3R_DESC_BASE<"xvsub.b", sub, LASX256BOpnd>; ++ ++def XVSUB_H : LASX_3R<0b01110100000011001>, ++ LASX_3R_DESC_BASE<"xvsub.h", sub, LASX256HOpnd>; ++ ++def XVSUB_W : LASX_3R<0b01110100000011010>, ++ LASX_3R_DESC_BASE<"xvsub.w", sub, LASX256WOpnd>; ++ ++def XVSUB_D : LASX_3R<0b01110100000011011>, ++ LASX_3R_DESC_BASE<"xvsub.d", sub, LASX256DOpnd>; ++ ++ ++def XVADDWEV_H_B : LASX_3R<0b01110100000111100>, ++ LASX_3R_DESC_BASE<"xvaddwev.h.b", int_loongarch_lasx_xvaddwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWEV_W_H : LASX_3R<0b01110100000111101>, ++ LASX_3R_DESC_BASE<"xvaddwev.w.h", int_loongarch_lasx_xvaddwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWEV_D_W : LASX_3R<0b01110100000111110>, ++ LASX_3R_DESC_BASE<"xvaddwev.d.w", int_loongarch_lasx_xvaddwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWEV_Q_D : LASX_3R<0b01110100000111111>, ++ LASX_3R_DESC_BASE<"xvaddwev.q.d", int_loongarch_lasx_xvaddwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSUBWEV_H_B : LASX_3R<0b01110100001000000>, ++ LASX_3R_DESC_BASE<"xvsubwev.h.b", int_loongarch_lasx_xvsubwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSUBWEV_W_H : LASX_3R<0b01110100001000001>, ++ LASX_3R_DESC_BASE<"xvsubwev.w.h", int_loongarch_lasx_xvsubwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSUBWEV_D_W : LASX_3R<0b01110100001000010>, ++ LASX_3R_DESC_BASE<"xvsubwev.d.w", int_loongarch_lasx_xvsubwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVSUBWEV_Q_D : LASX_3R<0b01110100001000011>, ++ LASX_3R_DESC_BASE<"xvsubwev.q.d", int_loongarch_lasx_xvsubwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDWOD_H_B : LASX_3R<0b01110100001000100>, ++ LASX_3R_DESC_BASE<"xvaddwod.h.b", int_loongarch_lasx_xvaddwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWOD_W_H : LASX_3R<0b01110100001000101>, ++ LASX_3R_DESC_BASE<"xvaddwod.w.h", int_loongarch_lasx_xvaddwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWOD_D_W : LASX_3R<0b01110100001000110>, ++ LASX_3R_DESC_BASE<"xvaddwod.d.w", int_loongarch_lasx_xvaddwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWOD_Q_D : LASX_3R<0b01110100001000111>, ++ LASX_3R_DESC_BASE<"xvaddwod.q.d", int_loongarch_lasx_xvaddwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSUBWOD_H_B : LASX_3R<0b01110100001001000>, ++ LASX_3R_DESC_BASE<"xvsubwod.h.b", int_loongarch_lasx_xvsubwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSUBWOD_W_H : LASX_3R<0b01110100001001001>, ++ LASX_3R_DESC_BASE<"xvsubwod.w.h", int_loongarch_lasx_xvsubwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSUBWOD_D_W : LASX_3R<0b01110100001001010>, ++ LASX_3R_DESC_BASE<"xvsubwod.d.w", int_loongarch_lasx_xvsubwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVSUBWOD_Q_D : LASX_3R<0b01110100001001011>, ++ LASX_3R_DESC_BASE<"xvsubwod.q.d", int_loongarch_lasx_xvsubwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDWEV_H_BU : LASX_3R<0b01110100001011100>, ++ LASX_3R_DESC_BASE<"xvaddwev.h.bu", int_loongarch_lasx_xvaddwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWEV_W_HU : LASX_3R<0b01110100001011101>, ++ LASX_3R_DESC_BASE<"xvaddwev.w.hu", int_loongarch_lasx_xvaddwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWEV_D_WU : LASX_3R<0b01110100001011110>, ++ LASX_3R_DESC_BASE<"xvaddwev.d.wu", int_loongarch_lasx_xvaddwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWEV_Q_DU : LASX_3R<0b01110100001011111>, ++ LASX_3R_DESC_BASE<"xvaddwev.q.du", int_loongarch_lasx_xvaddwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSUBWEV_H_BU : LASX_3R<0b01110100001100000>, ++ LASX_3R_DESC_BASE<"xvsubwev.h.bu", int_loongarch_lasx_xvsubwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSUBWEV_W_HU : LASX_3R<0b01110100001100001>, ++ LASX_3R_DESC_BASE<"xvsubwev.w.hu", int_loongarch_lasx_xvsubwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSUBWEV_D_WU : LASX_3R<0b01110100001100010>, ++ LASX_3R_DESC_BASE<"xvsubwev.d.wu", int_loongarch_lasx_xvsubwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVSUBWEV_Q_DU : LASX_3R<0b01110100001100011>, ++ LASX_3R_DESC_BASE<"xvsubwev.q.du", int_loongarch_lasx_xvsubwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDWOD_H_BU : LASX_3R<0b01110100001100100>, ++ LASX_3R_DESC_BASE<"xvaddwod.h.bu", int_loongarch_lasx_xvaddwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWOD_W_HU : LASX_3R<0b01110100001100101>, ++ LASX_3R_DESC_BASE<"xvaddwod.w.hu", int_loongarch_lasx_xvaddwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWOD_D_WU : LASX_3R<0b01110100001100110>, ++ LASX_3R_DESC_BASE<"xvaddwod.d.wu", int_loongarch_lasx_xvaddwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWOD_Q_DU : LASX_3R<0b01110100001100111>, ++ LASX_3R_DESC_BASE<"xvaddwod.q.du", int_loongarch_lasx_xvaddwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSUBWOD_H_BU : LASX_3R<0b01110100001101000>, ++ LASX_3R_DESC_BASE<"xvsubwod.h.bu", int_loongarch_lasx_xvsubwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSUBWOD_W_HU : LASX_3R<0b01110100001101001>, ++ LASX_3R_DESC_BASE<"xvsubwod.w.hu", int_loongarch_lasx_xvsubwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSUBWOD_D_WU : LASX_3R<0b01110100001101010>, ++ LASX_3R_DESC_BASE<"xvsubwod.d.wu", int_loongarch_lasx_xvsubwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVSUBWOD_Q_DU : LASX_3R<0b01110100001101011>, ++ LASX_3R_DESC_BASE<"xvsubwod.q.du", int_loongarch_lasx_xvsubwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDWEV_H_BU_B : LASX_3R<0b01110100001111100>, ++ LASX_3R_DESC_BASE<"xvaddwev.h.bu.b", int_loongarch_lasx_xvaddwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWEV_W_HU_H : LASX_3R<0b01110100001111101>, ++ LASX_3R_DESC_BASE<"xvaddwev.w.hu.h", int_loongarch_lasx_xvaddwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWEV_D_WU_W : LASX_3R<0b01110100001111110>, ++ LASX_3R_DESC_BASE<"xvaddwev.d.wu.w", int_loongarch_lasx_xvaddwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWEV_Q_DU_D : LASX_3R<0b01110100001111111>, ++ LASX_3R_DESC_BASE<"xvaddwev.q.du.d", int_loongarch_lasx_xvaddwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDWOD_H_BU_B : LASX_3R<0b01110100010000000>, ++ LASX_3R_DESC_BASE<"xvaddwod.h.bu.b", int_loongarch_lasx_xvaddwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVADDWOD_W_HU_H : LASX_3R<0b01110100010000001>, ++ LASX_3R_DESC_BASE<"xvaddwod.w.hu.h", int_loongarch_lasx_xvaddwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVADDWOD_D_WU_W : LASX_3R<0b01110100010000010>, ++ LASX_3R_DESC_BASE<"xvaddwod.d.wu.w", int_loongarch_lasx_xvaddwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVADDWOD_Q_DU_D : LASX_3R<0b01110100010000011>, ++ LASX_3R_DESC_BASE<"xvaddwod.q.du.d", int_loongarch_lasx_xvaddwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSADD_B : LASX_3R<0b01110100010001100>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.b", saddsat, LASX256BOpnd>; ++ ++def XVSADD_H : LASX_3R<0b01110100010001101>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.h", saddsat, LASX256HOpnd>; ++ ++def XVSADD_W : LASX_3R<0b01110100010001110>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.w", saddsat, LASX256WOpnd>; ++ ++def XVSADD_D : LASX_3R<0b01110100010001111>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.d", saddsat, LASX256DOpnd>; ++ ++ ++def XVSSUB_B : LASX_3R<0b01110100010010000>, ++ LASX_3R_DESC_BASE<"xvssub.b", ssubsat, LASX256BOpnd>; ++ ++def XVSSUB_H : LASX_3R<0b01110100010010001>, ++ LASX_3R_DESC_BASE<"xvssub.h", ssubsat, LASX256HOpnd>; ++ ++def XVSSUB_W : LASX_3R<0b01110100010010010>, ++ LASX_3R_DESC_BASE<"xvssub.w", ssubsat, LASX256WOpnd>; ++ ++def XVSSUB_D : LASX_3R<0b01110100010010011>, ++ LASX_3R_DESC_BASE<"xvssub.d", ssubsat, LASX256DOpnd>; ++ ++ ++def XVSADD_BU : LASX_3R<0b01110100010010100>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.bu", uaddsat, LASX256BOpnd>; ++ ++def XVSADD_HU : LASX_3R<0b01110100010010101>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.hu", uaddsat, LASX256HOpnd>; ++ ++def XVSADD_WU : LASX_3R<0b01110100010010110>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.wu", uaddsat, LASX256WOpnd>; ++ ++def XVSADD_DU : LASX_3R<0b01110100010010111>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvsadd.du", uaddsat, LASX256DOpnd>; ++ ++ ++def XVSSUB_BU : LASX_3R<0b01110100010011000>, ++ LASX_3R_DESC_BASE<"xvssub.bu", usubsat, LASX256BOpnd>; ++ ++def XVSSUB_HU : LASX_3R<0b01110100010011001>, ++ LASX_3R_DESC_BASE<"xvssub.hu", usubsat, LASX256HOpnd>; ++ ++def XVSSUB_WU : LASX_3R<0b01110100010011010>, ++ LASX_3R_DESC_BASE<"xvssub.wu", usubsat, LASX256WOpnd>; ++ ++def XVSSUB_DU : LASX_3R<0b01110100010011011>, ++ LASX_3R_DESC_BASE<"xvssub.du", usubsat, LASX256DOpnd>; ++ ++ ++def XVHADDW_H_B : LASX_3R<0b01110100010101000>, ++ LASX_3R_DESC_BASE<"xvhaddw.h.b", int_loongarch_lasx_xvhaddw_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVHADDW_W_H : LASX_3R<0b01110100010101001>, ++ LASX_3R_DESC_BASE<"xvhaddw.w.h", int_loongarch_lasx_xvhaddw_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVHADDW_D_W : LASX_3R<0b01110100010101010>, ++ LASX_3R_DESC_BASE<"xvhaddw.d.w", int_loongarch_lasx_xvhaddw_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVHADDW_Q_D : LASX_3R<0b01110100010101011>, ++ LASX_3R_DESC_BASE<"xvhaddw.q.d", int_loongarch_lasx_xvhaddw_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++ ++def XVHSUBW_H_B : LASX_3R<0b01110100010101100>, ++ LASX_3R_DESC_BASE<"xvhsubw.h.b", int_loongarch_lasx_xvhsubw_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVHSUBW_W_H : LASX_3R<0b01110100010101101>, ++ LASX_3R_DESC_BASE<"xvhsubw.w.h", int_loongarch_lasx_xvhsubw_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVHSUBW_D_W : LASX_3R<0b01110100010101110>, ++ LASX_3R_DESC_BASE<"xvhsubw.d.w", int_loongarch_lasx_xvhsubw_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVHSUBW_Q_D : LASX_3R<0b01110100010101111>, ++ LASX_3R_DESC_BASE<"xvhsubw.q.d", int_loongarch_lasx_xvhsubw_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVHADDW_HU_BU : LASX_3R<0b01110100010110000>, ++ LASX_3R_DESC_BASE<"xvhaddw.hu.bu", int_loongarch_lasx_xvhaddw_hu_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVHADDW_WU_HU : LASX_3R<0b01110100010110001>, ++ LASX_3R_DESC_BASE<"xvhaddw.wu.hu", int_loongarch_lasx_xvhaddw_wu_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVHADDW_DU_WU : LASX_3R<0b01110100010110010>, ++ LASX_3R_DESC_BASE<"xvhaddw.du.wu", int_loongarch_lasx_xvhaddw_du_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVHADDW_QU_DU : LASX_3R<0b01110100010110011>, ++ LASX_3R_DESC_BASE<"xvhaddw.qu.du", int_loongarch_lasx_xvhaddw_qu_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++ ++def XVHSUBW_HU_BU : LASX_3R<0b01110100010110100>, ++ LASX_3R_DESC_BASE<"xvhsubw.hu.bu", int_loongarch_lasx_xvhsubw_hu_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVHSUBW_WU_HU : LASX_3R<0b01110100010110101>, ++ LASX_3R_DESC_BASE<"xvhsubw.wu.hu", int_loongarch_lasx_xvhsubw_wu_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVHSUBW_DU_WU : LASX_3R<0b01110100010110110>, ++ LASX_3R_DESC_BASE<"xvhsubw.du.wu", int_loongarch_lasx_xvhsubw_du_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVHSUBW_QU_DU : LASX_3R<0b01110100010110111>, ++ LASX_3R_DESC_BASE<"xvhsubw.qu.du", int_loongarch_lasx_xvhsubw_qu_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVADDA_B : LASX_3R<0b01110100010111000>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadda.b", int_loongarch_lasx_xvadda_b, LASX256BOpnd>; ++ ++def XVADDA_H : LASX_3R<0b01110100010111001>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadda.h", int_loongarch_lasx_xvadda_h, LASX256HOpnd>; ++ ++def XVADDA_W : LASX_3R<0b01110100010111010>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadda.w", int_loongarch_lasx_xvadda_w, LASX256WOpnd>; ++ ++def XVADDA_D : LASX_3R<0b01110100010111011>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadda.d", int_loongarch_lasx_xvadda_d, LASX256DOpnd>; ++ ++ ++def XVABSD_B : LASX_3R<0b01110100011000000>, ++ LASX_3R_DESC_BASE<"xvabsd.b", int_loongarch_lasx_xvabsd_b, LASX256BOpnd>; ++ ++def XVABSD_H : LASX_3R<0b01110100011000001>, ++ LASX_3R_DESC_BASE<"xvabsd.h", int_loongarch_lasx_xvabsd_h, LASX256HOpnd>; ++ ++def XVABSD_W : LASX_3R<0b01110100011000010>, ++ LASX_3R_DESC_BASE<"xvabsd.w", int_loongarch_lasx_xvabsd_w, LASX256WOpnd>; ++ ++def XVABSD_D : LASX_3R<0b01110100011000011>, ++ LASX_3R_DESC_BASE<"xvabsd.d", int_loongarch_lasx_xvabsd_d, LASX256DOpnd>; ++ ++ ++def XVABSD_BU : LASX_3R<0b01110100011000100>, ++ LASX_3R_DESC_BASE<"xvabsd.bu", int_loongarch_lasx_xvabsd_bu, LASX256BOpnd>; ++ ++def XVABSD_HU : LASX_3R<0b01110100011000101>, ++ LASX_3R_DESC_BASE<"xvabsd.hu", int_loongarch_lasx_xvabsd_hu, LASX256HOpnd>; ++ ++def XVABSD_WU : LASX_3R<0b01110100011000110>, ++ LASX_3R_DESC_BASE<"xvabsd.wu", int_loongarch_lasx_xvabsd_wu, LASX256WOpnd>; ++ ++def XVABSD_DU : LASX_3R<0b01110100011000111>, ++ LASX_3R_DESC_BASE<"xvabsd.du", int_loongarch_lasx_xvabsd_du, LASX256DOpnd>; ++ ++ ++def XVAVG_B : LASX_3R<0b01110100011001000>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.b", int_loongarch_lasx_xvavg_b, LASX256BOpnd>; ++ ++def XVAVG_H : LASX_3R<0b01110100011001001>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.h", int_loongarch_lasx_xvavg_h, LASX256HOpnd>; ++ ++def XVAVG_W : LASX_3R<0b01110100011001010>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.w", int_loongarch_lasx_xvavg_w, LASX256WOpnd>; ++ ++def XVAVG_D : LASX_3R<0b01110100011001011>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.d", int_loongarch_lasx_xvavg_d, LASX256DOpnd>; ++ ++ ++def XVAVG_BU : LASX_3R<0b01110100011001100>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.bu", int_loongarch_lasx_xvavg_bu, LASX256BOpnd>; ++ ++def XVAVG_HU : LASX_3R<0b01110100011001101>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.hu", int_loongarch_lasx_xvavg_hu, LASX256HOpnd>; ++ ++def XVAVG_WU : LASX_3R<0b01110100011001110>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.wu", int_loongarch_lasx_xvavg_wu, LASX256WOpnd>; ++ ++def XVAVG_DU : LASX_3R<0b01110100011001111>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavg.du", int_loongarch_lasx_xvavg_du, LASX256DOpnd>; ++ ++ ++def XVAVGR_B : LASX_3R<0b01110100011010000>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.b", int_loongarch_lasx_xvavgr_b, LASX256BOpnd>; ++ ++def XVAVGR_H : LASX_3R<0b01110100011010001>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.h", int_loongarch_lasx_xvavgr_h, LASX256HOpnd>; ++ ++def XVAVGR_W : LASX_3R<0b01110100011010010>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.w", int_loongarch_lasx_xvavgr_w, LASX256WOpnd>; ++ ++def XVAVGR_D : LASX_3R<0b01110100011010011>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.d", int_loongarch_lasx_xvavgr_d, LASX256DOpnd>; ++ ++ ++def XVAVGR_BU : LASX_3R<0b01110100011010100>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.bu", int_loongarch_lasx_xvavgr_bu, LASX256BOpnd>; ++ ++def XVAVGR_HU : LASX_3R<0b01110100011010101>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.hu", int_loongarch_lasx_xvavgr_hu, LASX256HOpnd>; ++ ++def XVAVGR_WU : LASX_3R<0b01110100011010110>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.wu", int_loongarch_lasx_xvavgr_wu, LASX256WOpnd>; ++ ++def XVAVGR_DU : LASX_3R<0b01110100011010111>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvavgr.du", int_loongarch_lasx_xvavgr_du, LASX256DOpnd>; ++ ++ ++def XVMAX_B : LASX_3R<0b01110100011100000>, ++ LASX_3R_DESC_BASE<"xvmax.b", smax, LASX256BOpnd>; ++ ++def XVMAX_H : LASX_3R<0b01110100011100001>, ++ LASX_3R_DESC_BASE<"xvmax.h", smax, LASX256HOpnd>; ++ ++def XVMAX_W : LASX_3R<0b01110100011100010>, ++ LASX_3R_DESC_BASE<"xvmax.w", smax, LASX256WOpnd>; ++ ++def XVMAX_D : LASX_3R<0b01110100011100011>, ++ LASX_3R_DESC_BASE<"xvmax.d", smax, LASX256DOpnd>; ++ ++ ++def XVMIN_B : LASX_3R<0b01110100011100100>, ++ LASX_3R_DESC_BASE<"xvmin.b", smin, LASX256BOpnd>; ++ ++def XVMIN_H : LASX_3R<0b01110100011100101>, ++ LASX_3R_DESC_BASE<"xvmin.h", smin, LASX256HOpnd>; ++ ++def XVMIN_W : LASX_3R<0b01110100011100110>, ++ LASX_3R_DESC_BASE<"xvmin.w", smin, LASX256WOpnd>; ++ ++def XVMIN_D : LASX_3R<0b01110100011100111>, ++ LASX_3R_DESC_BASE<"xvmin.d", smin, LASX256DOpnd>; ++ ++ ++def XVMAX_BU : LASX_3R<0b01110100011101000>, ++ LASX_3R_DESC_BASE<"xvmax.bu", umax, LASX256BOpnd>; ++ ++def XVMAX_HU : LASX_3R<0b01110100011101001>, ++ LASX_3R_DESC_BASE<"xvmax.hu", umax, LASX256HOpnd>; ++ ++def XVMAX_WU : LASX_3R<0b01110100011101010>, ++ LASX_3R_DESC_BASE<"xvmax.wu", umax, LASX256WOpnd>; ++ ++def XVMAX_DU : LASX_3R<0b01110100011101011>, ++ LASX_3R_DESC_BASE<"xvmax.du", umax, LASX256DOpnd>; ++ ++ ++def XVMIN_BU : LASX_3R<0b01110100011101100>, ++ LASX_3R_DESC_BASE<"xvmin.bu", umin, LASX256BOpnd>; ++ ++def XVMIN_HU : LASX_3R<0b01110100011101101>, ++ LASX_3R_DESC_BASE<"xvmin.hu", umin, LASX256HOpnd>; ++ ++def XVMIN_WU : LASX_3R<0b01110100011101110>, ++ LASX_3R_DESC_BASE<"xvmin.wu", umin, LASX256WOpnd>; ++ ++def XVMIN_DU : LASX_3R<0b01110100011101111>, ++ LASX_3R_DESC_BASE<"xvmin.du", umin, LASX256DOpnd>; ++ ++ ++def XVMUL_B : LASX_3R<0b01110100100001000>, ++ LASX_3R_DESC_BASE<"xvmul.b", mul, LASX256BOpnd>, IsCommutable; ++ ++def XVMUL_H : LASX_3R<0b01110100100001001>, ++ LASX_3R_DESC_BASE<"xvmul.h", mul, LASX256HOpnd>, IsCommutable; ++ ++def XVMUL_W : LASX_3R<0b01110100100001010>, ++ LASX_3R_DESC_BASE<"xvmul.w", mul, LASX256WOpnd>, IsCommutable; ++ ++def XVMUL_D : LASX_3R<0b01110100100001011>, ++ LASX_3R_DESC_BASE<"xvmul.d", mul, LASX256DOpnd>, IsCommutable; ++ ++ ++def XVMUH_B : LASX_3R<0b01110100100001100>, ++ LASX_3R_DESC_BASE<"xvmuh.b", int_loongarch_lasx_xvmuh_b, LASX256BOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMUH_H : LASX_3R<0b01110100100001101>, ++ LASX_3R_DESC_BASE<"xvmuh.h", int_loongarch_lasx_xvmuh_h, LASX256HOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMUH_W : LASX_3R<0b01110100100001110>, ++ LASX_3R_DESC_BASE<"xvmuh.w", int_loongarch_lasx_xvmuh_w, LASX256WOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMUH_D : LASX_3R<0b01110100100001111>, ++ LASX_3R_DESC_BASE<"xvmuh.d", int_loongarch_lasx_xvmuh_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMUH_BU : LASX_3R<0b01110100100010000>, ++ LASX_3R_DESC_BASE<"xvmuh.bu", int_loongarch_lasx_xvmuh_bu, LASX256BOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMUH_HU : LASX_3R<0b01110100100010001>, ++ LASX_3R_DESC_BASE<"xvmuh.hu", int_loongarch_lasx_xvmuh_hu, LASX256HOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMUH_WU : LASX_3R<0b01110100100010010>, ++ LASX_3R_DESC_BASE<"xvmuh.wu", int_loongarch_lasx_xvmuh_wu, LASX256WOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMUH_DU : LASX_3R<0b01110100100010011>, ++ LASX_3R_DESC_BASE<"xvmuh.du", int_loongarch_lasx_xvmuh_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWEV_H_B : LASX_3R<0b01110100100100000>, ++ LASX_3R_DESC_BASE<"xvmulwev.h.b", int_loongarch_lasx_xvmulwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWEV_W_H : LASX_3R<0b01110100100100001>, ++ LASX_3R_DESC_BASE<"xvmulwev.w.h", int_loongarch_lasx_xvmulwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWEV_D_W : LASX_3R<0b01110100100100010>, ++ LASX_3R_DESC_BASE<"xvmulwev.d.w", int_loongarch_lasx_xvmulwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWEV_Q_D : LASX_3R<0b01110100100100011>, ++ LASX_3R_DESC_BASE<"xvmulwev.q.d", int_loongarch_lasx_xvmulwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWOD_H_B : LASX_3R<0b01110100100100100>, ++ LASX_3R_DESC_BASE<"xvmulwod.h.b", int_loongarch_lasx_xvmulwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWOD_W_H : LASX_3R<0b01110100100100101>, ++ LASX_3R_DESC_BASE<"xvmulwod.w.h", int_loongarch_lasx_xvmulwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWOD_D_W : LASX_3R<0b01110100100100110>, ++ LASX_3R_DESC_BASE<"xvmulwod.d.w", int_loongarch_lasx_xvmulwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWOD_Q_D : LASX_3R<0b01110100100100111>, ++ LASX_3R_DESC_BASE<"xvmulwod.q.d", int_loongarch_lasx_xvmulwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWEV_H_BU : LASX_3R<0b01110100100110000>, ++ LASX_3R_DESC_BASE<"xvmulwev.h.bu", int_loongarch_lasx_xvmulwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWEV_W_HU : LASX_3R<0b01110100100110001>, ++ LASX_3R_DESC_BASE<"xvmulwev.w.hu", int_loongarch_lasx_xvmulwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWEV_D_WU : LASX_3R<0b01110100100110010>, ++ LASX_3R_DESC_BASE<"xvmulwev.d.wu", int_loongarch_lasx_xvmulwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWEV_Q_DU : LASX_3R<0b01110100100110011>, ++ LASX_3R_DESC_BASE<"xvmulwev.q.du", int_loongarch_lasx_xvmulwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWOD_H_BU : LASX_3R<0b01110100100110100>, ++ LASX_3R_DESC_BASE<"xvmulwod.h.bu", int_loongarch_lasx_xvmulwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWOD_W_HU : LASX_3R<0b01110100100110101>, ++ LASX_3R_DESC_BASE<"xvmulwod.w.hu", int_loongarch_lasx_xvmulwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWOD_D_WU : LASX_3R<0b01110100100110110>, ++ LASX_3R_DESC_BASE<"xvmulwod.d.wu", int_loongarch_lasx_xvmulwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWOD_Q_DU : LASX_3R<0b01110100100110111>, ++ LASX_3R_DESC_BASE<"xvmulwod.q.du", int_loongarch_lasx_xvmulwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWEV_H_BU_B : LASX_3R<0b01110100101000000>, ++ LASX_3R_DESC_BASE<"xvmulwev.h.bu.b", int_loongarch_lasx_xvmulwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWEV_W_HU_H : LASX_3R<0b01110100101000001>, ++ LASX_3R_DESC_BASE<"xvmulwev.w.hu.h", int_loongarch_lasx_xvmulwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWEV_D_WU_W : LASX_3R<0b01110100101000010>, ++ LASX_3R_DESC_BASE<"xvmulwev.d.wu.w", int_loongarch_lasx_xvmulwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWEV_Q_DU_D : LASX_3R<0b01110100101000011>, ++ LASX_3R_DESC_BASE<"xvmulwev.q.du.d", int_loongarch_lasx_xvmulwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMULWOD_H_BU_B : LASX_3R<0b01110100101000100>, ++ LASX_3R_DESC_BASE<"xvmulwod.h.bu.b", int_loongarch_lasx_xvmulwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMULWOD_W_HU_H : LASX_3R<0b01110100101000101>, ++ LASX_3R_DESC_BASE<"xvmulwod.w.hu.h", int_loongarch_lasx_xvmulwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMULWOD_D_WU_W : LASX_3R<0b01110100101000110>, ++ LASX_3R_DESC_BASE<"xvmulwod.d.wu.w", int_loongarch_lasx_xvmulwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd> ; ++ ++def XVMULWOD_Q_DU_D : LASX_3R<0b01110100101000111>, ++ LASX_3R_DESC_BASE<"xvmulwod.q.du.d", int_loongarch_lasx_xvmulwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADD_B : LASX_3R<0b01110100101010000>, ++ LASX_3R_4R_DESC_BASE<"xvmadd.b", muladd, LASX256BOpnd>; ++ ++def XVMADD_H : LASX_3R<0b01110100101010001>, ++ LASX_3R_4R_DESC_BASE<"xvmadd.h", muladd, LASX256HOpnd>; ++ ++def XVMADD_W : LASX_3R<0b01110100101010010>, ++ LASX_3R_4R_DESC_BASE<"xvmadd.w", muladd, LASX256WOpnd>; ++ ++def XVMADD_D : LASX_3R<0b01110100101010011>, ++ LASX_3R_4R_DESC_BASE<"xvmadd.d", muladd, LASX256DOpnd>; ++ ++ ++def XVMSUB_B : LASX_3R<0b01110100101010100>, ++ LASX_3R_4R_DESC_BASE<"xvmsub.b", mulsub, LASX256BOpnd>; ++ ++def XVMSUB_H : LASX_3R<0b01110100101010101>, ++ LASX_3R_4R_DESC_BASE<"xvmsub.h", mulsub, LASX256HOpnd>; ++ ++def XVMSUB_W : LASX_3R<0b01110100101010110>, ++ LASX_3R_4R_DESC_BASE<"xvmsub.w", mulsub, LASX256WOpnd>; ++ ++def XVMSUB_D : LASX_3R<0b01110100101010111>, ++ LASX_3R_4R_DESC_BASE<"xvmsub.d", mulsub, LASX256DOpnd>; ++ ++ ++def XVMADDWEV_H_B : LASX_3R<0b01110100101011000>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.b", int_loongarch_lasx_xvmaddwev_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWEV_W_H : LASX_3R<0b01110100101011001>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.h", int_loongarch_lasx_xvmaddwev_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWEV_D_W : LASX_3R<0b01110100101011010>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.w", int_loongarch_lasx_xvmaddwev_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWEV_Q_D : LASX_3R<0b01110100101011011>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.d", int_loongarch_lasx_xvmaddwev_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADDWOD_H_B : LASX_3R<0b01110100101011100>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.b", int_loongarch_lasx_xvmaddwod_h_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWOD_W_H : LASX_3R<0b01110100101011101>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.h", int_loongarch_lasx_xvmaddwod_w_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWOD_D_W : LASX_3R<0b01110100101011110>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.w", int_loongarch_lasx_xvmaddwod_d_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWOD_Q_D : LASX_3R<0b01110100101011111>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.d", int_loongarch_lasx_xvmaddwod_q_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADDWEV_H_BU : LASX_3R<0b01110100101101000>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.bu", int_loongarch_lasx_xvmaddwev_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWEV_W_HU : LASX_3R<0b01110100101101001>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.hu", int_loongarch_lasx_xvmaddwev_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWEV_D_WU : LASX_3R<0b01110100101101010>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.wu", int_loongarch_lasx_xvmaddwev_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWEV_Q_DU : LASX_3R<0b01110100101101011>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.du", int_loongarch_lasx_xvmaddwev_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADDWOD_H_BU : LASX_3R<0b01110100101101100>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.bu", int_loongarch_lasx_xvmaddwod_h_bu, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWOD_W_HU : LASX_3R<0b01110100101101101>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.hu", int_loongarch_lasx_xvmaddwod_w_hu, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWOD_D_WU : LASX_3R<0b01110100101101110>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.wu", int_loongarch_lasx_xvmaddwod_d_wu, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWOD_Q_DU : LASX_3R<0b01110100101101111>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.du", int_loongarch_lasx_xvmaddwod_q_du, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADDWEV_H_BU_B : LASX_3R<0b01110100101111000>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.h.bu.b", int_loongarch_lasx_xvmaddwev_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWEV_W_HU_H : LASX_3R<0b01110100101111001>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.w.hu.h", int_loongarch_lasx_xvmaddwev_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWEV_D_WU_W : LASX_3R<0b01110100101111010>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.d.wu.w", int_loongarch_lasx_xvmaddwev_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWEV_Q_DU_D : LASX_3R<0b01110100101111011>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwev.q.du.d", int_loongarch_lasx_xvmaddwev_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVMADDWOD_H_BU_B : LASX_3R<0b01110100101111100>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.h.bu.b", int_loongarch_lasx_xvmaddwod_h_bu_b, LASX256HOpnd, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVMADDWOD_W_HU_H : LASX_3R<0b01110100101111101>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.w.hu.h", int_loongarch_lasx_xvmaddwod_w_hu_h, LASX256WOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVMADDWOD_D_WU_W : LASX_3R<0b01110100101111110>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.d.wu.w", int_loongarch_lasx_xvmaddwod_d_wu_w, LASX256DOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVMADDWOD_Q_DU_D : LASX_3R<0b01110100101111111>, ++ LASX_3R_4R_DESC_BASE<"xvmaddwod.q.du.d", int_loongarch_lasx_xvmaddwod_q_du_d, LASX256DOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVDIV_B : LASX_3R<0b01110100111000000>, ++ LASX_3R_DESC_BASE<"xvdiv.b", sdiv, LASX256BOpnd>; ++ ++def XVDIV_H : LASX_3R<0b01110100111000001>, ++ LASX_3R_DESC_BASE<"xvdiv.h", sdiv, LASX256HOpnd>; ++ ++def XVDIV_W : LASX_3R<0b01110100111000010>, ++ LASX_3R_DESC_BASE<"xvdiv.w", sdiv, LASX256WOpnd>; ++ ++def XVDIV_D : LASX_3R<0b01110100111000011>, ++ LASX_3R_DESC_BASE<"xvdiv.d", sdiv, LASX256DOpnd>; ++ ++ ++def XVMOD_B : LASX_3R<0b01110100111000100>, ++ LASX_3R_DESC_BASE<"xvmod.b", srem, LASX256BOpnd>; ++ ++def XVMOD_H : LASX_3R<0b01110100111000101>, ++ LASX_3R_DESC_BASE<"xvmod.h", srem, LASX256HOpnd>; ++ ++def XVMOD_W : LASX_3R<0b01110100111000110>, ++ LASX_3R_DESC_BASE<"xvmod.w", srem, LASX256WOpnd>; ++ ++def XVMOD_D : LASX_3R<0b01110100111000111>, ++ LASX_3R_DESC_BASE<"xvmod.d", srem, LASX256DOpnd>; ++ ++ ++def XVDIV_BU : LASX_3R<0b01110100111001000>, ++ LASX_3R_DESC_BASE<"xvdiv.bu", udiv, LASX256BOpnd>; ++ ++def XVDIV_HU : LASX_3R<0b01110100111001001>, ++ LASX_3R_DESC_BASE<"xvdiv.hu", udiv, LASX256HOpnd>; ++ ++def XVDIV_WU : LASX_3R<0b01110100111001010>, ++ LASX_3R_DESC_BASE<"xvdiv.wu", udiv, LASX256WOpnd>; ++ ++def XVDIV_DU : LASX_3R<0b01110100111001011>, ++ LASX_3R_DESC_BASE<"xvdiv.du", udiv, LASX256DOpnd>; ++ ++ ++def XVMOD_BU : LASX_3R<0b01110100111001100>, ++ LASX_3R_DESC_BASE<"xvmod.bu", urem, LASX256BOpnd>; ++ ++def XVMOD_HU : LASX_3R<0b01110100111001101>, ++ LASX_3R_DESC_BASE<"xvmod.hu", urem, LASX256HOpnd>; ++ ++def XVMOD_WU : LASX_3R<0b01110100111001110>, ++ LASX_3R_DESC_BASE<"xvmod.wu", urem, LASX256WOpnd>; ++ ++def XVMOD_DU : LASX_3R<0b01110100111001111>, ++ LASX_3R_DESC_BASE<"xvmod.du", urem, LASX256DOpnd>; ++ ++ ++def XVSLL_B : LASX_3R<0b01110100111010000>, ++ LASX_3R_DESC_BASE<"xvsll.b", shl, LASX256BOpnd>; ++ ++def XVSLL_H : LASX_3R<0b01110100111010001>, ++ LASX_3R_DESC_BASE<"xvsll.h", shl, LASX256HOpnd>; ++ ++def XVSLL_W : LASX_3R<0b01110100111010010>, ++ LASX_3R_DESC_BASE<"xvsll.w", shl, LASX256WOpnd>; ++ ++def XVSLL_D : LASX_3R<0b01110100111010011>, ++ LASX_3R_DESC_BASE<"xvsll.d", shl, LASX256DOpnd>; ++ ++ ++def XVSRL_B : LASX_3R<0b01110100111010100>, ++ LASX_3R_DESC_BASE<"xvsrl.b", srl, LASX256BOpnd>; ++ ++def XVSRL_H : LASX_3R<0b01110100111010101>, ++ LASX_3R_DESC_BASE<"xvsrl.h", srl, LASX256HOpnd>; ++ ++def XVSRL_W : LASX_3R<0b01110100111010110>, ++ LASX_3R_DESC_BASE<"xvsrl.w", srl, LASX256WOpnd>; ++ ++def XVSRL_D : LASX_3R<0b01110100111010111>, ++ LASX_3R_DESC_BASE<"xvsrl.d", srl, LASX256DOpnd>; ++ ++ ++def XVSRA_B : LASX_3R<0b01110100111011000>, ++ LASX_3R_DESC_BASE<"xvsra.b", sra, LASX256BOpnd>; ++ ++def XVSRA_H : LASX_3R<0b01110100111011001>, ++ LASX_3R_DESC_BASE<"xvsra.h", sra, LASX256HOpnd>; ++ ++def XVSRA_W : LASX_3R<0b01110100111011010>, ++ LASX_3R_DESC_BASE<"xvsra.w", sra, LASX256WOpnd>; ++ ++def XVSRA_D : LASX_3R<0b01110100111011011>, ++ LASX_3R_DESC_BASE<"xvsra.d", sra, LASX256DOpnd>; ++ ++ ++def XVROTR_B : LASX_3R<0b01110100111011100>, ++ LASX_3R_DESC_BASE<"xvrotr.b", int_loongarch_lasx_xvrotr_b, LASX256BOpnd>; ++ ++def XVROTR_H : LASX_3R<0b01110100111011101>, ++ LASX_3R_DESC_BASE<"xvrotr.h", int_loongarch_lasx_xvrotr_h, LASX256HOpnd>; ++ ++def XVROTR_W : LASX_3R<0b01110100111011110>, ++ LASX_3R_DESC_BASE<"xvrotr.w", int_loongarch_lasx_xvrotr_w, LASX256WOpnd>; ++ ++def XVROTR_D : LASX_3R<0b01110100111011111>, ++ LASX_3R_DESC_BASE<"xvrotr.d", int_loongarch_lasx_xvrotr_d, LASX256DOpnd>; ++ ++ ++def XVSRLR_B : LASX_3R<0b01110100111100000>, ++ LASX_3R_DESC_BASE<"xvsrlr.b", int_loongarch_lasx_xvsrlr_b, LASX256BOpnd>; ++ ++def XVSRLR_H : LASX_3R<0b01110100111100001>, ++ LASX_3R_DESC_BASE<"xvsrlr.h", int_loongarch_lasx_xvsrlr_h, LASX256HOpnd>; ++ ++def XVSRLR_W : LASX_3R<0b01110100111100010>, ++ LASX_3R_DESC_BASE<"xvsrlr.w", int_loongarch_lasx_xvsrlr_w, LASX256WOpnd>; ++ ++def XVSRLR_D : LASX_3R<0b01110100111100011>, ++ LASX_3R_DESC_BASE<"xvsrlr.d", int_loongarch_lasx_xvsrlr_d, LASX256DOpnd>; ++ ++ ++def XVSRAR_B : LASX_3R<0b01110100111100100>, ++ LASX_3R_DESC_BASE<"xvsrar.b", int_loongarch_lasx_xvsrar_b, LASX256BOpnd>; ++ ++def XVSRAR_H : LASX_3R<0b01110100111100101>, ++ LASX_3R_DESC_BASE<"xvsrar.h", int_loongarch_lasx_xvsrar_h, LASX256HOpnd>; ++ ++def XVSRAR_W : LASX_3R<0b01110100111100110>, ++ LASX_3R_DESC_BASE<"xvsrar.w", int_loongarch_lasx_xvsrar_w, LASX256WOpnd>; ++ ++def XVSRAR_D : LASX_3R<0b01110100111100111>, ++ LASX_3R_DESC_BASE<"xvsrar.d", int_loongarch_lasx_xvsrar_d, LASX256DOpnd>; ++ ++ ++def XVSRLN_B_H : LASX_3R<0b01110100111101001>, ++ LASX_3R_DESC_BASE<"xvsrln.b.h", int_loongarch_lasx_xvsrln_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSRLN_H_W : LASX_3R<0b01110100111101010>, ++ LASX_3R_DESC_BASE<"xvsrln.h.w", int_loongarch_lasx_xvsrln_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSRLN_W_D : LASX_3R<0b01110100111101011>, ++ LASX_3R_DESC_BASE<"xvsrln.w.d", int_loongarch_lasx_xvsrln_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSRAN_B_H : LASX_3R<0b01110100111101101>, ++ LASX_3R_DESC_BASE<"xvsran.b.h", int_loongarch_lasx_xvsran_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSRAN_H_W : LASX_3R<0b01110100111101110>, ++ LASX_3R_DESC_BASE<"xvsran.h.w", int_loongarch_lasx_xvsran_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSRAN_W_D : LASX_3R<0b01110100111101111>, ++ LASX_3R_DESC_BASE<"xvsran.w.d", int_loongarch_lasx_xvsran_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSRLRN_B_H : LASX_3R<0b01110100111110001>, ++ LASX_3R_DESC_BASE<"xvsrlrn.b.h", int_loongarch_lasx_xvsrlrn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSRLRN_H_W : LASX_3R<0b01110100111110010>, ++ LASX_3R_DESC_BASE<"xvsrlrn.h.w", int_loongarch_lasx_xvsrlrn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSRLRN_W_D : LASX_3R<0b01110100111110011>, ++ LASX_3R_DESC_BASE<"xvsrlrn.w.d", int_loongarch_lasx_xvsrlrn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSRARN_B_H : LASX_3R<0b01110100111110101>, ++ LASX_3R_DESC_BASE<"xvsrarn.b.h", int_loongarch_lasx_xvsrarn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSRARN_H_W : LASX_3R<0b01110100111110110>, ++ LASX_3R_DESC_BASE<"xvsrarn.h.w", int_loongarch_lasx_xvsrarn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSRARN_W_D : LASX_3R<0b01110100111110111>, ++ LASX_3R_DESC_BASE<"xvsrarn.w.d", int_loongarch_lasx_xvsrarn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRLN_B_H : LASX_3R<0b01110100111111001>, ++ LASX_3R_DESC_BASE<"xvssrln.b.h", int_loongarch_lasx_xvssrln_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRLN_H_W : LASX_3R<0b01110100111111010>, ++ LASX_3R_DESC_BASE<"xvssrln.h.w", int_loongarch_lasx_xvssrln_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRLN_W_D : LASX_3R<0b01110100111111011>, ++ LASX_3R_DESC_BASE<"xvssrln.w.d", int_loongarch_lasx_xvssrln_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRAN_B_H : LASX_3R<0b01110100111111101>, ++ LASX_3R_DESC_BASE<"xvssran.b.h", int_loongarch_lasx_xvssran_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRAN_H_W : LASX_3R<0b01110100111111110>, ++ LASX_3R_DESC_BASE<"xvssran.h.w", int_loongarch_lasx_xvssran_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRAN_W_D : LASX_3R<0b01110100111111111>, ++ LASX_3R_DESC_BASE<"xvssran.w.d", int_loongarch_lasx_xvssran_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRLRN_B_H : LASX_3R<0b01110101000000001>, ++ LASX_3R_DESC_BASE<"xvssrlrn.b.h", int_loongarch_lasx_xvssrlrn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRLRN_H_W : LASX_3R<0b01110101000000010>, ++ LASX_3R_DESC_BASE<"xvssrlrn.h.w", int_loongarch_lasx_xvssrlrn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRLRN_W_D : LASX_3R<0b01110101000000011>, ++ LASX_3R_DESC_BASE<"xvssrlrn.w.d", int_loongarch_lasx_xvssrlrn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRARN_B_H : LASX_3R<0b01110101000000101>, ++ LASX_3R_DESC_BASE<"xvssrarn.b.h", int_loongarch_lasx_xvssrarn_b_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRARN_H_W : LASX_3R<0b01110101000000110>, ++ LASX_3R_DESC_BASE<"xvssrarn.h.w", int_loongarch_lasx_xvssrarn_h_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRARN_W_D : LASX_3R<0b01110101000000111>, ++ LASX_3R_DESC_BASE<"xvssrarn.w.d", int_loongarch_lasx_xvssrarn_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRLN_BU_H : LASX_3R<0b01110101000001001>, ++ LASX_3R_DESC_BASE<"xvssrln.bu.h", int_loongarch_lasx_xvssrln_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRLN_HU_W : LASX_3R<0b01110101000001010>, ++ LASX_3R_DESC_BASE<"xvssrln.hu.w", int_loongarch_lasx_xvssrln_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRLN_WU_D : LASX_3R<0b01110101000001011>, ++ LASX_3R_DESC_BASE<"xvssrln.wu.d", int_loongarch_lasx_xvssrln_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRAN_BU_H : LASX_3R<0b01110101000001101>, ++ LASX_3R_DESC_BASE<"xvssran.bu.h", int_loongarch_lasx_xvssran_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRAN_HU_W : LASX_3R<0b01110101000001110>, ++ LASX_3R_DESC_BASE<"xvssran.hu.w", int_loongarch_lasx_xvssran_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRAN_WU_D : LASX_3R<0b01110101000001111>, ++ LASX_3R_DESC_BASE<"xvssran.wu.d", int_loongarch_lasx_xvssran_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRLRN_BU_H : LASX_3R<0b01110101000010001>, ++ LASX_3R_DESC_BASE<"xvssrlrn.bu.h", int_loongarch_lasx_xvssrlrn_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRLRN_HU_W : LASX_3R<0b01110101000010010>, ++ LASX_3R_DESC_BASE<"xvssrlrn.hu.w", int_loongarch_lasx_xvssrlrn_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRLRN_WU_D : LASX_3R<0b01110101000010011>, ++ LASX_3R_DESC_BASE<"xvssrlrn.wu.d", int_loongarch_lasx_xvssrlrn_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRARN_BU_H : LASX_3R<0b01110101000010101>, ++ LASX_3R_DESC_BASE<"xvssrarn.bu.h", int_loongarch_lasx_xvssrarn_bu_h, LASX256BOpnd, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRARN_HU_W : LASX_3R<0b01110101000010110>, ++ LASX_3R_DESC_BASE<"xvssrarn.hu.w", int_loongarch_lasx_xvssrarn_hu_w, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRARN_WU_D : LASX_3R<0b01110101000010111>, ++ LASX_3R_DESC_BASE<"xvssrarn.wu.d", int_loongarch_lasx_xvssrarn_wu_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVBITCLR_B : LASX_3R<0b01110101000011000>, ++ LASX_3R_DESC_BASE<"xvbitclr.b", xvbitclr_b, LASX256BOpnd>; ++ ++def XVBITCLR_H : LASX_3R<0b01110101000011001>, ++ LASX_3R_DESC_BASE<"xvbitclr.h", xvbitclr_h, LASX256HOpnd>; ++ ++def XVBITCLR_W : LASX_3R<0b01110101000011010>, ++ LASX_3R_DESC_BASE<"xvbitclr.w", xvbitclr_w, LASX256WOpnd>; ++ ++def XVBITCLR_D : LASX_3R<0b01110101000011011>, ++ LASX_3R_DESC_BASE<"xvbitclr.d", xvbitclr_d, LASX256DOpnd>; ++ ++ ++def XVBITSET_B : LASX_3R<0b01110101000011100>, ++ LASX_3R_DESC_BASE<"xvbitset.b", int_loongarch_lasx_xvbitset_b, LASX256BOpnd>; ++ ++def XVBITSET_H : LASX_3R<0b01110101000011101>, ++ LASX_3R_DESC_BASE<"xvbitset.h", int_loongarch_lasx_xvbitset_h, LASX256HOpnd>; ++ ++def XVBITSET_W : LASX_3R<0b01110101000011110>, ++ LASX_3R_DESC_BASE<"xvbitset.w", int_loongarch_lasx_xvbitset_w, LASX256WOpnd>; ++ ++def XVBITSET_D : LASX_3R<0b01110101000011111>, ++ LASX_3R_DESC_BASE<"xvbitset.d", int_loongarch_lasx_xvbitset_d, LASX256DOpnd>; ++ ++ ++def XVBITREV_B : LASX_3R<0b01110101000100000>, ++ LASX_3R_DESC_BASE<"xvbitrev.b", int_loongarch_lasx_xvbitrev_b, LASX256BOpnd>; ++ ++def XVBITREV_H : LASX_3R<0b01110101000100001>, ++ LASX_3R_DESC_BASE<"xvbitrev.h", int_loongarch_lasx_xvbitrev_h, LASX256HOpnd>; ++ ++def XVBITREV_W : LASX_3R<0b01110101000100010>, ++ LASX_3R_DESC_BASE<"xvbitrev.w", int_loongarch_lasx_xvbitrev_w, LASX256WOpnd>; ++ ++def XVBITREV_D : LASX_3R<0b01110101000100011>, ++ LASX_3R_DESC_BASE<"xvbitrev.d", int_loongarch_lasx_xvbitrev_d, LASX256DOpnd>; ++ ++ ++def XVPACKEV_B : LASX_3R<0b01110101000101100>, ++ LASX_3R_DESC_BASE<"xvpackev.b", LoongArchVPACKEV, LASX256BOpnd>; ++ ++def XVPACKEV_H : LASX_3R<0b01110101000101101>, ++ LASX_3R_DESC_BASE<"xvpackev.h", LoongArchVPACKEV, LASX256HOpnd>; ++ ++def XVPACKEV_W : LASX_3R<0b01110101000101110>, ++ LASX_3R_DESC_BASE<"xvpackev.w", LoongArchVPACKEV, LASX256WOpnd>; ++ ++def XVPACKEV_D : LASX_3R<0b01110101000101111>, ++ LASX_3R_DESC_BASE<"xvpackev.d", LoongArchVPACKEV, LASX256DOpnd>; ++ ++ ++def XVPACKOD_B : LASX_3R<0b01110101000110000>, ++ LASX_3R_DESC_BASE<"xvpackod.b", LoongArchVPACKOD, LASX256BOpnd>; ++ ++def XVPACKOD_H : LASX_3R<0b01110101000110001>, ++ LASX_3R_DESC_BASE<"xvpackod.h", LoongArchVPACKOD, LASX256HOpnd>; ++ ++def XVPACKOD_W : LASX_3R<0b01110101000110010>, ++ LASX_3R_DESC_BASE<"xvpackod.w", LoongArchVPACKOD, LASX256WOpnd>; ++ ++def XVPACKOD_D : LASX_3R<0b01110101000110011>, ++ LASX_3R_DESC_BASE<"xvpackod.d", LoongArchVPACKOD, LASX256DOpnd>; ++ ++ ++def XVILVL_B : LASX_3R<0b01110101000110100>, ++ LASX_3R_DESC_BASE<"xvilvl.b", LoongArchVILVL, LASX256BOpnd>; ++ ++def XVILVL_H : LASX_3R<0b01110101000110101>, ++ LASX_3R_DESC_BASE<"xvilvl.h", LoongArchVILVL, LASX256HOpnd>; ++ ++def XVILVL_W : LASX_3R<0b01110101000110110>, ++ LASX_3R_DESC_BASE<"xvilvl.w", LoongArchVILVL, LASX256WOpnd>; ++ ++def XVILVL_D : LASX_3R<0b01110101000110111>, ++ LASX_3R_DESC_BASE<"xvilvl.d", LoongArchVILVL, LASX256DOpnd>; ++ ++ ++def XVILVH_B : LASX_3R<0b01110101000111000>, ++ LASX_3R_DESC_BASE<"xvilvh.b", LoongArchVILVH, LASX256BOpnd>; ++ ++def XVILVH_H : LASX_3R<0b01110101000111001>, ++ LASX_3R_DESC_BASE<"xvilvh.h", LoongArchVILVH, LASX256HOpnd>; ++ ++def XVILVH_W : LASX_3R<0b01110101000111010>, ++ LASX_3R_DESC_BASE<"xvilvh.w", LoongArchVILVH, LASX256WOpnd>; ++ ++def XVILVH_D : LASX_3R<0b01110101000111011>, ++ LASX_3R_DESC_BASE<"xvilvh.d", LoongArchVILVH, LASX256DOpnd>; ++ ++ ++def XVPICKEV_B : LASX_3R<0b01110101000111100>, ++ LASX_3R_DESC_BASE<"xvpickev.b", LoongArchVPICKEV, LASX256BOpnd>; ++ ++def XVPICKEV_H : LASX_3R<0b01110101000111101>, ++ LASX_3R_DESC_BASE<"xvpickev.h", LoongArchVPICKEV, LASX256HOpnd>; ++ ++def XVPICKEV_W : LASX_3R<0b01110101000111110>, ++ LASX_3R_DESC_BASE<"xvpickev.w", LoongArchVPICKEV, LASX256WOpnd>; ++ ++def XVPICKEV_D : LASX_3R<0b01110101000111111>, ++ LASX_3R_DESC_BASE<"xvpickev.d", LoongArchVPICKEV, LASX256DOpnd>; ++ ++ ++def XVPICKOD_B : LASX_3R<0b01110101001000000>, ++ LASX_3R_DESC_BASE<"xvpickod.b", LoongArchVPICKOD, LASX256BOpnd>; ++ ++def XVPICKOD_H : LASX_3R<0b01110101001000001>, ++ LASX_3R_DESC_BASE<"xvpickod.h", LoongArchVPICKOD, LASX256HOpnd>; ++ ++def XVPICKOD_W : LASX_3R<0b01110101001000010>, ++ LASX_3R_DESC_BASE<"xvpickod.w", LoongArchVPICKOD, LASX256WOpnd>; ++ ++def XVPICKOD_D : LASX_3R<0b01110101001000011>, ++ LASX_3R_DESC_BASE<"xvpickod.d", LoongArchVPICKOD, LASX256DOpnd>; ++ ++ ++def XVREPLVE_B : LASX_3R_1GP<0b01110101001000100>, ++ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.b", int_loongarch_lasx_xvreplve_b, LASX256BOpnd>; ++ ++def XVREPLVE_H : LASX_3R_1GP<0b01110101001000101>, ++ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.h", int_loongarch_lasx_xvreplve_h, LASX256HOpnd>; ++ ++def XVREPLVE_W : LASX_3R_1GP<0b01110101001000110>, ++ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.w", int_loongarch_lasx_xvreplve_w, LASX256WOpnd>; ++ ++def XVREPLVE_D : LASX_3R_1GP<0b01110101001000111>, ++ LASX_3R_VREPLVE_DESC_BASE<"xvreplve.d", int_loongarch_lasx_xvreplve_d, LASX256DOpnd>; ++ ++ ++def XVAND_V : LASX_3R<0b01110101001001100>, ++ LASX_VEC_DESC_BASE<"xvand.v", and, LASX256BOpnd>; ++class XAND_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XAND_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XAND_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++ ++def XAND_V_H_PSEUDO : XAND_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XAND_V_W_PSEUDO : XAND_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XAND_V_D_PSEUDO : XAND_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(XVAND_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++ ++def XVOR_V : LASX_3R<0b01110101001001101>, ++ LASX_VEC_DESC_BASE<"xvor.v", or, LASX256BOpnd>; ++class X_OR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class X_OR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class X_OR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++ ++def X_OR_V_H_PSEUDO : X_OR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def X_OR_V_W_PSEUDO : X_OR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def X_OR_V_D_PSEUDO : X_OR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(XVOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++ ++def XVXOR_V : LASX_3R<0b01110101001001110>, ++ LASX_VEC_DESC_BASE<"xvxor.v", xor, LASX256BOpnd>; ++class XXOR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XXOR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XXOR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++ ++def XXOR_V_H_PSEUDO : XXOR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XXOR_V_W_PSEUDO : XXOR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XXOR_V_D_PSEUDO : XXOR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(XVXOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++ ++def XVNOR_V : LASX_3R<0b01110101001001111>, ++ LASX_VEC_DESC_BASE<"xvnor.v", LoongArchVNOR, LASX256BOpnd>; ++ ++class XNOR_V_H_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XNOR_V_W_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++class XNOR_V_D_PSEUDO_DESC : LASX_VEC_PSEUDO_BASE; ++ ++def XNOR_V_H_PSEUDO : XNOR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XNOR_V_W_PSEUDO : XNOR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++def XNOR_V_D_PSEUDO : XNOR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(XVNOR_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++ ++def XVANDN_V : LASX_3R<0b01110101001010000>, ++ LASX_3R_DESC_BASE<"xvandn.v", int_loongarch_lasx_xvandn_v, LASX256BOpnd>; ++ ++ ++class LASX_ANDN_PSEUDO_BASE : ++ LASXPseudo<(outs RO:$xd), (ins RO:$xj, RO:$xk), ++ []>, ++ PseudoInstExpansion<(XVANDN_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++def XVANDN_H_PSEUDO : LASX_ANDN_PSEUDO_BASE; ++def XVANDN_W_PSEUDO : LASX_ANDN_PSEUDO_BASE; ++def XVANDN_D_PSEUDO : LASX_ANDN_PSEUDO_BASE; ++ ++ ++def XVORN_V : LASX_3R<0b01110101001010001>, ++ LASX_3R_DESC_BASE<"xvorn.v", int_loongarch_lasx_xvorn_v, LASX256BOpnd>; ++ ++ ++class LASX_ORN_PSEUDO_BASE : ++ LASXPseudo<(outs RO:$xd), (ins RO:$xj, RO:$xk), ++ []>, ++ PseudoInstExpansion<(XVORN_V LASX256BOpnd:$xd, ++ LASX256BOpnd:$xj, ++ LASX256BOpnd:$xk)>; ++ ++def XVORN_H_PSEUDO : LASX_ORN_PSEUDO_BASE; ++def XVORN_W_PSEUDO : LASX_ORN_PSEUDO_BASE; ++def XVORN_D_PSEUDO : LASX_ORN_PSEUDO_BASE; ++ ++ ++def XVFRSTP_B : LASX_3R<0b01110101001010110>, ++ LASX_3R_4R_DESC_BASE<"xvfrstp.b", int_loongarch_lasx_xvfrstp_b, LASX256BOpnd>; ++ ++def XVFRSTP_H : LASX_3R<0b01110101001010111>, ++ LASX_3R_4R_DESC_BASE<"xvfrstp.h", int_loongarch_lasx_xvfrstp_h, LASX256HOpnd>; ++ ++ ++def XVADD_Q : LASX_3R<0b01110101001011010>, IsCommutable, ++ LASX_3R_DESC_BASE<"xvadd.q", int_loongarch_lasx_xvadd_q, LASX256DOpnd>; ++ ++def XVSUB_Q : LASX_3R<0b01110101001011011>, ++ LASX_3R_DESC_BASE<"xvsub.q", int_loongarch_lasx_xvsub_q, LASX256DOpnd>; ++ ++ ++def XVSIGNCOV_B : LASX_3R<0b01110101001011100>, ++ LASX_3R_DESC_BASE<"xvsigncov.b", int_loongarch_lasx_xvsigncov_b, LASX256BOpnd>; ++ ++def XVSIGNCOV_H : LASX_3R<0b01110101001011101>, ++ LASX_3R_DESC_BASE<"xvsigncov.h", int_loongarch_lasx_xvsigncov_h, LASX256HOpnd>; ++ ++def XVSIGNCOV_W : LASX_3R<0b01110101001011110>, ++ LASX_3R_DESC_BASE<"xvsigncov.w", int_loongarch_lasx_xvsigncov_w, LASX256WOpnd>; ++ ++def XVSIGNCOV_D : LASX_3R<0b01110101001011111>, ++ LASX_3R_DESC_BASE<"xvsigncov.d", int_loongarch_lasx_xvsigncov_d, LASX256DOpnd>; ++ ++ ++def XVFADD_S : LASX_3R<0b01110101001100001>, IsCommutable, ++ LASX_3RF_DESC_BASE<"xvfadd.s", fadd, LASX256WOpnd>; ++ ++def XVFADD_D : LASX_3R<0b01110101001100010>, IsCommutable, ++ LASX_3RF_DESC_BASE<"xvfadd.d", fadd, LASX256DOpnd>; ++ ++ ++def XVFSUB_S : LASX_3R<0b01110101001100101>, ++ LASX_3RF_DESC_BASE<"xvfsub.s", fsub, LASX256WOpnd>; ++ ++def XVFSUB_D : LASX_3R<0b01110101001100110>, ++ LASX_3RF_DESC_BASE<"xvfsub.d", fsub, LASX256DOpnd>; ++ ++ ++def XVFMUL_S : LASX_3R<0b01110101001110001>, ++ LASX_3RF_DESC_BASE<"xvfmul.s", fmul, LASX256WOpnd>; ++ ++def XVFMUL_D : LASX_3R<0b01110101001110010>, ++ LASX_3RF_DESC_BASE<"xvfmul.d", fmul, LASX256DOpnd>; ++ ++ ++def XVFDIV_S : LASX_3R<0b01110101001110101>, ++ LASX_3RF_DESC_BASE<"xvfdiv.s", fdiv, LASX256WOpnd>; ++ ++def XVFDIV_D : LASX_3R<0b01110101001110110>, ++ LASX_3RF_DESC_BASE<"xvfdiv.d", fdiv, LASX256DOpnd>; ++ ++ ++def XVFMAX_S : LASX_3R<0b01110101001111001>, ++ LASX_3RF_DESC_BASE<"xvfmax.s", int_loongarch_lasx_xvfmax_s, LASX256WOpnd>; ++ ++def XVFMAX_D : LASX_3R<0b01110101001111010>, ++ LASX_3RF_DESC_BASE<"xvfmax.d", int_loongarch_lasx_xvfmax_d, LASX256DOpnd>; ++ ++ ++def XVFMIN_S : LASX_3R<0b01110101001111101>, ++ LASX_3RF_DESC_BASE<"xvfmin.s", int_loongarch_lasx_xvfmin_s, LASX256WOpnd>; ++ ++def XVFMIN_D : LASX_3R<0b01110101001111110>, ++ LASX_3RF_DESC_BASE<"xvfmin.d", int_loongarch_lasx_xvfmin_d, LASX256DOpnd>; ++ ++ ++def XVFMAXA_S : LASX_3R<0b01110101010000001>, ++ LASX_3RF_DESC_BASE<"xvfmaxa.s", int_loongarch_lasx_xvfmaxa_s, LASX256WOpnd>; ++ ++def XVFMAXA_D : LASX_3R<0b01110101010000010>, ++ LASX_3RF_DESC_BASE<"xvfmaxa.d", int_loongarch_lasx_xvfmaxa_d, LASX256DOpnd>; ++ ++ ++def XVFMINA_S : LASX_3R<0b01110101010000101>, ++ LASX_3RF_DESC_BASE<"xvfmina.s", int_loongarch_lasx_xvfmina_s, LASX256WOpnd>; ++ ++def XVFMINA_D : LASX_3R<0b01110101010000110>, ++ LASX_3RF_DESC_BASE<"xvfmina.d", int_loongarch_lasx_xvfmina_d, LASX256DOpnd>; ++ ++ ++def XVFCVT_H_S : LASX_3R<0b01110101010001100>, ++ LASX_3RF_DESC_BASE<"xvfcvt.h.s", int_loongarch_lasx_xvfcvt_h_s, LASX256HOpnd, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVFCVT_S_D : LASX_3R<0b01110101010001101>, ++ LASX_3RF_DESC_BASE1<"xvfcvt.s.d", int_loongarch_lasx_xvfcvt_s_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVFFINT_S_L : LASX_3R<0b01110101010010000>, ++ LASX_3RF_DESC_BASE<"xvffint.s.l", int_loongarch_lasx_xvffint_s_l, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++def XVFTINT_W_D : LASX_3R<0b01110101010010011>, ++ LASX_3RF_DESC_BASE<"xvftint.w.d", int_loongarch_lasx_xvftint_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVFTINTRM_W_D : LASX_3R<0b01110101010010100>, ++ LASX_3RF_DESC_BASE<"xvftintrm.w.d", int_loongarch_lasx_xvftintrm_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++def XVFTINTRP_W_D : LASX_3R<0b01110101010010101>, ++ LASX_3RF_DESC_BASE<"xvftintrp.w.d", int_loongarch_lasx_xvftintrp_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++def XVFTINTRZ_W_D : LASX_3R<0b01110101010010110>, ++ LASX_3RF_DESC_BASE<"xvftintrz.w.d", int_loongarch_lasx_xvftintrz_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++def XVFTINTRNE_W_D : LASX_3R<0b01110101010010111>, ++ LASX_3RF_DESC_BASE<"xvftintrne.w.d", int_loongarch_lasx_xvftintrne_w_d, LASX256WOpnd, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSHUF_H : LASX_3R<0b01110101011110101>, ++ LASX_3R_VSHF_DESC_BASE<"xvshuf.h", LASX256HOpnd>; ++ ++def XVSHUF_W : LASX_3R<0b01110101011110110>, ++ LASX_3R_VSHF_DESC_BASE<"xvshuf.w", LASX256WOpnd>; ++ ++def XVSHUF_D : LASX_3R<0b01110101011110111>, ++ LASX_3R_VSHF_DESC_BASE<"xvshuf.d", LASX256DOpnd>; ++ ++ ++def XVPERM_W : LASX_3R<0b01110101011111010>, ++ LASX_3R_DESC_BASE<"xvperm.w", int_loongarch_lasx_xvperm_w, LASX256WOpnd>; ++ ++ ++def XVSEQI_B : LASX_I5<0b01110110100000000>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.b", int_loongarch_lasx_xvseqi_b, simm5_32, immSExt5, LASX256BOpnd>; ++ ++def XVSEQI_H : LASX_I5<0b01110110100000001>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.h", int_loongarch_lasx_xvseqi_h, simm5_32, immSExt5, LASX256HOpnd>; ++ ++def XVSEQI_W : LASX_I5<0b01110110100000010>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.w", int_loongarch_lasx_xvseqi_w, simm5_32, immSExt5, LASX256WOpnd>; ++ ++def XVSEQI_D : LASX_I5<0b01110110100000011>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvseqi.d", int_loongarch_lasx_xvseqi_d, simm5_32, immSExt5, LASX256DOpnd>; ++ ++ ++def XVSLEI_B : LASX_I5<0b01110110100000100>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.b", int_loongarch_lasx_xvslei_b, simm5_32, immSExt5, LASX256BOpnd>; ++ ++def XVSLEI_H : LASX_I5<0b01110110100000101>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.h", int_loongarch_lasx_xvslei_h, simm5_32, immSExt5, LASX256HOpnd>; ++ ++def XVSLEI_W : LASX_I5<0b01110110100000110>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.w", int_loongarch_lasx_xvslei_w, simm5_32, immSExt5, LASX256WOpnd>; ++ ++def XVSLEI_D : LASX_I5<0b01110110100000111>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslei.d", int_loongarch_lasx_xvslei_d, simm5_32, immSExt5, LASX256DOpnd>; ++ ++ ++def XVSLEI_BU : LASX_I5_U<0b01110110100001000>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.bu", int_loongarch_lasx_xvslei_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVSLEI_HU : LASX_I5_U<0b01110110100001001>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.hu", int_loongarch_lasx_xvslei_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSLEI_WU : LASX_I5_U<0b01110110100001010>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.wu", int_loongarch_lasx_xvslei_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSLEI_DU : LASX_I5_U<0b01110110100001011>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslei.du", int_loongarch_lasx_xvslei_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVSLTI_B : LASX_I5<0b01110110100001100>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.b", int_loongarch_lasx_xvslti_b, simm5_32, immSExt5, LASX256BOpnd>; ++ ++def XVSLTI_H : LASX_I5<0b01110110100001101>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.h", int_loongarch_lasx_xvslti_h, simm5_32, immSExt5, LASX256HOpnd>; ++ ++def XVSLTI_W : LASX_I5<0b01110110100001110>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.w", int_loongarch_lasx_xvslti_w, simm5_32, immSExt5, LASX256WOpnd>; ++ ++def XVSLTI_D : LASX_I5<0b01110110100001111>, ++ LASX_I5_SETCC_DESC_BASE_Intrinsic<"xvslti.d", int_loongarch_lasx_xvslti_d, simm5_32, immSExt5, LASX256DOpnd>; ++ ++ ++def XVSLTI_BU : LASX_I5_U<0b01110110100010000>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.bu", int_loongarch_lasx_xvslti_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVSLTI_HU : LASX_I5_U<0b01110110100010001>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.hu", int_loongarch_lasx_xvslti_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSLTI_WU : LASX_I5_U<0b01110110100010010>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.wu", int_loongarch_lasx_xvslti_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSLTI_DU : LASX_I5_U<0b01110110100010011>, ++ LASX_I5_U_SETCC_DESC_BASE_Intrinsic<"xvslti.du", int_loongarch_lasx_xvslti_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVADDI_BU : LASX_I5_U<0b01110110100010100>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.bu", int_loongarch_lasx_xvaddi_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVADDI_HU : LASX_I5_U<0b01110110100010101>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.hu", int_loongarch_lasx_xvaddi_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVADDI_WU : LASX_I5_U<0b01110110100010110>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.wu", int_loongarch_lasx_xvaddi_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVADDI_DU : LASX_I5_U<0b01110110100010111>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvaddi.du", int_loongarch_lasx_xvaddi_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVSUBI_BU : LASX_I5_U<0b01110110100011000>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.bu", int_loongarch_lasx_xvsubi_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVSUBI_HU : LASX_I5_U<0b01110110100011001>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.hu", int_loongarch_lasx_xvsubi_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSUBI_WU : LASX_I5_U<0b01110110100011010>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.wu", int_loongarch_lasx_xvsubi_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSUBI_DU : LASX_I5_U<0b01110110100011011>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvsubi.du", int_loongarch_lasx_xvsubi_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVBSLL_V : LASX_I5_U<0b01110110100011100>, ++ LASX_U5_DESC_BASE<"xvbsll.v", int_loongarch_lasx_xvbsll_v, LASX256BOpnd>; ++ ++def XVBSRL_V : LASX_I5_U<0b01110110100011101>, ++ LASX_U5_DESC_BASE<"xvbsrl.v", int_loongarch_lasx_xvbsrl_v, LASX256BOpnd>; ++ ++ ++def XVMAXI_B : LASX_I5<0b01110110100100000>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.b", int_loongarch_lasx_xvmaxi_b, simm5_32, immSExt5, LASX256BOpnd>; ++ ++def XVMAXI_H : LASX_I5<0b01110110100100001>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.h", int_loongarch_lasx_xvmaxi_h, simm5_32, immSExt5, LASX256HOpnd>; ++ ++def XVMAXI_W : LASX_I5<0b01110110100100010>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.w", int_loongarch_lasx_xvmaxi_w, simm5_32, immSExt5, LASX256WOpnd>; ++ ++def XVMAXI_D : LASX_I5<0b01110110100100011>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmaxi.d", int_loongarch_lasx_xvmaxi_d, simm5_32, immSExt5, LASX256DOpnd>; ++ ++ ++def XVMINI_B : LASX_I5<0b01110110100100100>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmini.b", int_loongarch_lasx_xvmini_b, simm5_32, immSExt5, LASX256BOpnd>; ++ ++def XVMINI_H : LASX_I5<0b01110110100100101>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmini.h", int_loongarch_lasx_xvmini_h, simm5_32, immSExt5, LASX256HOpnd>; ++ ++def XVMINI_W : LASX_I5<0b01110110100100110>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmini.w", int_loongarch_lasx_xvmini_w, simm5_32, immSExt5, LASX256WOpnd>; ++ ++def XVMINI_D : LASX_I5<0b01110110100100111>, ++ LASX_I5_DESC_BASE_Intrinsic<"xvmini.d", int_loongarch_lasx_xvmini_d, simm5_32, immSExt5, LASX256DOpnd>; ++ ++ ++def XVMAXI_BU : LASX_I5_U<0b01110110100101000>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.bu", int_loongarch_lasx_xvmaxi_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVMAXI_HU : LASX_I5_U<0b01110110100101001>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.hu", int_loongarch_lasx_xvmaxi_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVMAXI_WU : LASX_I5_U<0b01110110100101010>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.wu", int_loongarch_lasx_xvmaxi_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVMAXI_DU : LASX_I5_U<0b01110110100101011>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmaxi.du", int_loongarch_lasx_xvmaxi_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVMINI_BU : LASX_I5_U<0b01110110100101100>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.bu", int_loongarch_lasx_xvmini_bu, uimm5, immZExt5, LASX256BOpnd>; ++ ++def XVMINI_HU : LASX_I5_U<0b01110110100101101>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.hu", int_loongarch_lasx_xvmini_hu, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVMINI_WU : LASX_I5_U<0b01110110100101110>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.wu", int_loongarch_lasx_xvmini_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVMINI_DU : LASX_I5_U<0b01110110100101111>, ++ LASX_I5_U_DESC_BASE_Intrinsic<"xvmini.du", int_loongarch_lasx_xvmini_du, uimm5, immZExt5, LASX256DOpnd>; ++ ++ ++def XVFRSTPI_B : LASX_I5_U<0b01110110100110100>, ++ LASX_U5_4R_DESC_BASE<"xvfrstpi.b", int_loongarch_lasx_xvfrstpi_b, LASX256BOpnd>; ++ ++def XVFRSTPI_H : LASX_I5_U<0b01110110100110101>, ++ LASX_U5_4R_DESC_BASE<"xvfrstpi.h", int_loongarch_lasx_xvfrstpi_h, LASX256HOpnd>; ++ ++ ++def XVCLO_B : LASX_2R<0b0111011010011100000000>, ++ LASX_2R_DESC_BASE<"xvclo.b", int_loongarch_lasx_xvclo_b, LASX256BOpnd>; ++ ++def XVCLO_H : LASX_2R<0b0111011010011100000001>, ++ LASX_2R_DESC_BASE<"xvclo.h", int_loongarch_lasx_xvclo_h, LASX256HOpnd>; ++ ++def XVCLO_W : LASX_2R<0b0111011010011100000010>, ++ LASX_2R_DESC_BASE<"xvclo.w", int_loongarch_lasx_xvclo_w, LASX256WOpnd>; ++ ++def XVCLO_D : LASX_2R<0b0111011010011100000011>, ++ LASX_2R_DESC_BASE<"xvclo.d", int_loongarch_lasx_xvclo_d, LASX256DOpnd>; ++ ++ ++def XVCLZ_B : LASX_2R<0b0111011010011100000100>, ++ LASX_2R_DESC_BASE<"xvclz.b", ctlz, LASX256BOpnd>; ++ ++def XVCLZ_H : LASX_2R<0b0111011010011100000101>, ++ LASX_2R_DESC_BASE<"xvclz.h", ctlz, LASX256HOpnd>; ++ ++def XVCLZ_W : LASX_2R<0b0111011010011100000110>, ++ LASX_2R_DESC_BASE<"xvclz.w", ctlz, LASX256WOpnd>; ++ ++def XVCLZ_D : LASX_2R<0b0111011010011100000111>, ++ LASX_2R_DESC_BASE<"xvclz.d", ctlz, LASX256DOpnd>; ++ ++ ++def XVPCNT_B : LASX_2R<0b0111011010011100001000>, ++ LASX_2R_DESC_BASE<"xvpcnt.b", ctpop, LASX256BOpnd>; ++ ++def XVPCNT_H : LASX_2R<0b0111011010011100001001>, ++ LASX_2R_DESC_BASE<"xvpcnt.h", ctpop, LASX256HOpnd>; ++ ++def XVPCNT_W : LASX_2R<0b0111011010011100001010>, ++ LASX_2R_DESC_BASE<"xvpcnt.w", ctpop, LASX256WOpnd>; ++ ++def XVPCNT_D : LASX_2R<0b0111011010011100001011>, ++ LASX_2R_DESC_BASE<"xvpcnt.d", ctpop, LASX256DOpnd>; ++ ++ ++def XVNEG_B : LASX_2R<0b0111011010011100001100>, ++ LASX_2R_DESC_BASE<"xvneg.b", int_loongarch_lasx_xvneg_b, LASX256BOpnd>; ++ ++def XVNEG_H : LASX_2R<0b0111011010011100001101>, ++ LASX_2R_DESC_BASE<"xvneg.h", int_loongarch_lasx_xvneg_h, LASX256HOpnd>; ++ ++def XVNEG_W : LASX_2R<0b0111011010011100001110>, ++ LASX_2R_DESC_BASE<"xvneg.w", int_loongarch_lasx_xvneg_w, LASX256WOpnd>; ++ ++def XVNEG_D : LASX_2R<0b0111011010011100001111>, ++ LASX_2R_DESC_BASE<"xvneg.d", int_loongarch_lasx_xvneg_d, LASX256DOpnd>; ++ ++ ++def XVMSKLTZ_B : LASX_2R<0b0111011010011100010000>, ++ LASX_2R_DESC_BASE<"xvmskltz.b", int_loongarch_lasx_xvmskltz_b, LASX256BOpnd>; ++ ++def XVMSKLTZ_H : LASX_2R<0b0111011010011100010001>, ++ LASX_2R_DESC_BASE<"xvmskltz.h", int_loongarch_lasx_xvmskltz_h, LASX256HOpnd>; ++ ++def XVMSKLTZ_W : LASX_2R<0b0111011010011100010010>, ++ LASX_2R_DESC_BASE<"xvmskltz.w", int_loongarch_lasx_xvmskltz_w, LASX256WOpnd>; ++ ++def XVMSKLTZ_D : LASX_2R<0b0111011010011100010011>, ++ LASX_2R_DESC_BASE<"xvmskltz.d", int_loongarch_lasx_xvmskltz_d, LASX256DOpnd>; ++ ++ ++def XVMSKGEZ_B : LASX_2R<0b0111011010011100010100>, ++ LASX_2R_DESC_BASE<"xvmskgez.b", int_loongarch_lasx_xvmskgez_b, LASX256BOpnd>; ++ ++def XVMSKNZ_B : LASX_2R<0b0111011010011100011000>, ++ LASX_2R_DESC_BASE<"xvmsknz.b", int_loongarch_lasx_xvmsknz_b, LASX256BOpnd>; ++ ++ ++def XVSETEQZ_V : LASX_SET<0b0111011010011100100110>, ++ LASX_SET_DESC_BASE<"xvseteqz.v", LASX256BOpnd>; ++ ++def XVSETNEZ_V : LASX_SET<0b0111011010011100100111>, ++ LASX_SET_DESC_BASE<"xvsetnez.v", LASX256BOpnd>; ++ ++ ++def XVSETANYEQZ_B : LASX_SET<0b0111011010011100101000>, ++ LASX_SET_DESC_BASE<"xvsetanyeqz.b", LASX256BOpnd>; ++ ++def XVSETANYEQZ_H : LASX_SET<0b0111011010011100101001>, ++ LASX_SET_DESC_BASE<"xvsetanyeqz.h", LASX256HOpnd>; ++ ++def XVSETANYEQZ_W : LASX_SET<0b0111011010011100101010>, ++ LASX_SET_DESC_BASE<"xvsetanyeqz.w", LASX256WOpnd>; ++ ++def XVSETANYEQZ_D : LASX_SET<0b0111011010011100101011>, ++ LASX_SET_DESC_BASE<"xvsetanyeqz.d", LASX256DOpnd>; ++ ++ ++def XVSETALLNEZ_B : LASX_SET<0b0111011010011100101100>, ++ LASX_SET_DESC_BASE<"xvsetallnez.b", LASX256BOpnd>; ++ ++def XVSETALLNEZ_H : LASX_SET<0b0111011010011100101101>, ++ LASX_SET_DESC_BASE<"xvsetallnez.h", LASX256HOpnd>; ++ ++def XVSETALLNEZ_W : LASX_SET<0b0111011010011100101110>, ++ LASX_SET_DESC_BASE<"xvsetallnez.w", LASX256WOpnd>; ++ ++def XVSETALLNEZ_D : LASX_SET<0b0111011010011100101111>, ++ LASX_SET_DESC_BASE<"xvsetallnez.d", LASX256DOpnd>; ++ ++class LASX_CBRANCH_PSEUDO_DESC_BASE : ++ LoongArchPseudo<(outs GPR32:$dst), ++ (ins RCWS:$xj), ++ [(set GPR32:$dst, (OpNode (TyNode RCWS:$xj)))]> { ++ bit usesCustomInserter = 1; ++} ++ ++def XSNZ_B_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSNZ_H_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSNZ_W_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSNZ_D_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSNZ_V_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++ ++def XSZ_B_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSZ_H_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSZ_W_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSZ_D_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++def XSZ_V_PSEUDO : LASX_CBRANCH_PSEUDO_DESC_BASE; ++ ++ ++def XVFLOGB_S : LASX_2R<0b0111011010011100110001>, ++ LASX_2RF_DESC_BASE<"xvflogb.s", int_loongarch_lasx_xvflogb_s, LASX256WOpnd>; ++ ++def XVFLOGB_D : LASX_2R<0b0111011010011100110010>, ++ LASX_2RF_DESC_BASE<"xvflogb.d", int_loongarch_lasx_xvflogb_d, LASX256DOpnd>; ++ ++ ++def XVFCLASS_S : LASX_2R<0b0111011010011100110101>, ++ LASX_2RF_DESC_BASE<"xvfclass.s", int_loongarch_lasx_xvfclass_s, LASX256WOpnd>; ++ ++def XVFCLASS_D : LASX_2R<0b0111011010011100110110>, ++ LASX_2RF_DESC_BASE<"xvfclass.d", int_loongarch_lasx_xvfclass_d, LASX256DOpnd>; ++ ++ ++def XVFSQRT_S : LASX_2R<0b0111011010011100111001>, ++ LASX_2RF_DESC_BASE<"xvfsqrt.s", fsqrt, LASX256WOpnd>; ++ ++def XVFSQRT_D : LASX_2R<0b0111011010011100111010>, ++ LASX_2RF_DESC_BASE<"xvfsqrt.d", fsqrt, LASX256DOpnd>; ++ ++ ++def XVFRECIP_S : LASX_2R<0b0111011010011100111101>, ++ LASX_2RF_DESC_BASE<"xvfrecip.s", int_loongarch_lasx_xvfrecip_s, LASX256WOpnd>; ++ ++def XVFRECIP_D : LASX_2R<0b0111011010011100111110>, ++ LASX_2RF_DESC_BASE<"xvfrecip.d", int_loongarch_lasx_xvfrecip_d, LASX256DOpnd>; ++ ++ ++def XVFRSQRT_S : LASX_2R<0b0111011010011101000001>, ++ LASX_2RF_DESC_BASE<"xvfrsqrt.s", int_loongarch_lasx_xvfrsqrt_s, LASX256WOpnd>; ++ ++def XVFRSQRT_D : LASX_2R<0b0111011010011101000010>, ++ LASX_2RF_DESC_BASE<"xvfrsqrt.d", int_loongarch_lasx_xvfrsqrt_d, LASX256DOpnd>; ++ ++ ++def XVFRINT_S : LASX_2R<0b0111011010011101001101>, ++ LASX_2RF_DESC_BASE<"xvfrint.s", frint, LASX256WOpnd>; ++ ++def XVFRINT_D : LASX_2R<0b0111011010011101001110>, ++ LASX_2RF_DESC_BASE<"xvfrint.d", frint, LASX256DOpnd>; ++ ++ ++def XVFRINTRM_S : LASX_2R<0b0111011010011101010001>, ++ LASX_2RF_DESC_BASE<"xvfrintrm.s", int_loongarch_lasx_xvfrintrm_s, LASX256WOpnd>; ++ ++def XVFRINTRM_D : LASX_2R<0b0111011010011101010010>, ++ LASX_2RF_DESC_BASE<"xvfrintrm.d", int_loongarch_lasx_xvfrintrm_d, LASX256DOpnd>; ++ ++ ++def XVFRINTRP_S : LASX_2R<0b0111011010011101010101>, ++ LASX_2RF_DESC_BASE<"xvfrintrp.s", int_loongarch_lasx_xvfrintrp_s, LASX256WOpnd>; ++ ++def XVFRINTRP_D : LASX_2R<0b0111011010011101010110>, ++ LASX_2RF_DESC_BASE<"xvfrintrp.d", int_loongarch_lasx_xvfrintrp_d, LASX256DOpnd>; ++ ++ ++def XVFRINTRZ_S : LASX_2R<0b0111011010011101011001>, ++ LASX_2RF_DESC_BASE<"xvfrintrz.s", int_loongarch_lasx_xvfrintrz_s, LASX256WOpnd>; ++ ++def XVFRINTRZ_D : LASX_2R<0b0111011010011101011010>, ++ LASX_2RF_DESC_BASE<"xvfrintrz.d", int_loongarch_lasx_xvfrintrz_d, LASX256DOpnd>; ++ ++ ++def XVFRINTRNE_S : LASX_2R<0b0111011010011101011101>, ++ LASX_2RF_DESC_BASE<"xvfrintrne.s", int_loongarch_lasx_xvfrintrne_s, LASX256WOpnd>; ++ ++def XVFRINTRNE_D : LASX_2R<0b0111011010011101011110>, ++ LASX_2RF_DESC_BASE<"xvfrintrne.d", int_loongarch_lasx_xvfrintrne_d, LASX256DOpnd>; ++ ++ ++def XVFCVTL_S_H : LASX_2R<0b0111011010011101111010>, ++ LASX_2RF_DESC_BASE<"xvfcvtl.s.h", int_loongarch_lasx_xvfcvtl_s_h, LASX256WOpnd, LASX256HOpnd>; ++ ++def XVFCVTH_S_H : LASX_2R<0b0111011010011101111011>, ++ LASX_2RF_DESC_BASE<"xvfcvth.s.h", int_loongarch_lasx_xvfcvth_s_h, LASX256WOpnd, LASX256HOpnd>; ++ ++ ++def XVFCVTL_D_S : LASX_2R<0b0111011010011101111100>, ++ LASX_2RF_DESC_BASE<"xvfcvtl.d.s", int_loongarch_lasx_xvfcvtl_d_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFCVTH_D_S : LASX_2R<0b0111011010011101111101>, ++ LASX_2RF_DESC_BASE<"xvfcvth.d.s", int_loongarch_lasx_xvfcvth_d_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFFINT_S_W : LASX_2R<0b0111011010011110000000>, ++ LASX_2RF_DESC_BASE<"xvffint.s.w", sint_to_fp, LASX256WOpnd>; ++ ++def XVFFINT_S_WU : LASX_2R<0b0111011010011110000001>, ++ LASX_2RF_DESC_BASE<"xvffint.s.wu", uint_to_fp, LASX256WOpnd>; ++ ++ ++def XVFFINT_D_L : LASX_2R<0b0111011010011110000010>, ++ LASX_2RF_DESC_BASE<"xvffint.d.l", sint_to_fp, LASX256DOpnd>; ++ ++def XVFFINT_D_LU : LASX_2R<0b0111011010011110000011>, ++ LASX_2RF_DESC_BASE<"xvffint.d.lu", uint_to_fp, LASX256DOpnd>; ++ ++ ++def XVFFINTL_D_W : LASX_2R<0b0111011010011110000100>, ++ LASX_2RF_DESC_BASE<"xvffintl.d.w", int_loongarch_lasx_xvffintl_d_w, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFFINTH_D_W : LASX_2R<0b0111011010011110000101>, ++ LASX_2RF_DESC_BASE<"xvffinth.d.w", int_loongarch_lasx_xvffinth_d_w, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFTINT_W_S : LASX_2R<0b0111011010011110001100>, ++ LASX_2RF_DESC_BASE<"xvftint.w.s", int_loongarch_lasx_xvftint_w_s, LASX256WOpnd>; ++ ++def XVFTINT_L_D : LASX_2R<0b0111011010011110001101>, ++ LASX_2RF_DESC_BASE<"xvftint.l.d", int_loongarch_lasx_xvftint_l_d, LASX256DOpnd>; ++ ++ ++def XVFTINTRM_W_S : LASX_2R<0b0111011010011110001110>, ++ LASX_2RF_DESC_BASE<"xvftintrm.w.s", int_loongarch_lasx_xvftintrm_w_s, LASX256WOpnd>; ++ ++def XVFTINTRM_L_D : LASX_2R<0b0111011010011110001111>, ++ LASX_2RF_DESC_BASE<"xvftintrm.l.d", int_loongarch_lasx_xvftintrm_l_d, LASX256DOpnd>; ++ ++ ++def XVFTINTRP_W_S : LASX_2R<0b0111011010011110010000>, ++ LASX_2RF_DESC_BASE<"xvftintrp.w.s", int_loongarch_lasx_xvftintrp_w_s, LASX256WOpnd>; ++ ++def XVFTINTRP_L_D : LASX_2R<0b0111011010011110010001>, ++ LASX_2RF_DESC_BASE<"xvftintrp.l.d", int_loongarch_lasx_xvftintrp_l_d, LASX256DOpnd>; ++ ++ ++def XVFTINTRZ_W_S : LASX_2R<0b0111011010011110010010>, ++ LASX_2RF_DESC_BASE<"xvftintrz.w.s", fp_to_sint, LASX256WOpnd>; ++ ++def XVFTINTRZ_L_D : LASX_2R<0b0111011010011110010011>, ++ LASX_2RF_DESC_BASE<"xvftintrz.l.d", fp_to_sint, LASX256DOpnd>; ++ ++ ++def XVFTINTRNE_W_S : LASX_2R<0b0111011010011110010100>, ++ LASX_2RF_DESC_BASE<"xvftintrne.w.s", int_loongarch_lasx_xvftintrne_w_s, LASX256WOpnd>; ++ ++def XVFTINTRNE_L_D : LASX_2R<0b0111011010011110010101>, ++ LASX_2RF_DESC_BASE<"xvftintrne.l.d", int_loongarch_lasx_xvftintrne_l_d, LASX256DOpnd>; ++ ++ ++def XVFTINT_WU_S : LASX_2R<0b0111011010011110010110>, ++ LASX_2RF_DESC_BASE<"xvftint.wu.s", int_loongarch_lasx_xvftint_wu_s, LASX256WOpnd>; ++ ++def XVFTINT_LU_D : LASX_2R<0b0111011010011110010111>, ++ LASX_2RF_DESC_BASE<"xvftint.lu.d", int_loongarch_lasx_xvftint_lu_d, LASX256DOpnd>; ++ ++ ++def XVFTINTRZ_WU_S : LASX_2R<0b0111011010011110011100>, ++ LASX_2RF_DESC_BASE<"xvftintrz.wu.s", fp_to_uint, LASX256WOpnd>; ++ ++def XVFTINTRZ_LU_D : LASX_2R<0b0111011010011110011101>, ++ LASX_2RF_DESC_BASE<"xvftintrz.lu.d", fp_to_uint, LASX256DOpnd>; ++ ++ ++def XVFTINTL_L_S : LASX_2R<0b0111011010011110100000>, ++ LASX_2RF_DESC_BASE<"xvftintl.l.s", int_loongarch_lasx_xvftintl_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFTINTH_L_S : LASX_2R<0b0111011010011110100001>, ++ LASX_2RF_DESC_BASE<"xvftinth.l.s", int_loongarch_lasx_xvftinth_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFTINTRML_L_S : LASX_2R<0b0111011010011110100010>, ++ LASX_2RF_DESC_BASE<"xvftintrml.l.s", int_loongarch_lasx_xvftintrml_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFTINTRMH_L_S : LASX_2R<0b0111011010011110100011>, ++ LASX_2RF_DESC_BASE<"xvftintrmh.l.s", int_loongarch_lasx_xvftintrmh_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFTINTRPL_L_S : LASX_2R<0b0111011010011110100100>, ++ LASX_2RF_DESC_BASE<"xvftintrpl.l.s", int_loongarch_lasx_xvftintrpl_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFTINTRPH_L_S : LASX_2R<0b0111011010011110100101>, ++ LASX_2RF_DESC_BASE<"xvftintrph.l.s", int_loongarch_lasx_xvftintrph_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFTINTRZL_L_S : LASX_2R<0b0111011010011110100110>, ++ LASX_2RF_DESC_BASE<"xvftintrzl.l.s", int_loongarch_lasx_xvftintrzl_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFTINTRZH_L_S : LASX_2R<0b0111011010011110100111>, ++ LASX_2RF_DESC_BASE<"xvftintrzh.l.s", int_loongarch_lasx_xvftintrzh_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVFTINTRNEL_L_S : LASX_2R<0b0111011010011110101000>, ++ LASX_2RF_DESC_BASE<"xvftintrnel.l.s", int_loongarch_lasx_xvftintrnel_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++def XVFTINTRNEH_L_S : LASX_2R<0b0111011010011110101001>, ++ LASX_2RF_DESC_BASE<"xvftintrneh.l.s", int_loongarch_lasx_xvftintrneh_l_s, LASX256DOpnd, LASX256WOpnd>; ++ ++ ++def XVEXTH_H_B : LASX_2R<0b0111011010011110111000>, ++ LASX_2R_DESC_BASE<"xvexth.h.b", int_loongarch_lasx_xvexth_h_b, LASX256HOpnd, LASX256BOpnd>; ++ ++def XVEXTH_W_H : LASX_2R<0b0111011010011110111001>, ++ LASX_2R_DESC_BASE<"xvexth.w.h", int_loongarch_lasx_xvexth_w_h, LASX256WOpnd, LASX256HOpnd>; ++ ++def XVEXTH_D_W : LASX_2R<0b0111011010011110111010>, ++ LASX_2R_DESC_BASE<"xvexth.d.w", int_loongarch_lasx_xvexth_d_w, LASX256DOpnd, LASX256WOpnd> ; ++ ++def XVEXTH_Q_D : LASX_2R<0b0111011010011110111011>, ++ LASX_2R_DESC_BASE<"xvexth.q.d", int_loongarch_lasx_xvexth_q_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVEXTH_HU_BU : LASX_2R<0b0111011010011110111100>, ++ LASX_2R_DESC_BASE<"xvexth.hu.bu", int_loongarch_lasx_xvexth_hu_bu, LASX256HOpnd, LASX256BOpnd>; ++ ++def XVEXTH_WU_HU : LASX_2R<0b0111011010011110111101>, ++ LASX_2R_DESC_BASE<"xvexth.wu.hu", int_loongarch_lasx_xvexth_wu_hu, LASX256WOpnd, LASX256HOpnd>; ++ ++def XVEXTH_DU_WU : LASX_2R<0b0111011010011110111110>, ++ LASX_2R_DESC_BASE<"xvexth.du.wu", int_loongarch_lasx_xvexth_du_wu, LASX256DOpnd, LASX256WOpnd> ; ++ ++def XVEXTH_QU_DU : LASX_2R<0b0111011010011110111111>, ++ LASX_2R_DESC_BASE<"xvexth.qu.du", int_loongarch_lasx_xvexth_qu_du, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVREPLGR2VR_B : LASX_2R_1GP<0b0111011010011111000000>, ++ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.b", v32i8, xvsplati8, LASX256BOpnd, GPR32Opnd>; ++ ++def XVREPLGR2VR_H : LASX_2R_1GP<0b0111011010011111000001>, ++ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.h", v16i16, xvsplati16, LASX256HOpnd, GPR32Opnd>; ++ ++def XVREPLGR2VR_W : LASX_2R_1GP<0b0111011010011111000010>, ++ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.w", v8i32, xvsplati32, LASX256WOpnd, GPR32Opnd>; ++ ++def XVREPLGR2VR_D : LASX_2R_1GP<0b0111011010011111000011>, ++ LASX_2R_REPL_DESC_BASE<"xvreplgr2vr.d", v4i64, xvsplati64, LASX256DOpnd, GPR64Opnd>; ++ ++ ++def VEXT2XV_H_B : LASX_2R<0b0111011010011111000100>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.h.b", int_loongarch_lasx_vext2xv_h_b, v32i8, v16i16, LASX256BOpnd, LASX256HOpnd>; ++ ++def VEXT2XV_W_B : LASX_2R<0b0111011010011111000101>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.w.b", int_loongarch_lasx_vext2xv_w_b, v32i8, v8i32, LASX256BOpnd, LASX256WOpnd>; ++ ++def VEXT2XV_D_B : LASX_2R<0b0111011010011111000110>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.b", int_loongarch_lasx_vext2xv_d_b, v32i8, v4i64, LASX256BOpnd, LASX256DOpnd> ; ++ ++def VEXT2XV_W_H : LASX_2R<0b0111011010011111000111>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.w.h", int_loongarch_lasx_vext2xv_w_h, v16i16, v8i32, LASX256HOpnd, LASX256WOpnd>; ++ ++def VEXT2XV_D_H : LASX_2R<0b0111011010011111001000>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.h", int_loongarch_lasx_vext2xv_d_h, v16i16, v4i64, LASX256HOpnd, LASX256DOpnd> ; ++ ++def VEXT2XV_D_W : LASX_2R<0b0111011010011111001001>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.d.w", int_loongarch_lasx_vext2xv_d_w, v8i32, v4i64, LASX256WOpnd, LASX256DOpnd>; ++ ++ ++def VEXT2XV_HU_BU : LASX_2R<0b0111011010011111001010>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.hu.bu", int_loongarch_lasx_vext2xv_hu_bu, v32i8, v16i16, LASX256BOpnd, LASX256HOpnd>; ++ ++def VEXT2XV_WU_BU : LASX_2R<0b0111011010011111001011>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.wu.bu", int_loongarch_lasx_vext2xv_wu_bu, v32i8, v8i32, LASX256BOpnd, LASX256WOpnd>; ++ ++def VEXT2XV_DU_BU : LASX_2R<0b0111011010011111001100>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.bu", int_loongarch_lasx_vext2xv_du_bu, v32i8, v4i64, LASX256BOpnd, LASX256DOpnd> ; ++ ++def VEXT2XV_WU_HU : LASX_2R<0b0111011010011111001101>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.wu.hu", int_loongarch_lasx_vext2xv_wu_hu, v16i16, v8i32, LASX256HOpnd, LASX256WOpnd>; ++ ++def VEXT2XV_DU_HU : LASX_2R<0b0111011010011111001110>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.hu", int_loongarch_lasx_vext2xv_du_hu, v16i16, v4i64, LASX256HOpnd, LASX256DOpnd> ; ++ ++def VEXT2XV_DU_WU : LASX_2R<0b0111011010011111001111>, ++ LASX_XVEXTEND_DESC_BASE<"vext2xv.du.wu", int_loongarch_lasx_vext2xv_du_wu, v8i32, v4i64, LASX256WOpnd, LASX256DOpnd>; ++ ++ ++def XVHSELI_D : LASX_I5_U<0b01110110100111111>, ++ LASX_U5N_DESC_BASE<"xvhseli.d", LASX256DOpnd>; ++ ++ ++def XVROTRI_B : LASX_I3_U<0b0111011010100000001>, ++ LASX_RORI_U3_DESC_BASE_Intrinsic<"xvrotri.b", int_loongarch_lasx_xvrotri_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVROTRI_H : LASX_I4_U<0b011101101010000001>, ++ LASX_RORI_U4_DESC_BASE_Intrinsic<"xvrotri.h", int_loongarch_lasx_xvrotri_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVROTRI_W : LASX_I5_U<0b01110110101000001>, ++ LASX_RORI_U5_DESC_BASE_Intrinsic<"xvrotri.w", int_loongarch_lasx_xvrotri_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVROTRI_D : LASX_I6_U<0b0111011010100001>, ++ LASX_RORI_U6_DESC_BASE_Intrinsic<"xvrotri.d", int_loongarch_lasx_xvrotri_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSRLRI_B : LASX_I3_U<0b0111011010100100001>, ++ LASX_BIT_3_DESC_BASE<"xvsrlri.b", int_loongarch_lasx_xvsrlri_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSRLRI_H : LASX_I4_U<0b011101101010010001>, ++ LASX_BIT_4_DESC_BASE<"xvsrlri.h", int_loongarch_lasx_xvsrlri_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSRLRI_W : LASX_I5_U<0b01110110101001001>, ++ LASX_BIT_5_DESC_BASE<"xvsrlri.w", int_loongarch_lasx_xvsrlri_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSRLRI_D : LASX_I6_U<0b0111011010100101>, ++ LASX_BIT_6_DESC_BASE<"xvsrlri.d", int_loongarch_lasx_xvsrlri_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSRARI_B : LASX_I3_U<0b0111011010101000001>, ++ LASX_BIT_3_DESC_BASE<"xvsrari.b", int_loongarch_lasx_xvsrari_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSRARI_H : LASX_I4_U<0b011101101010100001>, ++ LASX_BIT_4_DESC_BASE<"xvsrari.h", int_loongarch_lasx_xvsrari_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSRARI_W : LASX_I5_U<0b01110110101010001>, ++ LASX_BIT_5_DESC_BASE<"xvsrari.w", int_loongarch_lasx_xvsrari_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSRARI_D : LASX_I6_U<0b0111011010101001>, ++ LASX_BIT_6_DESC_BASE<"xvsrari.d", int_loongarch_lasx_xvsrari_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVINSGR2VR_W : LASX_I3_R_U<0b0111011011101011110>, ++ LASX_INSERT_U3_DESC_BASE<"xvinsgr2vr.w", v8i32, uimm3_ptr, immZExt3Ptr, LASX256WOpnd, GPR32Opnd>; ++ ++def XVINSGR2VR_D : LASX_I2_R_U<0b01110110111010111110>, ++ LASX_INSERT_U2_DESC_BASE<"xvinsgr2vr.d", v4i64, uimm2_ptr, immZExt2Ptr, LASX256DOpnd, GPR64Opnd>; ++ ++ ++def XVPICKVE2GR_W : LASX_ELM_COPY_U3<0b0111011011101111110>, ++ LASX_COPY_U3_DESC_BASE<"xvpickve2gr.w", vextract_sext_i32, v8i32, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LASX256WOpnd>; ++ ++def XVPICKVE2GR_D : LASX_ELM_COPY_U2<0b01110110111011111110>, ++ LASX_COPY_U2_DESC_BASE<"xvpickve2gr.d", vextract_sext_i64, v4i64, uimm2_ptr, immZExt2Ptr, GPR64Opnd, LASX256DOpnd>; ++ ++ ++def XVPICKVE2GR_WU : LASX_ELM_COPY_U3<0b0111011011110011110>, ++ LASX_COPY_U3_DESC_BASE<"xvpickve2gr.wu", vextract_zext_i32, v8i32, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LASX256WOpnd>; ++ ++def XVPICKVE2GR_DU : LASX_ELM_COPY_U2<0b01110110111100111110>, ++ LASX_COPY_U2_DESC_BASE<"xvpickve2gr.du", vextract_zext_i64, v4i64, uimm2_ptr, immZExt2Ptr, GPR64Opnd, LASX256DOpnd>; ++ ++ ++def XVREPL128VEI_B : LASX_I4_U<0b011101101111011110>, ++ LASX_ELM_U4_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.b", int_loongarch_lasx_xvrepl128vei_b, LASX256BOpnd>; ++ ++def XVREPL128VEI_H : LASX_I3_U<0b0111011011110111110>, ++ LASX_ELM_U3_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.h", int_loongarch_lasx_xvrepl128vei_h, LASX256HOpnd>; ++ ++def XVREPL128VEI_W : LASX_I2_U<0b01110110111101111110>, ++ LASX_ELM_U2_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.w", int_loongarch_lasx_xvrepl128vei_w, LASX256WOpnd>; ++ ++def XVREPL128VEI_D : LASX_I1_U<0b011101101111011111110>, ++ LASX_ELM_U1_VREPLVE_DESC_BASE_Intrinsic<"xvrepl128vei.d", int_loongarch_lasx_xvrepl128vei_d, LASX256DOpnd>; ++ ++ ++def XVINSVE0_W : LASX_I3_U<0b0111011011111111110>, ++ LASX_BIT_3_4O_DESC_BASE<"xvinsve0.w", int_loongarch_lasx_xvinsve0_w, uimm3, immZExt3, LASX256WOpnd>; ++ ++def XVINSVE0_D : LASX_I2_U<0b01110110111111111110>, ++ LASX_BIT_2_4O_DESC_BASE<"xvinsve0.d", int_loongarch_lasx_xvinsve0_d, uimm2, immZExt2, LASX256DOpnd>; ++ ++ ++def XVPICKVE_W : LASX_I3_U<0b0111011100000011110>, ++ LASX_BIT_3_4ON<"xvpickve.w", uimm3, immZExt3, LASX256WOpnd>; ++ ++def XVPICKVE_D : LASX_I2_U<0b01110111000000111110>, ++ LASX_BIT_2_4ON<"xvpickve.d", uimm2, immZExt2, LASX256DOpnd>; ++ ++ ++def XVREPLVE0_B : LASX_2R<0b0111011100000111000000>, ++ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.b", int_loongarch_lasx_xvreplve0_b, v32i8, LASX256BOpnd>; ++ ++def XVREPLVE0_H : LASX_2R<0b0111011100000111100000>, ++ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.h", int_loongarch_lasx_xvreplve0_h, v16i16, LASX256HOpnd>; ++ ++def XVREPLVE0_W : LASX_2R<0b0111011100000111110000>, ++ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.w", int_loongarch_lasx_xvreplve0_w, v8i32, LASX256WOpnd> ; ++ ++def XVREPLVE0_D : LASX_2R<0b0111011100000111111000>, ++ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.d", xvbroadcast_v4i64, v4i64, LASX256DOpnd>; ++ ++def XVREPLVE0_Q : LASX_2R<0b0111011100000111111100>, ++ LASX_XVBROADCAST_DESC_BASE<"xvreplve0.q", int_loongarch_lasx_xvreplve0_q, v32i8, LASX256BOpnd>; ++ ++ ++def XVSLLWIL_H_B : LASX_I3_U<0b0111011100001000001>, ++ LASX_2R_U3_DESC_BASE<"xvsllwil.h.b", int_loongarch_lasx_xvsllwil_h_b, LASX256HOpnd, LASX256BOpnd>; ++ ++def XVSLLWIL_W_H : LASX_I4_U<0b011101110000100001>, ++ LASX_2R_U4_DESC_BASE<"xvsllwil.w.h", int_loongarch_lasx_xvsllwil_w_h, LASX256WOpnd, LASX256HOpnd>; ++ ++def XVSLLWIL_D_W : LASX_I5_U<0b01110111000010001>, ++ LASX_2R_U5_DESC_BASE<"xvsllwil.d.w", int_loongarch_lasx_xvsllwil_d_w, LASX256DOpnd, LASX256WOpnd> ; ++ ++ ++def XVEXTL_Q_D : LASX_2R<0b0111011100001001000000>, ++ LASX_2R_DESC_BASE<"xvextl.q.d", int_loongarch_lasx_xvextl_q_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSLLWIL_HU_BU : LASX_I3_U<0b0111011100001100001>, ++ LASX_2R_U3_DESC_BASE<"xvsllwil.hu.bu", int_loongarch_lasx_xvsllwil_hu_bu, LASX256HOpnd, LASX256BOpnd>; ++ ++def XVSLLWIL_WU_HU : LASX_I4_U<0b011101110000110001>, ++ LASX_2R_U4_DESC_BASE<"xvsllwil.wu.hu", int_loongarch_lasx_xvsllwil_wu_hu, LASX256WOpnd, LASX256HOpnd>; ++ ++def XVSLLWIL_DU_WU : LASX_I5_U<0b01110111000011001>, ++ LASX_2R_U5_DESC_BASE<"xvsllwil.du.wu", int_loongarch_lasx_xvsllwil_du_wu, LASX256DOpnd, LASX256WOpnd> ; ++ ++ ++def XVEXTL_QU_DU : LASX_2R<0b0111011100001101000000>, ++ LASX_2R_DESC_BASE<"xvextl.qu.du", int_loongarch_lasx_xvextl_qu_du, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVBITCLRI_B : LASX_I3_U<0b0111011100010000001>, ++ LASX_2R_U3_DESC_BASE<"xvbitclri.b", int_loongarch_lasx_xvbitclri_b, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVBITCLRI_H : LASX_I4_U<0b011101110001000001>, ++ LASX_2R_U4_DESC_BASE<"xvbitclri.h", int_loongarch_lasx_xvbitclri_h, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVBITCLRI_W : LASX_I5_U<0b01110111000100001>, ++ LASX_2R_U5_DESC_BASE<"xvbitclri.w", int_loongarch_lasx_xvbitclri_w, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVBITCLRI_D : LASX_I6_U<0b0111011100010001>, ++ LASX_2R_U6_DESC_BASE<"xvbitclri.d", int_loongarch_lasx_xvbitclri_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVBITSETI_B : LASX_I3_U<0b0111011100010100001>, ++ LASX_2R_U3_DESC_BASE<"xvbitseti.b", int_loongarch_lasx_xvbitseti_b, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVBITSETI_H : LASX_I4_U<0b011101110001010001>, ++ LASX_2R_U4_DESC_BASE<"xvbitseti.h", int_loongarch_lasx_xvbitseti_h, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVBITSETI_W : LASX_I5_U<0b01110111000101001>, ++ LASX_2R_U5_DESC_BASE<"xvbitseti.w", int_loongarch_lasx_xvbitseti_w, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVBITSETI_D : LASX_I6_U<0b0111011100010101>, ++ LASX_2R_U6_DESC_BASE<"xvbitseti.d", int_loongarch_lasx_xvbitseti_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVBITREVI_B : LASX_I3_U<0b0111011100011000001>, ++ LASX_2R_U3_DESC_BASE<"xvbitrevi.b", int_loongarch_lasx_xvbitrevi_b, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVBITREVI_H : LASX_I4_U<0b011101110001100001>, ++ LASX_2R_U4_DESC_BASE<"xvbitrevi.h", int_loongarch_lasx_xvbitrevi_h, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVBITREVI_W : LASX_I5_U<0b01110111000110001>, ++ LASX_2R_U5_DESC_BASE<"xvbitrevi.w", int_loongarch_lasx_xvbitrevi_w, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVBITREVI_D : LASX_I6_U<0b0111011100011001>, ++ LASX_2R_U6_DESC_BASE<"xvbitrevi.d", int_loongarch_lasx_xvbitrevi_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSAT_B : LASX_I3_U<0b0111011100100100001>, ++ LASX_BIT_3_DESC_BASE<"xvsat.b", int_loongarch_lasx_xvsat_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSAT_H : LASX_I4_U<0b011101110010010001>, ++ LASX_BIT_4_DESC_BASE<"xvsat.h", int_loongarch_lasx_xvsat_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSAT_W : LASX_I5_U<0b01110111001001001>, ++ LASX_BIT_5_DESC_BASE<"xvsat.w", int_loongarch_lasx_xvsat_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSAT_D : LASX_I6_U<0b0111011100100101>, ++ LASX_BIT_6_DESC_BASE<"xvsat.d", int_loongarch_lasx_xvsat_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSAT_BU : LASX_I3_U<0b0111011100101000001>, ++ LASX_BIT_3_DESC_BASE<"xvsat.bu", int_loongarch_lasx_xvsat_bu, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSAT_HU : LASX_I4_U<0b011101110010100001>, ++ LASX_BIT_4_DESC_BASE<"xvsat.hu", int_loongarch_lasx_xvsat_hu, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSAT_WU : LASX_I5_U<0b01110111001010001>, ++ LASX_BIT_5_DESC_BASE<"xvsat.wu", int_loongarch_lasx_xvsat_wu, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSAT_DU : LASX_I6_U<0b0111011100101001>, ++ LASX_BIT_6_DESC_BASE<"xvsat.du", int_loongarch_lasx_xvsat_du, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSLLI_B : LASX_I3_U<0b0111011100101100001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvslli.b", int_loongarch_lasx_xvslli_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSLLI_H : LASX_I4_U<0b011101110010110001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvslli.h", int_loongarch_lasx_xvslli_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSLLI_W : LASX_I5_U<0b01110111001011001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvslli.w", int_loongarch_lasx_xvslli_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSLLI_D : LASX_I6_U<0b0111011100101101>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvslli.d", int_loongarch_lasx_xvslli_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSRLI_B : LASX_I3_U<0b0111011100110000001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.b", int_loongarch_lasx_xvsrli_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSRLI_H : LASX_I4_U<0b011101110011000001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.h", int_loongarch_lasx_xvsrli_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSRLI_W : LASX_I5_U<0b01110111001100001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.w", int_loongarch_lasx_xvsrli_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSRLI_D : LASX_I6_U<0b0111011100110001>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvsrli.d", int_loongarch_lasx_xvsrli_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSRAI_B : LASX_I3_U<0b0111011100110100001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.b", int_loongarch_lasx_xvsrai_b, uimm3, immZExt3, LASX256BOpnd>; ++ ++def XVSRAI_H : LASX_I4_U<0b011101110011010001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.h", int_loongarch_lasx_xvsrai_h, uimm4, immZExt4, LASX256HOpnd>; ++ ++def XVSRAI_W : LASX_I5_U<0b01110111001101001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.w", int_loongarch_lasx_xvsrai_w, uimm5, immZExt5, LASX256WOpnd>; ++ ++def XVSRAI_D : LASX_I6_U<0b0111011100110101>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"xvsrai.d", int_loongarch_lasx_xvsrai_d, uimm6, immZExt6, LASX256DOpnd>; ++ ++ ++def XVSRLNI_B_H : LASX_I4_U<0b011101110100000001>, ++ LASX_U4_DESC_BASE<"xvsrlni.b.h", int_loongarch_lasx_xvsrlni_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSRLNI_H_W : LASX_I5_U<0b01110111010000001>, ++ LASX_N4_U5_DESC_BASE<"xvsrlni.h.w", int_loongarch_lasx_xvsrlni_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSRLNI_W_D : LASX_I6_U<0b0111011101000001>, ++ LASX_U6_DESC_BASE<"xvsrlni.w.d", int_loongarch_lasx_xvsrlni_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSRLNI_D_Q : LASX_I7_U<0b011101110100001>, ++ LASX_D_DESC_BASE<"xvsrlni.d.q", int_loongarch_lasx_xvsrlni_d_q, LASX256DOpnd>; ++ ++ ++def XVSRLRNI_B_H : LASX_I4_U<0b011101110100010001>, ++ LASX_U4_DESC_BASE<"xvsrlrni.b.h", int_loongarch_lasx_xvsrlrni_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSRLRNI_H_W : LASX_I5_U<0b01110111010001001>, ++ LASX_N4_U5_DESC_BASE<"xvsrlrni.h.w", int_loongarch_lasx_xvsrlrni_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSRLRNI_W_D : LASX_I6_U<0b0111011101000101>, ++ LASX_U6_DESC_BASE<"xvsrlrni.w.d", int_loongarch_lasx_xvsrlrni_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSRLRNI_D_Q : LASX_I7_U<0b011101110100011>, ++ LASX_D_DESC_BASE<"xvsrlrni.d.q", int_loongarch_lasx_xvsrlrni_d_q, LASX256DOpnd>; ++ ++ ++def XVSSRLNI_B_H : LASX_I4_U<0b011101110100100001>, ++ LASX_U4_DESC_BASE<"xvssrlni.b.h", int_loongarch_lasx_xvssrlni_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRLNI_H_W : LASX_I5_U<0b01110111010010001>, ++ LASX_N4_U5_DESC_BASE<"xvssrlni.h.w", int_loongarch_lasx_xvssrlni_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRLNI_W_D : LASX_I6_U<0b0111011101001001>, ++ LASX_U6_DESC_BASE<"xvssrlni.w.d", int_loongarch_lasx_xvssrlni_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRLNI_D_Q : LASX_I7_U<0b011101110100101>, ++ LASX_D_DESC_BASE<"xvssrlni.d.q", int_loongarch_lasx_xvssrlni_d_q, LASX256DOpnd>; ++ ++ ++def XVSSRLNI_BU_H : LASX_I4_U<0b011101110100110001>, ++ LASX_U4_DESC_BASE<"xvssrlni.bu.h", int_loongarch_lasx_xvssrlni_bu_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRLNI_HU_W : LASX_I5_U<0b01110111010011001>, ++ LASX_N4_U5_DESC_BASE<"xvssrlni.hu.w", int_loongarch_lasx_xvssrlni_hu_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRLNI_WU_D : LASX_I6_U<0b0111011101001101>, ++ LASX_U6_DESC_BASE<"xvssrlni.wu.d", int_loongarch_lasx_xvssrlni_wu_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRLNI_DU_Q : LASX_I7_U<0b011101110100111>, ++ LASX_D_DESC_BASE<"xvssrlni.du.q", int_loongarch_lasx_xvssrlni_du_q, LASX256DOpnd>; ++ ++ ++def XVSSRLRNI_B_H : LASX_I4_U<0b011101110101000001>, ++ LASX_2R_3R_U4_DESC_BASE<"xvssrlrni.b.h", int_loongarch_lasx_xvssrlrni_b_h, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSSRLRNI_H_W : LASX_I5_U<0b01110111010100001>, ++ LASX_2R_3R_U5_DESC_BASE<"xvssrlrni.h.w", int_loongarch_lasx_xvssrlrni_h_w, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSSRLRNI_W_D : LASX_I6_U<0b0111011101010001>, ++ LASX_2R_3R_U6_DESC_BASE<"xvssrlrni.w.d", int_loongarch_lasx_xvssrlrni_w_d, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSSRLRNI_D_Q : LASX_I7_U<0b011101110101001>, ++ LASX_2R_3R_U7_DESC_BASE<"xvssrlrni.d.q", int_loongarch_lasx_xvssrlrni_d_q, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSSRLRNI_BU_H : LASX_I4_U<0b011101110101010001>, ++ LASX_U4_DESC_BASE<"xvssrlrni.bu.h", int_loongarch_lasx_xvssrlrni_bu_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRLRNI_HU_W : LASX_I5_U<0b01110111010101001>, ++ LASX_N4_U5_DESC_BASE<"xvssrlrni.hu.w", int_loongarch_lasx_xvssrlrni_hu_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRLRNI_WU_D : LASX_I6_U<0b0111011101010101>, ++ LASX_U6_DESC_BASE<"xvssrlrni.wu.d", int_loongarch_lasx_xvssrlrni_wu_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRLRNI_DU_Q : LASX_I7_U<0b011101110101011>, ++ LASX_D_DESC_BASE<"xvssrlrni.du.q", int_loongarch_lasx_xvssrlrni_du_q, LASX256DOpnd>; ++ ++ ++def XVSRANI_B_H : LASX_I4_U<0b011101110101100001>, ++ LASX_2R_3R_U4_DESC_BASE<"xvsrani.b.h", int_loongarch_lasx_xvsrani_b_h, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVSRANI_H_W : LASX_I5_U<0b01110111010110001>, ++ LASX_2R_3R_U5_DESC_BASE<"xvsrani.h.w", int_loongarch_lasx_xvsrani_h_w, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVSRANI_W_D : LASX_I6_U<0b0111011101011001>, ++ LASX_2R_3R_U6_DESC_BASE<"xvsrani.w.d", int_loongarch_lasx_xvsrani_w_d, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVSRANI_D_Q : LASX_I7_U<0b011101110101101>, ++ LASX_2R_3R_U7_DESC_BASE<"xvsrani.d.q", int_loongarch_lasx_xvsrani_d_q, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSRARNI_B_H : LASX_I4_U<0b011101110101110001>, ++ LASX_U4_DESC_BASE<"xvsrarni.b.h", int_loongarch_lasx_xvsrarni_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSRARNI_H_W : LASX_I5_U<0b01110111010111001>, ++ LASX_N4_U5_DESC_BASE<"xvsrarni.h.w", int_loongarch_lasx_xvsrarni_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSRARNI_W_D : LASX_I6_U<0b0111011101011101>, ++ LASX_U6_DESC_BASE<"xvsrarni.w.d", int_loongarch_lasx_xvsrarni_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSRARNI_D_Q : LASX_I7_U<0b011101110101111>, ++ LASX_D_DESC_BASE<"xvsrarni.d.q", int_loongarch_lasx_xvsrarni_d_q, LASX256DOpnd>; ++ ++ ++def XVSSRANI_B_H : LASX_I4_U<0b011101110110000001>, ++ LASX_U4_DESC_BASE<"xvssrani.b.h", int_loongarch_lasx_xvssrani_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRANI_H_W : LASX_I5_U<0b01110111011000001>, ++ LASX_N4_U5_DESC_BASE<"xvssrani.h.w", int_loongarch_lasx_xvssrani_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRANI_W_D : LASX_I6_U<0b0111011101100001>, ++ LASX_U6_DESC_BASE<"xvssrani.w.d", int_loongarch_lasx_xvssrani_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRANI_D_Q : LASX_I7_U<0b011101110110001>, ++ LASX_D_DESC_BASE<"xvssrani.d.q", int_loongarch_lasx_xvssrani_d_q, LASX256DOpnd>; ++ ++ ++def XVSSRANI_BU_H : LASX_I4_U<0b011101110110010001>, ++ LASX_U4_DESC_BASE<"xvssrani.bu.h", int_loongarch_lasx_xvssrani_bu_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRANI_HU_W : LASX_I5_U<0b01110111011001001>, ++ LASX_N4_U5_DESC_BASE<"xvssrani.hu.w", int_loongarch_lasx_xvssrani_hu_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRANI_WU_D : LASX_I6_U<0b0111011101100101>, ++ LASX_U6_DESC_BASE<"xvssrani.wu.d", int_loongarch_lasx_xvssrani_wu_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRANI_DU_Q : LASX_I7_U<0b011101110110011>, ++ LASX_D_DESC_BASE<"xvssrani.du.q", int_loongarch_lasx_xvssrani_du_q, LASX256DOpnd>; ++ ++ ++def XVSSRARNI_B_H : LASX_I4_U<0b011101110110100001>, ++ LASX_U4_DESC_BASE<"xvssrarni.b.h", int_loongarch_lasx_xvssrarni_b_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRARNI_H_W : LASX_I5_U<0b01110111011010001>, ++ LASX_N4_U5_DESC_BASE<"xvssrarni.h.w", int_loongarch_lasx_xvssrarni_h_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRARNI_W_D : LASX_I6_U<0b0111011101101001>, ++ LASX_U6_DESC_BASE<"xvssrarni.w.d", int_loongarch_lasx_xvssrarni_w_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRARNI_D_Q : LASX_I7_U<0b011101110110101>, ++ LASX_D_DESC_BASE<"xvssrarni.d.q", int_loongarch_lasx_xvssrarni_d_q, LASX256DOpnd>; ++ ++ ++def XVSSRARNI_BU_H : LASX_I4_U<0b011101110110110001>, ++ LASX_U4_DESC_BASE<"xvssrarni.bu.h", int_loongarch_lasx_xvssrarni_bu_h, uimm4, immZExt4, LASX256BOpnd>; ++ ++def XVSSRARNI_HU_W : LASX_I5_U<0b01110111011011001>, ++ LASX_N4_U5_DESC_BASE<"xvssrarni.hu.w", int_loongarch_lasx_xvssrarni_hu_w, uimm5, immZExt5, LASX256HOpnd>; ++ ++def XVSSRARNI_WU_D : LASX_I6_U<0b0111011101101101>, ++ LASX_U6_DESC_BASE<"xvssrarni.wu.d", int_loongarch_lasx_xvssrarni_wu_d, uimm6, immZExt6, LASX256WOpnd>; ++ ++def XVSSRARNI_DU_Q : LASX_I7_U<0b011101110110111>, ++ LASX_D_DESC_BASE<"xvssrarni.du.q", int_loongarch_lasx_xvssrarni_du_q, LASX256DOpnd>; ++ ++ ++def XVEXTRINS_B : LASX_I8_U<0b01110111100011>, ++ LASX_2R_3R_U8_DESC_BASE<"xvextrins.b", int_loongarch_lasx_xvextrins_b, LASX256BOpnd, LASX256BOpnd>; ++ ++def XVEXTRINS_H : LASX_I8_U<0b01110111100010>, ++ LASX_2R_3R_U8_DESC_BASE<"xvextrins.h", int_loongarch_lasx_xvextrins_h, LASX256HOpnd, LASX256HOpnd>; ++ ++def XVEXTRINS_W : LASX_I8_U<0b01110111100001>, ++ LASX_2R_3R_U8_DESC_BASE<"xvextrins.w", int_loongarch_lasx_xvextrins_w, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVEXTRINS_D : LASX_I8_U<0b01110111100000>, ++ LASX_2R_3R_U8_DESC_BASE<"xvextrins.d", int_loongarch_lasx_xvextrins_d, LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVSHUF4I_B : LASX_I8_U<0b01110111100100>, ++ LASX_I8_SHF_DESC_BASE<"xvshuf4i.b", int_loongarch_lasx_xvshuf4i_b, LASX256BOpnd>; ++ ++def XVSHUF4I_H : LASX_I8_U<0b01110111100101>, ++ LASX_I8_SHF_DESC_BASE<"xvshuf4i.h", int_loongarch_lasx_xvshuf4i_h, LASX256HOpnd>; ++ ++def XVSHUF4I_W : LASX_I8_U<0b01110111100110>, ++ LASX_I8_SHF_DESC_BASE<"xvshuf4i.w", int_loongarch_lasx_xvshuf4i_w, LASX256WOpnd>; ++ ++def XVSHUF4I_D : LASX_I8_U<0b01110111100111>, ++ LASX_I8_O4_SHF_DESC_BASE<"xvshuf4i.d", int_loongarch_lasx_xvshuf4i_d, LASX256DOpnd>; ++ ++ ++def XVBITSELI_B : LASX_I8_U<0b01110111110001>, ++ LASX_2R_3R_U8_DESC_BASE<"xvbitseli.b", int_loongarch_lasx_xvbitseli_b, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++def XVANDI_B : LASX_I8_U<0b01110111110100>, ++ LASX_2R_U8_DESC_BASE<"xvandi.b", int_loongarch_lasx_xvandi_b, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++def XVORI_B : LASX_I8_U<0b01110111110101>, ++ LASX_2R_U8_DESC_BASE<"xvori.b", int_loongarch_lasx_xvori_b, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++def XVXORI_B : LASX_I8_U<0b01110111110110>, ++ LASX_2R_U8_DESC_BASE<"xvxori.b", int_loongarch_lasx_xvxori_b, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++def XVNORI_B : LASX_I8_U<0b01110111110111>, ++ LASX_2R_U8_DESC_BASE<"xvnori.b", int_loongarch_lasx_xvnori_b, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++def XVLDI : LASX_1R_I13<0b01110111111000>, ++ LASX_I13_DESC_BASE<"xvldi", int_loongarch_lasx_xvldi, i32, simm13Op, LASX256DOpnd>; ++ ++ ++def XVLDI_B : LASX_1R_I13_I10<0b01110111111000000>, ++ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_b, simm10, immZExt10, LASX256BOpnd>; ++ ++def XVLDI_H : LASX_1R_I13_I10<0b01110111111000001>, ++ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_h, simm10, immZExt10, LASX256HOpnd>; ++ ++def XVLDI_W : LASX_1R_I13_I10<0b01110111111000010>, ++ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_w, simm10, immZExt10, LASX256WOpnd>; ++ ++def XVLDI_D : LASX_1R_I13_I10<0b01110111111000011>, ++ LASX_I13_DESC_BASE_10<"xvldi", int_loongarch_lasx_xvrepli_d, simm10, immZExt10, LASX256DOpnd>; ++ ++ ++def XVPERMI_W : LASX_I8_U<0b01110111111001>, ++ LASX_2R_3R_U8_DESC_BASE<"xvpermi.w", int_loongarch_lasx_xvpermi_w, LASX256WOpnd, LASX256WOpnd>; ++ ++def XVPERMI_D : LASX_I8_U<0b01110111111010>, ++ LASX_2R_U8_DESC_BASE<"xvpermi.d", int_loongarch_lasx_xvpermi_d, LASX256DOpnd, LASX256DOpnd>; ++ ++def XVPERMI_Q : LASX_I8_U<0b01110111111011>, ++ LASX_2R_3R_U8_DESC_BASE<"xvpermi.q", int_loongarch_lasx_xvpermi_q, LASX256BOpnd, LASX256BOpnd>; ++ ++ ++//Pat ++ ++class LASXBitconvertPat preds = [HasLASX]> : ++ LASXPat<(DstVT (bitconvert SrcVT:$src)), ++ (COPY_TO_REGCLASS SrcVT:$src, DstRC), preds>; ++ ++// These are endian-independent because the element size doesnt change ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++def : LASXBitconvertPat; ++ ++class LASX_XINSERT_PSEUDO_BASE : ++ LASXPseudo<(outs ROXD:$xd), (ins ROXD:$xd_in, ImmOp:$n, ROFS:$fs), ++ [(set ROXD:$xd, (OpNode (Ty ROXD:$xd_in), ROFS:$fs, Imm:$n))]> { ++ bit usesCustomInserter = 1; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++class XINSERT_H_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; ++ ++class XINSERT_H64_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; ++ ++def XINSERT_H_PSEUDO : XINSERT_H_PSEUDO_DESC; ++def XINSERT_H64_PSEUDO : XINSERT_H64_PSEUDO_DESC; ++ ++class XINSERT_B_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; ++def XINSERT_B_PSEUDO : XINSERT_B_PSEUDO_DESC; ++ ++ ++class LASX_COPY_PSEUDO_BASE : ++ LASXPseudo<(outs RCD:$xd), (ins RCWS:$xj, ImmOp:$n), ++ [(set RCD:$xd, (OpNode (VecTy RCWS:$xj), Imm:$n))]> { ++ bit usesCustomInserter = 1; ++} ++ ++class XCOPY_FW_PSEUDO_DESC : LASX_COPY_PSEUDO_BASE; ++class XCOPY_FD_PSEUDO_DESC : LASX_COPY_PSEUDO_BASE; ++def XCOPY_FW_PSEUDO : XCOPY_FW_PSEUDO_DESC; ++def XCOPY_FD_PSEUDO : XCOPY_FD_PSEUDO_DESC; ++ ++ ++ ++class LASX_XINSERT_VIDX_PSEUDO_BASE : ++ LASXPseudo<(outs ROXD:$xd), (ins ROXD:$xd_in, ROIdx:$n, ROFS:$fs), ++ [(set ROXD:$xd, (OpNode (Ty ROXD:$xd_in), ROFS:$fs, ROIdx:$n))]> { ++ bit usesCustomInserter = 1; ++ string Constraints = "$xd = $xd_in"; ++} ++ ++ ++class XINSERT_FW_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; ++def XINSERT_FW_PSEUDO : XINSERT_FW_PSEUDO_DESC; ++ ++class XINSERT_FW_VIDX_PSEUDO_DESC : ++ LASX_XINSERT_VIDX_PSEUDO_BASE; ++class XINSERT_FW_VIDX64_PSEUDO_DESC : ++ LASX_XINSERT_VIDX_PSEUDO_BASE; ++ ++def XINSERT_FW_VIDX_PSEUDO : XINSERT_FW_VIDX_PSEUDO_DESC; ++def XINSERT_FW_VIDX64_PSEUDO : XINSERT_FW_VIDX64_PSEUDO_DESC; ++ ++class XINSERT_B_VIDX64_PSEUDO_DESC : ++ LASX_XINSERT_VIDX_PSEUDO_BASE; ++ ++def XINSERT_B_VIDX64_PSEUDO : XINSERT_B_VIDX64_PSEUDO_DESC; ++ ++ ++class XINSERT_B_VIDX_PSEUDO_DESC : ++ LASX_XINSERT_VIDX_PSEUDO_BASE; ++ ++def XINSERT_B_VIDX_PSEUDO : XINSERT_B_VIDX_PSEUDO_DESC; ++ ++ ++class XINSERTPostRA : ++ LoongArchPseudo<(outs RC:$xd), (ins RC:$xd_in, RD:$n, RE:$fs), []> { ++ let mayLoad = 1; ++ let mayStore = 1; ++} ++ ++def XINSERT_B_VIDX_PSEUDO_POSTRA : XINSERTPostRA; ++def XINSERT_B_VIDX64_PSEUDO_POSTRA : XINSERTPostRA; ++def XINSERT_FW_VIDX_PSEUDO_POSTRA : XINSERTPostRA; ++def XINSERT_FW_VIDX64_PSEUDO_POSTRA : XINSERTPostRA; ++ ++class XINSERT_FD_PSEUDO_DESC : LASX_XINSERT_PSEUDO_BASE; ++ ++def XINSERT_FD_PSEUDO : XINSERT_FD_PSEUDO_DESC; ++ ++class LASX_2R_FILL_PSEUDO_BASE : ++ LASXPseudo<(outs RCWD:$xd), (ins RCWS:$fs), ++ [(set RCWD:$xd, (OpNode RCWS:$fs))]> { ++ let usesCustomInserter = 1; ++} ++ ++class XFILL_FW_PSEUDO_DESC : LASX_2R_FILL_PSEUDO_BASE; ++class XFILL_FD_PSEUDO_DESC : LASX_2R_FILL_PSEUDO_BASE; ++def XFILL_FW_PSEUDO : XFILL_FW_PSEUDO_DESC; ++def XFILL_FD_PSEUDO : XFILL_FD_PSEUDO_DESC; ++ ++class LASX_CONCAT_VECTORS_PSEUDO_BASE : ++ LASXPseudo<(outs ROXD:$xd), (ins ROXJ:$xs, ROXK:$xt), ++ [(set ROXD:$xd, (Ty (concat_vectors (SubTy ROXJ:$xs), (SubTy ROXK:$xt))))]> { ++ bit usesCustomInserter = 1; ++} ++ ++class CONCAT_VECTORS_B_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++class CONCAT_VECTORS_H_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++class CONCAT_VECTORS_W_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++class CONCAT_VECTORS_D_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++ ++class CONCAT_VECTORS_FW_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++class CONCAT_VECTORS_FD_PSEUDO_DESC : ++ LASX_CONCAT_VECTORS_PSEUDO_BASE; ++ ++def CONCAT_VECTORS_B_PSEUDO : CONCAT_VECTORS_B_PSEUDO_DESC; ++def CONCAT_VECTORS_H_PSEUDO : CONCAT_VECTORS_H_PSEUDO_DESC; ++def CONCAT_VECTORS_W_PSEUDO : CONCAT_VECTORS_W_PSEUDO_DESC; ++def CONCAT_VECTORS_D_PSEUDO : CONCAT_VECTORS_D_PSEUDO_DESC; ++def CONCAT_VECTORS_FW_PSEUDO : CONCAT_VECTORS_FW_PSEUDO_DESC; ++def CONCAT_VECTORS_FD_PSEUDO : CONCAT_VECTORS_FD_PSEUDO_DESC; ++ ++ ++class LASX_COPY_GPR_PSEUDO_BASE : ++ LASXPseudo<(outs ROXD:$xd), (ins ROFS:$xj, ROIdx:$n), ++ [(set ROXD:$xd, (OpNode (VecTy ROFS:$xj), ROIdx:$n))]> { ++ bit usesCustomInserter = 1; ++} ++ ++class XCOPY_FW_GPR_PSEUDO_DESC : LASX_COPY_GPR_PSEUDO_BASE; ++def XCOPY_FW_GPR_PSEUDO : XCOPY_FW_GPR_PSEUDO_DESC; ++ ++ ++let isCodeGenOnly = 1 in { ++ ++def XVLD_H : LASX_I12_S<0b0010110010>, ++ LASX_LD<"xvld", load, v16i16, LASX256HOpnd, mem>; ++ ++def XVLD_W : LASX_I12_S<0b0010110010>, ++ LASX_LD<"xvld", load, v8i32, LASX256WOpnd, mem>; ++ ++def XVLD_D : LASX_I12_S<0b0010110010>, ++ LASX_LD<"xvld", load, v4i64, LASX256DOpnd, mem>; ++ ++ ++def XVST_H : LASX_I12_S<0b0010110011>, ++ LASX_ST<"xvst", store, v16i16, LASX256HOpnd, mem_simm12>; ++ ++def XVST_W : LASX_I12_S<0b0010110011>, ++ LASX_ST<"xvst", store, v8i32, LASX256WOpnd, mem_simm12>; ++ ++def XVST_D : LASX_I12_S<0b0010110011>, ++ LASX_ST<"xvst", store, v4i64, LASX256DOpnd, mem_simm12>; ++ ++ ++def XVREPLVE_W_N : LASX_3R_1GP<0b01110101001000110>, ++ LASX_3R_VREPLVE_DESC_BASE_N<"xvreplve.w", LASX256WOpnd>; ++ ++ ++def XVANDI_B_N : LASX_I8_U<0b01110111110100>, ++ LASX_BIT_U8_DESC_BASE<"xvandi.b", and, xvsplati8_uimm8, LASX256BOpnd>; ++ ++ ++def XVXORI_B_N : LASX_I8_U<0b01110111110110>, ++ LASX_BIT_U8_DESC_BASE<"xvxori.b", xor, xvsplati8_uimm8, LASX256BOpnd>; ++ ++ ++def XVSRAI_B_N : LASX_I3_U<0b0111011100110100001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvsrai.b", sra, xvsplati8_uimm3, LASX256BOpnd>; ++ ++def XVSRAI_H_N : LASX_I4_U<0b011101110011010001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvsrai.h", sra, xvsplati16_uimm4, LASX256HOpnd>; ++ ++def XVSRAI_W_N : LASX_I5_U<0b01110111001101001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvsrai.w", sra, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSRAI_D_N : LASX_I6_U<0b0111011100110101>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvsrai.d", sra, xvsplati64_uimm6, LASX256DOpnd>; ++ ++ ++def XVSLLI_B_N : LASX_I3_U<0b0111011100101100001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvslli.b", shl, xvsplati8_uimm3, LASX256BOpnd>; ++ ++def XVSLLI_H_N : LASX_I4_U<0b011101110010110001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvslli.h", shl, xvsplati16_uimm4, LASX256HOpnd>; ++ ++def XVSLLI_W_N : LASX_I5_U<0b01110111001011001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvslli.w", shl, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSLLI_D_N : LASX_I6_U<0b0111011100101101>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvslli.d", shl, xvsplati64_uimm6, LASX256DOpnd>; ++ ++ ++def XVSRLI_B_N : LASX_I3_U<0b0111011100110000001>, ++ LASX_BIT_U3_VREPLVE_DESC_BASE<"xvsrli.b", srl, xvsplati8_uimm3, LASX256BOpnd>; ++ ++def XVSRLI_H_N : LASX_I4_U<0b011101110011000001>, ++ LASX_BIT_U4_VREPLVE_DESC_BASE<"xvsrli.h", srl, xvsplati16_uimm4, LASX256HOpnd>; ++ ++def XVSRLI_W_N : LASX_I5_U<0b01110111001100001>, ++ LASX_BIT_U5_VREPLVE_DESC_BASE<"xvsrli.w", srl, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSRLI_D_N : LASX_I6_U<0b0111011100110001>, ++ LASX_BIT_U6_VREPLVE_DESC_BASE<"xvsrli.d", srl, xvsplati64_uimm6, LASX256DOpnd>; ++ ++ ++def XVMAXI_B_N : LASX_I5<0b01110110100100000>, ++ LASX_I5_DESC_BASE<"xvmaxi.b", smax, xvsplati8_simm5, LASX256BOpnd>; ++ ++def XVMAXI_H_N : LASX_I5<0b01110110100100001>, ++ LASX_I5_DESC_BASE<"xvmaxi.h", smax, xvsplati16_simm5, LASX256HOpnd>; ++ ++def XVMAXI_W_N : LASX_I5<0b01110110100100010>, ++ LASX_I5_DESC_BASE<"xvmaxi.w", smax, xvsplati32_simm5, LASX256WOpnd>; ++ ++def XVMAXI_D_N : LASX_I5<0b01110110100100011>, ++ LASX_I5_DESC_BASE<"xvmaxi.d", smax, xvsplati64_simm5, LASX256DOpnd>; ++ ++ ++def XVMINI_B_N : LASX_I5<0b01110110100100100>, ++ LASX_I5_DESC_BASE<"xvmini.b", smin, xvsplati8_simm5, LASX256BOpnd>; ++ ++def XVMINI_H_N : LASX_I5<0b01110110100100101>, ++ LASX_I5_DESC_BASE<"xvmini.h", smin, xvsplati16_simm5, LASX256HOpnd>; ++ ++def XVMINI_W_N : LASX_I5<0b01110110100100110>, ++ LASX_I5_DESC_BASE<"xvmini.w", smin, xvsplati32_simm5, LASX256WOpnd>; ++ ++def XVMINI_D_N : LASX_I5<0b01110110100100111>, ++ LASX_I5_DESC_BASE<"xvmini.d", smin, xvsplati64_simm5, LASX256DOpnd>; ++ ++ ++def XVMAXI_BU_N : LASX_I5_U<0b01110110100101000>, ++ LASX_I5_U_DESC_BASE<"xvmaxi.bu", umax, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVMAXI_HU_N : LASX_I5_U<0b01110110100101001>, ++ LASX_I5_U_DESC_BASE<"xvmaxi.hu", umax, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVMAXI_WU_N : LASX_I5_U<0b01110110100101010>, ++ LASX_I5_U_DESC_BASE<"xvmaxi.wu", umax, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVMAXI_DU_N : LASX_I5_U<0b01110110100101011>, ++ LASX_I5_U_DESC_BASE<"xvmaxi.du", umax, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVMINI_BU_N : LASX_I5_U<0b01110110100101100>, ++ LASX_I5_U_DESC_BASE<"xvmini.bu", umin, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVMINI_HU_N : LASX_I5_U<0b01110110100101101>, ++ LASX_I5_U_DESC_BASE<"xvmini.hu", umin, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVMINI_WU_N : LASX_I5_U<0b01110110100101110>, ++ LASX_I5_U_DESC_BASE<"xvmini.wu", umin, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVMINI_DU_N : LASX_I5_U<0b01110110100101111>, ++ LASX_I5_U_DESC_BASE<"xvmini.du", umin, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVSEQI_B_N : LASX_I5<0b01110110100000000>, ++ LASX_I5_SETCC_DESC_BASE<"xvseqi.b", SETEQ, v32i8, xvsplati8_simm5, LASX256BOpnd>; ++ ++def XVSEQI_H_N : LASX_I5<0b01110110100000001>, ++ LASX_I5_SETCC_DESC_BASE<"xvseqi.h", SETEQ, v16i16, xvsplati16_simm5, LASX256HOpnd>; ++ ++def XVSEQI_W_N : LASX_I5<0b01110110100000010>, ++ LASX_I5_SETCC_DESC_BASE<"xvseqi.w", SETEQ, v8i32, xvsplati32_simm5, LASX256WOpnd>; ++ ++def XVSEQI_D_N : LASX_I5<0b01110110100000011>, ++ LASX_I5_SETCC_DESC_BASE<"xvseqi.d", SETEQ, v4i64, xvsplati64_simm5, LASX256DOpnd>; ++ ++ ++def XVSLEI_B_N : LASX_I5<0b01110110100000100>, ++ LASX_I5_SETCC_DESC_BASE<"xvslei.b", SETLE, v32i8, xvsplati8_simm5, LASX256BOpnd>; ++ ++def XVSLEI_H_N : LASX_I5<0b01110110100000101>, ++ LASX_I5_SETCC_DESC_BASE<"xvslei.h", SETLE, v16i16, xvsplati16_simm5, LASX256HOpnd>; ++ ++def XVSLEI_W_N : LASX_I5<0b01110110100000110>, ++ LASX_I5_SETCC_DESC_BASE<"xvslei.w", SETLE, v8i32, xvsplati32_simm5, LASX256WOpnd>; ++ ++def XVSLEI_D_N : LASX_I5<0b01110110100000111>, ++ LASX_I5_SETCC_DESC_BASE<"xvslei.d", SETLE, v4i64, xvsplati64_simm5, LASX256DOpnd>; ++ ++ ++def XVSLEI_BU_N : LASX_I5_U<0b01110110100001000>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslei.bu", SETULE, v32i8, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVSLEI_HU_N : LASX_I5_U<0b01110110100001001>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslei.hu", SETULE, v16i16, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVSLEI_WU_N : LASX_I5_U<0b01110110100001010>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslei.wu", SETULE, v8i32, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSLEI_DU_N : LASX_I5_U<0b01110110100001011>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslei.du", SETULE, v4i64, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVSLTI_B_N : LASX_I5<0b01110110100001100>, ++ LASX_I5_SETCC_DESC_BASE<"xvslti.b", SETLT, v32i8, xvsplati8_simm5, LASX256BOpnd>; ++ ++def XVSLTI_H_N : LASX_I5<0b01110110100001101>, ++ LASX_I5_SETCC_DESC_BASE<"xvslti.h", SETLT, v16i16, xvsplati16_simm5, LASX256HOpnd>; ++ ++def XVSLTI_W_N : LASX_I5<0b01110110100001110>, ++ LASX_I5_SETCC_DESC_BASE<"xvslti.w", SETLT, v8i32, xvsplati32_simm5, LASX256WOpnd>; ++ ++def XVSLTI_D_N : LASX_I5<0b01110110100001111>, ++ LASX_I5_SETCC_DESC_BASE<"xvslti.d", SETLT, v4i64, xvsplati64_simm5, LASX256DOpnd>; ++ ++ ++def XVSLTI_BU_N : LASX_I5_U<0b01110110100010000>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslti.bu", SETULT, v32i8, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVSLTI_HU_N : LASX_I5_U<0b01110110100010001>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslti.hu", SETULT, v16i16, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVSLTI_WU_N : LASX_I5_U<0b01110110100010010>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslti.wu", SETULT, v8i32, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSLTI_DU_N : LASX_I5_U<0b01110110100010011>, ++ LASX_I5_U_SETCC_DESC_BASE<"xvslti.du", SETULT, v4i64, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVADDI_BU_N : LASX_I5_U<0b01110110100010100>, ++ LASX_I5_U_DESC_BASE<"xvaddi.bu", add, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVADDI_HU_N : LASX_I5_U<0b01110110100010101>, ++ LASX_I5_U_DESC_BASE<"xvaddi.hu", add, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVADDI_WU_N : LASX_I5_U<0b01110110100010110>, ++ LASX_I5_U_DESC_BASE<"xvaddi.wu", add, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVADDI_DU_N : LASX_I5_U<0b01110110100010111>, ++ LASX_I5_U_DESC_BASE<"xvaddi.du", add, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVSUBI_BU_N : LASX_I5_U<0b01110110100011000>, ++ LASX_I5_U_DESC_BASE<"xvsubi.bu", sub, xvsplati8_uimm5, LASX256BOpnd>; ++ ++def XVSUBI_HU_N : LASX_I5_U<0b01110110100011001>, ++ LASX_I5_U_DESC_BASE<"xvsubi.hu", sub, xvsplati16_uimm5, LASX256HOpnd>; ++ ++def XVSUBI_WU_N : LASX_I5_U<0b01110110100011010>, ++ LASX_I5_U_DESC_BASE<"xvsubi.wu", sub, xvsplati32_uimm5, LASX256WOpnd>; ++ ++def XVSUBI_DU_N : LASX_I5_U<0b01110110100011011>, ++ LASX_I5_U_DESC_BASE<"xvsubi.du", sub, xvsplati64_uimm5, LASX256DOpnd>; ++ ++ ++def XVPERMI_QH : LASX_I8_U<0b01110111111011>, ++ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256HOpnd, LASX256HOpnd>; ++ ++def XVPERMI_QW : LASX_I8_U<0b01110111111011>, ++ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256WOpnd, LASX256WOpnd>; ++ ++def XVPERMI_QD : LASX_I8_U<0b01110111111011>, ++ LASX_2RN_3R_U8_DESC_BASE<"xvpermi.q", LASX256DOpnd, LASX256DOpnd>; ++ ++ ++def XVBITSELI_B_N : LASX_I8_U<0b01110111110001>, ++ LASX_2R_3R_U8_SELECT<"xvbitseli.b", vselect, LASX256BOpnd, LASX256BOpnd>; ++ ++} ++ ++ ++def : LASXPat<(v8f32 (load addrimm12:$addr)), (XVLD_W addrimm12:$addr)>; ++def : LASXPat<(v4f64 (load addrimm12:$addr)), (XVLD_D addrimm12:$addr)>; ++ ++def XVST_FW : LASXPat<(store (v8f32 LASX256W:$xj), addrimm12:$addr), ++ (XVST_W LASX256W:$xj, addrimm12:$addr)>; ++def XVST_FD : LASXPat<(store (v4f64 LASX256D:$xj), addrimm12:$addr), ++ (XVST_D LASX256D:$xj, addrimm12:$addr)>; ++ ++def XVNEG_FW : LASXPat<(fneg (v8f32 LASX256W:$xj)), ++ (XVBITREVI_W LASX256W:$xj, 31)>; ++def XVNEG_FD : LASXPat<(fneg (v4f64 LASX256D:$xj)), ++ (XVBITREVI_D LASX256D:$xj, 63)>; ++ ++ ++def : LASXPat<(v4i64 (LoongArchVABSD v4i64:$xj, v4i64:$xk, (i32 0))), ++ (v4i64 (XVABSD_D $xj, $xk))>; ++ ++def : LASXPat<(v8i32 (LoongArchVABSD v8i32:$xj, v8i32:$xk, (i32 0))), ++ (v8i32 (XVABSD_W $xj, $xk))>; ++ ++def : LASXPat<(v16i16 (LoongArchVABSD v16i16:$xj, v16i16:$xk, (i32 0))), ++ (v16i16 (XVABSD_H $xj, $xk))>; ++ ++def : LASXPat<(v32i8 (LoongArchVABSD v32i8:$xj, v32i8:$xk, (i32 0))), ++ (v32i8 (XVABSD_B $xj, $xk))>; ++ ++def : LASXPat<(v4i64 (LoongArchUVABSD v4i64:$xj, v4i64:$xk, (i32 0))), ++ (v4i64 (XVABSD_DU $xj, $xk))>; ++ ++def : LASXPat<(v8i32 (LoongArchUVABSD v8i32:$xj, v8i32:$xk, (i32 0))), ++ (v8i32 (XVABSD_WU $xj, $xk))>; ++ ++def : LASXPat<(v16i16 (LoongArchUVABSD v16i16:$xj, v16i16:$xk, (i32 0))), ++ (v16i16 (XVABSD_HU $xj, $xk))>; ++ ++def : LASXPat<(v32i8 (LoongArchUVABSD v32i8:$xj, v32i8:$xk, (i32 0))), ++ (v32i8 (XVABSD_BU $xj, $xk))>; ++ ++ ++def : LASXPat<(or v32i8:$vj, (shl vsplat_imm_eq_1, v32i8:$vk)), ++ (XVBITSET_B v32i8:$vj, v32i8:$vk)>; ++def : LASXPat<(or v16i16:$vj, (shl vsplat_imm_eq_1, v16i16:$vk)), ++ (XVBITSET_H v16i16:$vj, v16i16:$vk)>; ++def : LASXPat<(or v8i32:$vj, (shl vsplat_imm_eq_1, v8i32:$vk)), ++ (XVBITSET_W v8i32:$vj, v8i32:$vk)>; ++def : LASXPat<(or v4i64:$vj, (shl vsplat_imm_eq_1, v4i64:$vk)), ++ (XVBITSET_D v4i64:$vj, v4i64:$vk)>; ++ ++def : LASXPat<(xor v32i8:$vj, (shl xvsplat_imm_eq_1, v32i8:$vk)), ++ (XVBITREV_B v32i8:$vj, v32i8:$vk)>; ++def : LASXPat<(xor v16i16:$vj, (shl xvsplat_imm_eq_1, v16i16:$vk)), ++ (XVBITREV_H v16i16:$vj, v16i16:$vk)>; ++def : LASXPat<(xor v8i32:$vj, (shl xvsplat_imm_eq_1, v8i32:$vk)), ++ (XVBITREV_W v8i32:$vj, v8i32:$vk)>; ++def : LASXPat<(xor v4i64:$vj, (shl (v4i64 xvsplati64_imm_eq_1), v4i64:$vk)), ++ (XVBITREV_D v4i64:$vj, v4i64:$vk)>; ++ ++def : LASXPat<(and v32i8:$vj, (xor (shl vsplat_imm_eq_1, v32i8:$vk), immAllOnesV)), ++ (XVBITCLR_B v32i8:$vj, v32i8:$vk)>; ++def : LASXPat<(and v16i16:$vj, (xor (shl vsplat_imm_eq_1, v16i16:$vk), immAllOnesV)), ++ (XVBITCLR_H v16i16:$vj, v16i16:$vk)>; ++def : LASXPat<(and v8i32:$vj, (xor (shl vsplat_imm_eq_1, v8i32:$vk), immAllOnesV)), ++ (XVBITCLR_W v8i32:$vj, v8i32:$vk)>; ++def : LASXPat<(and v4i64:$vj, (xor (shl (v4i64 vsplati64_imm_eq_1), v4i64:$vk), (bitconvert (v8i32 immAllOnesV)))), ++ (XVBITCLR_D v4i64:$vj, v4i64:$vk)>; ++ ++def xvsplati64_imm_eq_63 : PatLeaf<(bitconvert (v8i32 (build_vector))), [{ ++ APInt Imm; ++ SDNode *BV = N->getOperand(0).getNode(); ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63; ++}]>; ++ ++def xvsplati8imm7 : PatFrag<(ops node:$wt), ++ (and node:$wt, (xvsplati8 immi32Cst7))>; ++def xvsplati16imm15 : PatFrag<(ops node:$wt), ++ (and node:$wt, (xvsplati16 immi32Cst15))>; ++def xvsplati32imm31 : PatFrag<(ops node:$wt), ++ (and node:$wt, (xvsplati32 immi32Cst31))>; ++def xvsplati64imm63 : PatFrag<(ops node:$wt), ++ (and node:$wt, xvsplati64_imm_eq_63)>; ++ ++ ++class LASXShiftPat : ++ LASXPat<(VT (Node VT:$vs, (VT (and VT:$vt, Vec)))), ++ (VT (Insn VT:$vs, VT:$vt))>; ++ ++class LASXBitPat : ++ LASXPat<(VT (Node VT:$vs, (shl vsplat_imm_eq_1, (Frag VT:$vt)))), ++ (VT (Insn VT:$vs, VT:$vt))>; ++ ++multiclass LASXShiftPats { ++ def : LASXShiftPat(Insn#_B), ++ (xvsplati8 immi32Cst7)>; ++ def : LASXShiftPat(Insn#_H), ++ (xvsplati16 immi32Cst15)>; ++ def : LASXShiftPat(Insn#_W), ++ (xvsplati32 immi32Cst31)>; ++ def : LASXPat<(v4i64 (Node v4i64:$vs, (v4i64 (and v4i64:$vt, ++ xvsplati64_imm_eq_63)))), ++ (v4i64 (!cast(Insn#_D) v4i64:$vs, v4i64:$vt))>; ++} ++ ++multiclass LASXBitPats { ++ def : LASXBitPat(Insn#_B), xvsplati8imm7>; ++ def : LASXBitPat(Insn#_H), xvsplati16imm15>; ++ def : LASXBitPat(Insn#_W), xvsplati32imm31>; ++ def : LASXPat<(Node v4i64:$vs, (shl (v4i64 xvsplati64_imm_eq_1), ++ (xvsplati64imm63 v4i64:$vt))), ++ (v4i64 (!cast(Insn#_D) v4i64:$vs, v4i64:$vt))>; ++} ++ ++defm : LASXShiftPats; ++defm : LASXShiftPats; ++defm : LASXShiftPats; ++defm : LASXBitPats; ++defm : LASXBitPats; ++ ++def : LASXPat<(and v32i8:$vs, (xor (shl xvsplat_imm_eq_1, ++ (xvsplati8imm7 v32i8:$vt)), ++ immAllOnesV)), ++ (v32i8 (XVBITCLR_B v32i8:$vs, v32i8:$vt))>; ++def : LASXPat<(and v16i16:$vs, (xor (shl xvsplat_imm_eq_1, ++ (xvsplati16imm15 v16i16:$vt)), ++ immAllOnesV)), ++ (v16i16 (XVBITCLR_H v16i16:$vs, v16i16:$vt))>; ++def : LASXPat<(and v8i32:$vs, (xor (shl xvsplat_imm_eq_1, ++ (xvsplati32imm31 v8i32:$vt)), ++ immAllOnesV)), ++ (v8i32 (XVBITCLR_W v8i32:$vs, v8i32:$vt))>; ++def : LASXPat<(and v4i64:$vs, (xor (shl (v4i64 xvsplati64_imm_eq_1), ++ (xvsplati64imm63 v4i64:$vt)), ++ (bitconvert (v8i32 immAllOnesV)))), ++ (v4i64 (XVBITCLR_D v4i64:$vs, v4i64:$vt))>; ++ ++ ++def : LASXPat<(fdiv (v8f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), ++ (f32 fpimm1),(f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), v8f32:$v), ++ (XVFRECIP_S v8f32:$v)>; ++ ++def : LASXPat<(fdiv (v4f64 (build_vector (f64 fpimm1), (f64 fpimm1), (f64 fpimm1), (f64 fpimm1))), v4f64:$v), ++ (XVFRECIP_D v4f64:$v)>; ++ ++def : LASXPat<(fdiv (v8f32 fpimm1), v8f32:$v), ++ (XVFRECIP_S v8f32:$v)>; ++ ++def : LASXPat<(fdiv (v4f64 fpimm1), v4f64:$v), ++ (XVFRECIP_D v4f64:$v)>; ++ ++ ++def : LASXPat<(fdiv (v8f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), ++ (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), (fsqrt v8f32:$v)), ++ (XVFRSQRT_S v8f32:$v)>; ++ ++def : LASXPat<(fdiv (v4f64 (build_vector (f64 fpimm1), (f64 fpimm1), (f64 fpimm1), (f64 fpimm1))), (fsqrt v4f64:$v)), ++ (XVFRSQRT_D v4f64:$v)>; ++ ++def : LASXPat<(fdiv (v8f32 fpimm1), (fsqrt v8f32:$v)), ++ (XVFRSQRT_S v8f32:$v)>; ++ ++def : LASXPat<(fdiv (v4f64 fpimm1), (fsqrt v4f64:$v)), ++ (XVFRSQRT_D v4f64:$v)>; ++ ++ ++def : LASXPat <(extract_subvector v4f64:$vec, (i32 0)), ++ (v2f64 (EXTRACT_SUBREG v4f64:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v8f32:$vec, (i32 0)), ++ (v4f32 (EXTRACT_SUBREG v8f32:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v4i64:$vec, (i32 0)), ++ (v2i64 (EXTRACT_SUBREG v4i64:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v8i32:$vec, (i32 0)), ++ (v4i32 (EXTRACT_SUBREG v8i32:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v16i16:$vec, (i32 0)), ++ (v8i16 (EXTRACT_SUBREG v16i16:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v32i8:$vec, (i32 0)), ++ (v16i8 (EXTRACT_SUBREG v32i8:$vec, sub_128))>; ++ ++ ++ ++def : LASXPat <(extract_subvector v4f64:$vec, (i64 0)), ++ (v2f64 (EXTRACT_SUBREG v4f64:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v8f32:$vec, (i64 0)), ++ (v4f32 (EXTRACT_SUBREG v8f32:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v4i64:$vec, (i64 0)), ++ (v2i64 (EXTRACT_SUBREG v4i64:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v8i32:$vec, (i64 0)), ++ (v4i32 (EXTRACT_SUBREG v8i32:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v16i16:$vec, (i64 0)), ++ (v8i16 (EXTRACT_SUBREG v16i16:$vec, sub_128))>; ++ ++def : LASXPat <(extract_subvector v32i8:$vec, (i64 0)), ++ (v16i8 (EXTRACT_SUBREG v32i8:$vec, sub_128))>; ++ ++ ++def : LASXPat <(extract_subvector v4i64:$vec, (i32 2)), ++ (v2i64 (EXTRACT_SUBREG (v4i64 (XVPERMI_QD v4i64:$vec, v4i64:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v8i32:$vec, (i32 4)), ++ (v4i32 (EXTRACT_SUBREG (v8i32 (XVPERMI_QW v8i32:$vec, v8i32:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v16i16:$vec, (i32 8)), ++ (v8i16 (EXTRACT_SUBREG (v16i16 (XVPERMI_QH v16i16:$vec, v16i16:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v32i8:$vec, (i32 16)), ++ (v16i8 (EXTRACT_SUBREG (v32i8 (XVPERMI_Q v32i8:$vec, v32i8:$vec, (i32 1))), sub_128))>; ++ ++ ++def : LASXPat <(extract_subvector v4i64:$vec, (i64 2)), ++ (v2i64 (EXTRACT_SUBREG (v4i64 (XVPERMI_QD v4i64:$vec, v4i64:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v8i32:$vec, (i64 4)), ++ (v4i32 (EXTRACT_SUBREG (v8i32 (XVPERMI_QW v8i32:$vec, v8i32:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v16i16:$vec, (i64 8)), ++ (v8i16 (EXTRACT_SUBREG (v16i16 (XVPERMI_QH v16i16:$vec, v16i16:$vec, (i32 1))), sub_128))>; ++ ++def : LASXPat <(extract_subvector v32i8:$vec, (i64 16)), ++ (v16i8 (EXTRACT_SUBREG (v32i8 (XVPERMI_Q v32i8:$vec, v32i8:$vec, (i32 1))), sub_128))>; ++ ++ ++def : LASXPat<(abs v4i64:$v), ++ (XVMAX_D v4i64:$v, (XVNEG_D v4i64:$v))>; ++ ++def : LASXPat<(abs v8i32:$v), ++ (XVMAX_W v8i32:$v, (XVNEG_W v8i32:$v))>; ++ ++def : LASXPat<(abs v16i16:$v), ++ (XVMAX_H v16i16:$v, (XVNEG_H v16i16:$v))>; ++ ++def : LASXPat<(abs v32i8:$v), ++ (XVMAX_B v32i8:$v, (XVNEG_B v32i8:$v))>; ++ ++ ++def : LASXPat<(sub (v32i8 immAllZerosV), v32i8:$v), ++ (XVNEG_B v32i8:$v)>; ++ ++def : LASXPat<(sub (v16i16 immAllZerosV), v16i16:$v), ++ (XVNEG_H v16i16:$v)>; ++ ++def : LASXPat<(sub (v8i32 immAllZerosV), v8i32:$v), ++ (XVNEG_W v8i32:$v)>; ++ ++def : LASXPat<(sub (v4i64 immAllZerosV), v4i64:$v), ++ (XVNEG_D v4i64:$v)>; ++ ++ ++ ++def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i32 0)), ++ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i32 0)), ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i32 0)), ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i32 0)), ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; ++ ++ ++def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i64 0)), ++ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i64 0)), ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i64 0)), ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i64 0)), ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; ++ ++ ++def : LASXPat<(insert_subvector ++ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i32 0)), ++ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i32 0)), ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i32 0)), ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i32 0)), ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i64 0)), ++ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), LSX128D:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i64 0)), ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i64 0)), ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$src, sub_128)>; ++ ++def : LASXPat<(insert_subvector ++ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i64 0)), ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$src, sub_128)>; ++ ++ ++def : LASXPat<(insert_subvector ++ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i32 2)), ++ (XVPERMI_QD (v4i64 (XVREPLGR2VR_D ZERO_64)), ++ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), ++ LSX128D:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector (v8i32 immAllZerosV), ++ (v4i32 LSX128W:$src), (i32 4)), ++ (XVPERMI_QW (v8i32 (XVREPLGR2VR_W ZERO)), ++ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), ++ LSX128W:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector ++ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i32 8)), ++ (XVPERMI_QH (v16i16 (XVREPLGR2VR_H ZERO)), ++ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), ++ LSX128H:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector ++ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i32 16)), ++ (XVPERMI_Q (v32i8 (XVREPLGR2VR_B ZERO)), ++ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), ++ LSX128B:$src, sub_128)), (i32 32))>; ++ ++ ++def : LASXPat<(insert_subvector ++ (v4i64 immAllZerosV), (v2i64 LSX128D:$src), (i64 2)), ++ (XVPERMI_QD (v4i64 (XVREPLGR2VR_D ZERO_64)), ++ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), ++ LSX128D:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector ++ (v8i32 immAllZerosV), (v4i32 LSX128W:$src), (i64 4)), ++ (XVPERMI_QW (v8i32 (XVREPLGR2VR_W ZERO)), ++ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), ++ LSX128W:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector ++ (v16i16 immAllZerosV), (v8i16 LSX128H:$src), (i64 8)), ++ (XVPERMI_QH (v16i16 (XVREPLGR2VR_H ZERO)), ++ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), ++ LSX128H:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector ++ (v32i8 immAllZerosV), (v16i8 LSX128B:$src), (i64 16)), ++ (XVPERMI_Q (v32i8 (XVREPLGR2VR_B ZERO)), ++ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), ++ LSX128B:$src, sub_128)), (i32 32))>; ++ ++ ++def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i32 2)), ++ (XVPERMI_QD (v4i64 (IMPLICIT_DEF)), ++ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), ++ LSX128D:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i32 4)), ++ (XVPERMI_QW (v8i32 (IMPLICIT_DEF)), ++ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), ++ LSX128W:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i32 8)), ++ (XVPERMI_QH (v16i16 (IMPLICIT_DEF)), ++ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), ++ LSX128H:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i32 16)), ++ (XVPERMI_Q (v32i8 (IMPLICIT_DEF)), ++ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), ++ LSX128B:$src, sub_128)), (i32 32))>; ++ ++ ++def : LASXPat<(insert_subvector undef, (v2i64 LSX128D:$src), (i64 2)), ++ (XVPERMI_QD (v4i64 (IMPLICIT_DEF)), ++ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), ++ LSX128D:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v4i32 LSX128W:$src), (i64 4)), ++ (XVPERMI_QW (v8i32 (IMPLICIT_DEF)), ++ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), ++ LSX128W:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v8i16 LSX128H:$src), (i64 8)), ++ (XVPERMI_QH (v16i16 (IMPLICIT_DEF)), ++ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), ++ LSX128H:$src, sub_128)), (i32 32))>; ++ ++def : LASXPat<(insert_subvector undef, (v16i8 LSX128B:$src), (i64 16)), ++ (XVPERMI_Q (v32i8 (IMPLICIT_DEF)), ++ (v32i8 (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), ++ LSX128B:$src, sub_128)), (i32 32))>; ++ ++ ++def : LASXPat<(sra ++ (v32i8 (add ++ (v32i8 (add LASX256B:$a, LASX256B:$b)), ++ (v32i8 (srl ++ (v32i8 (add LASX256B:$a, LASX256B:$b)), ++ (v32i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (XVAVG_B (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; ++ ++def : LASXPat<(sra ++ (v16i16 (add ++ (v16i16 (add LASX256H:$a, LASX256H:$b)), ++ (v16i16 (srl ++ (v16i16 (add LASX256H:$a, LASX256H:$b)), ++ (v16i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (XVAVG_H (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; ++ ++def : LASXPat<(sra ++ (v8i32 (add ++ (v8i32 (add LASX256W:$a, LASX256W:$b)), ++ (v8i32 (srl ++ (v8i32 (add LASX256W:$a, LASX256W:$b)), ++ (v8i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31), ++ (i32 31),(i32 31),(i32 31),(i32 31)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (XVAVG_W (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; ++ ++def : LASXPat<(sra ++ (v4i64 (add ++ (v4i64 (add LASX256D:$a, LASX256D:$b)), ++ (v4i64 (srl ++ (v4i64 (add LASX256D:$a, LASX256D:$b)), ++ (v4i64 (build_vector (i64 63),(i64 63),(i64 63),(i64 63))) ++ ) ++ ) ++ ) ++ ), ++ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))), ++ (XVAVG_D (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; ++ ++ ++ ++def : LASXPat<(srl ++ (v32i8 (add LASX256B:$a, LASX256B:$b)), ++ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVG_BU (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; ++ ++def : LASXPat<(srl ++ (v16i16 (add LASX256H:$a, LASX256H:$b)), ++ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVG_HU (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; ++ ++def : LASXPat<(srl ++ (v8i32 (add LASX256W:$a, LASX256W:$b)), ++ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVG_WU (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; ++ ++def : LASXPat<(srl ++ (v4i64 (add LASX256D:$a, LASX256D:$b)), ++ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)) ++ ) ++ ), ++ (XVAVG_DU (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; ++ ++ ++ ++def : LASXPat<(sra ++ (v32i8 (add ++ (v32i8 (add (v32i8 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v32i8 (add LASX256B:$a, LASX256B:$b)) ++ )), ++ (v32i8 (srl ++ (v32i8 ( add (v32i8( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v32i8 (add LASX256B:$a, LASX256B:$b)) ++ )), ++ (v32i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (XVAVGR_B (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; ++ ++ ++def : LASXPat<(sra ++ (v16i16 (add ++ (v16i16 (add (v16i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i16 (add LASX256H:$a, LASX256H:$b)) ++ )), ++ (v16i16 (srl ++ (v16i16 (add (v16i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i16 (add LASX256H:$a, LASX256H:$b)) ++ )), ++ (v16i16 (build_vector ++ (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (XVAVGR_H (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; ++ ++ ++def : LASXPat<(sra ++ (v8i32 (add ++ (v8i32 (add (v8i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i32 (add LASX256W:$a, LASX256W:$b)) ++ )), ++ (v8i32 (srl ++ (v8i32 (add (v8i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i32 (add LASX256W:$a, LASX256W:$b)) ++ )), ++ (v8i32 (build_vector ++ (i32 31),(i32 31),(i32 31),(i32 31), ++ (i32 31),(i32 31),(i32 31),(i32 31) ++ ) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)))), ++ (XVAVGR_W (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; ++ ++def : LASXPat<(sra ++ (v4i64 (add ++ (v4i64 (add (v4i64 ( ++ build_vector (i64 1),(i64 1),(i64 1),(i64 1) ++ )), ++ (v4i64 (add LASX256D:$a, LASX256D:$b)) ++ )), ++ (v4i64 (srl ++ (v4i64 (add (v4i64 ( ++ build_vector (i64 1),(i64 1),(i64 1),(i64 1) ++ )), ++ (v4i64 (add LASX256D:$a, LASX256D:$b)) ++ )), ++ (v4i64 (build_vector ++ (i64 63),(i64 63),(i64 63),(i64 63))) ++ ) ++ ) ++ ) ++ ), ++ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))), ++ (XVAVGR_D (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; ++ ++ ++ ++def : LASXPat<(srl ++ (v32i8 (add (v32i8 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v32i8 (add LASX256B:$a, LASX256B:$b)) ++ )), ++ (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVGR_BU (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>; ++ ++def : LASXPat<(srl ++ (v16i16 (add (v16i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i16 (add LASX256H:$a, LASX256H:$b)) ++ )), ++ (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVGR_HU (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>; ++ ++def : LASXPat<(srl ++ (v8i32 (add (v8i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i32 (add LASX256W:$a, LASX256W:$b)) ++ )), ++ (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (XVAVGR_WU (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>; ++ ++def : LASXPat<(srl ++ (v4i64 (add (v4i64 ( ++ build_vector (i64 1),(i64 1),(i64 1),(i64 1) ++ )), ++ (v4i64 (add LASX256D:$a, LASX256D:$b)) ++ )), ++ (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)) ++ ) ++ ), ++ (XVAVGR_DU (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>; ++ ++ ++def : LASXPat<(mulhs LASX256D:$a, LASX256D:$b), ++ (XVMUH_D LASX256D:$a, LASX256D:$b)>; ++ ++def : LASXPat<(mulhs LASX256W:$a, LASX256W:$b), ++ (XVMUH_W LASX256W:$a, LASX256W:$b)>; ++ ++def : LASXPat<(mulhs LASX256H:$a, LASX256H:$b), ++ (XVMUH_H LASX256H:$a, LASX256H:$b)>; ++ ++def : LASXPat<(mulhs LASX256B:$a, LASX256B:$b), ++ (XVMUH_B LASX256B:$a, LASX256B:$b)>; ++ ++ ++def : LASXPat<(mulhu LASX256D:$a, LASX256D:$b), ++ (XVMUH_DU LASX256D:$a, LASX256D:$b)>; ++ ++def : LASXPat<(mulhu LASX256W:$a, LASX256W:$b), ++ (XVMUH_WU LASX256W:$a, LASX256W:$b)>; ++ ++def : LASXPat<(mulhu LASX256H:$a, LASX256H:$b), ++ (XVMUH_HU LASX256H:$a, LASX256H:$b)>; ++ ++def : LASXPat<(mulhu LASX256B:$a, LASX256B:$b), ++ (XVMUH_BU LASX256B:$a, LASX256B:$b)>; ++ ++ ++def : LASXPat<(LoongArchINSVE (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3), ++ (XVINSVE0_W LASX256W:$a, LASX256W:$b, uimm3:$ui3)>; ++ ++def : LASXPat<(LoongArchINSVE (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2), ++ (XVINSVE0_D LASX256D:$a, LASX256D:$b, uimm2:$ui2)>; ++ ++ ++def : LASXPat<(LoongArchXVPICKVE (v8i32 (bitconvert (v32i8 (build_vector ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0) ++ )))), (v8i32 LASX256W:$b), uimm3:$ui3), ++ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>; ++ ++def : LASXPat<(LoongArchXVPICKVE (v4i64 (bitconvert (v32i8 (build_vector ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0) ++ )))), (v4i64 LASX256D:$b), uimm2:$ui2), ++ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>; ++ ++ ++def : LASXPat<(LoongArchXVPICKVE (v8i32 (build_vector ++ (i32 0),(i32 0),(i32 0),(i32 0), ++ (i32 0),(i32 0),(i32 0),(i32 0) ++ )), (v8i32 LASX256W:$b), uimm3:$ui3), ++ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>; ++ ++def : LASXPat<(LoongArchXVPICKVE (v4i64 (build_vector ++ (i64 0),(i64 0),(i64 0),(i64 0) ++ )), (v4i64 LASX256D:$b), uimm2:$ui2), ++ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>; ++ ++ ++def : LASXPat<(LoongArchXVPICKVE (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3), ++ (XVPICKVE_W LASX256W:$a, LASX256W:$b, uimm3:$ui3)>; ++ ++def : LASXPat<(LoongArchXVPICKVE (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2), ++ (XVPICKVE_D LASX256D:$a, LASX256D:$b, uimm2:$ui2)>; ++ ++ ++def : LASXPat<(LoongArchXVSHUF4I (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm8_32:$ui8), ++ (XVSHUF4I_D LASX256D:$a, LASX256D:$b, uimm8_32:$ui8)>; ++ ++def : LASXPat<(LoongArchXVPERMI (v4i64 LASX256D:$a), uimm8_32:$ui8), ++ (XVPERMI_D LASX256D:$a, uimm8_32:$ui8)>; ++ ++ ++ ++ ++//===----------------------------------------------------------------------===// ++// Intrinsics ++//===----------------------------------------------------------------------===// ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cor_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_COR_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cor_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_COR_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cun_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CUN_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cun_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CUN_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cune_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CUNE_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cune_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CUNE_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cueq_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CUEQ_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cueq_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CUEQ_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_ceq_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CEQ_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_ceq_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CEQ_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cne_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CNE_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cne_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CNE_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_clt_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CLT_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_clt_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CLT_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cult_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CULT_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cult_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CULT_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cle_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CLE_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cle_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CLE_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cule_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFCMP_CULE_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfcmp_cule_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFCMP_CULE_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvseq_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSEQ_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvseq_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSEQ_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvseq_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSEQ_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvseq_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSEQ_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsle_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSLE_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSLE_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSLE_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSLE_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsle_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSLE_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSLE_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSLE_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsle_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSLE_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvslt_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSLT_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSLT_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSLT_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSLT_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvslt_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSLT_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSLT_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSLT_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvslt_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSLT_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvadd_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVADD_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvadd_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVADD_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvadd_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVADD_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvadd_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVADD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsub_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSUB_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsub_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSUB_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsub_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSUB_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsub_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSUB_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmax_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMAX_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMAX_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMAX_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMAX_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmin_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMIN_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMIN_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMIN_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMIN_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmin_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMIN_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMIN_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMIN_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmin_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMIN_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmul_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMUL_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmul_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMUL_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmul_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMUL_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmul_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMUL_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvdiv_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVDIV_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVDIV_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVDIV_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVDIV_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsll_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSLL_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsll_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSLL_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsll_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSLL_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsll_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSLL_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsrl_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSRL_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsrl_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSRL_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsrl_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSRL_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsrl_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSRL_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsra_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSRA_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsra_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSRA_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsra_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSRA_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsra_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSRA_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfadd_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFADD_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfadd_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFADD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfsub_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFSUB_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfsub_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFSUB_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfmul_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFMUL_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfmul_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFMUL_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfdiv_s (v8f32 LASX256W:$xj), (v8f32 LASX256W:$xk)), ++ (XVFDIV_S LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvfdiv_d (v4f64 LASX256D:$xj), (v4f64 LASX256D:$xk)), ++ (XVFDIV_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfsqrt_s (v8f32 LASX256W:$xj)), ++ (XVFSQRT_S LASX256W:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvfsqrt_d (v4f64 LASX256D:$xj)), ++ (XVFSQRT_D LASX256D:$xj)>; ++ ++def : LASXPat<(v8f32 (int_loongarch_lasx_xvffint_s_w (v8i32 LASX256W:$xj))), ++ (XVFFINT_S_W (v8i32 LASX256W:$xj))>; ++def : LASXPat<(v8f32 (int_loongarch_lasx_xvffint_s_wu (v8i32 LASX256W:$xj))), ++ (XVFFINT_S_WU (v8i32 LASX256W:$xj))>; ++ ++def : LASXPat<(v4f64 (int_loongarch_lasx_xvffint_d_l (v4i64 LASX256D:$xj))), ++ (XVFFINT_D_L (v4i64 LASX256D:$xj))>; ++def : LASXPat<(v4f64 (int_loongarch_lasx_xvffint_d_lu (v4i64 LASX256D:$xj))), ++ (XVFFINT_D_LU (v4i64 LASX256D:$xj))>; ++ ++def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_b GPR32Opnd:$rj), ++ (XVREPLGR2VR_B GPR32Opnd:$rj)>; ++def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_h GPR32Opnd:$rj), ++ (XVREPLGR2VR_H GPR32Opnd:$rj)>; ++def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_w GPR32Opnd:$rj), ++ (XVREPLGR2VR_W GPR32Opnd:$rj)>; ++def : LASXPat<(int_loongarch_lasx_xvreplgr2vr_d GPR64Opnd:$rj), ++ (XVREPLGR2VR_D GPR64Opnd:$rj)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickve2gr_w (v8i32 LASX256W:$xj), (immZExt3:$ui3)), ++ (XVPICKVE2GR_W LASX256W:$xj, uimm3:$ui3)>; ++def : LASXPat<(int_loongarch_lasx_xvpickve2gr_d (v4i64 LASX256D:$xj), (immZExt2:$ui2)), ++ (XVPICKVE2GR_D LASX256D:$xj, uimm2:$ui2)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickve2gr_wu (v8i32 LASX256W:$xj), (immZExt3:$ui3)), ++ (XVPICKVE2GR_WU LASX256W:$xj, uimm3:$ui3)>; ++def : LASXPat<(int_loongarch_lasx_xvpickve2gr_du (v4i64 LASX256D:$xj), (immZExt2:$ui2)), ++ (XVPICKVE2GR_DU LASX256D:$xj, uimm2:$ui2)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvreplve0_d (v4i64 LASX256D:$xj)), ++ (XVREPLVE0_D (v4i64 LASX256D:$xj))>; ++ ++def : LASXPat<(int_loongarch_lasx_xvinsgr2vr_w (v8i32 LASX256W:$xj), GPR32Opnd:$rj, (immZExt3:$ui3)), ++ (XVINSGR2VR_W LASX256W:$xj, GPR32Opnd:$rj, uimm3:$ui3)>; ++def : LASXPat<(int_loongarch_lasx_xvinsgr2vr_d (v4i64 LASX256D:$xj), GPR64Opnd:$rj, (immZExt2:$ui2)), ++ (XVINSGR2VR_D LASX256D:$xj, GPR64Opnd:$rj, uimm2:$ui2)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickve_w (v8i32 LASX256W:$xj), (immZExt3:$ui3)), ++ (XVPICKVE_W (v8i32 (IMPLICIT_DEF)), LASX256W:$xj, uimm3:$ui3)>; ++def : LASXPat<(int_loongarch_lasx_xvpickve_d (v4i64 LASX256D:$xj), (immZExt2:$ui2)), ++ (XVPICKVE_D (v4i64 (IMPLICIT_DEF)), LASX256D:$xj, uimm2:$ui2)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickve_w_f (v8f32 LASX256W:$xj), (immZExt3:$ui3)), ++ (XVPICKVE_W (v8f32 (IMPLICIT_DEF)), LASX256W:$xj, uimm3:$ui3)>; ++def : LASXPat<(int_loongarch_lasx_xvpickve_d_f (v4f64 LASX256D:$xj), (immZExt2:$ui2)), ++ (XVPICKVE_D (v4f64 (IMPLICIT_DEF)), LASX256D:$xj, uimm2:$ui2)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvdiv_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVDIV_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVDIV_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVDIV_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvdiv_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVDIV_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmod_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMOD_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMOD_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMOD_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMOD_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMOD_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMOD_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMOD_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMOD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmax_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMAX_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMAX_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMAX_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmax_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMAX_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvfrint_s (v8f32 LASX256W:$xj)), ++ (XVFRINT_S LASX256W:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvfrint_d (v4f64 LASX256D:$xj)), ++ (XVFRINT_D LASX256D:$xj)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpackod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVPACKOD_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVPACKOD_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVPACKOD_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVPACKOD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpackev_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVPACKEV_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackev_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVPACKEV_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackev_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVPACKEV_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpackev_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVPACKEV_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvilvh_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVILVH_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvh_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVILVH_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvh_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVILVH_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvh_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVILVH_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvilvl_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVILVL_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvl_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVILVL_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvl_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVILVL_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvilvl_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVILVL_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickev_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVPICKEV_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickev_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVPICKEV_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickev_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVPICKEV_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickev_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVPICKEV_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpickod_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVPICKOD_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickod_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVPICKOD_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickod_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVPICKOD_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvpickod_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVPICKOD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsadd_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSADD_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSADD_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSADD_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSADD_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvssub_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSSUB_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSSUB_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSSUB_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSSUB_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvsadd_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSADD_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSADD_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSADD_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvsadd_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSADD_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvssub_bu (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVSSUB_BU LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_hu (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVSSUB_HU LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_wu (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVSSUB_WU LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvssub_du (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVSSUB_DU LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmadd_b (v32i8 LASX256B:$xd_in), (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMADD_B LASX256B:$xd_in, LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmadd_h (v16i16 LASX256H:$xd_in), (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMADD_H LASX256H:$xd_in, LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmadd_w (v8i32 LASX256W:$xd_in), (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMADD_W LASX256W:$xd_in, LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmadd_d (v4i64 LASX256D:$xd_in), (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMADD_D LASX256D:$xd_in, LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvmsub_b (v32i8 LASX256B:$xd_in), (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVMSUB_B LASX256B:$xd_in, LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmsub_h (v16i16 LASX256H:$xd_in), (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVMSUB_H LASX256H:$xd_in, LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmsub_w (v8i32 LASX256W:$xd_in), (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVMSUB_W LASX256W:$xd_in, LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvmsub_d (v4i64 LASX256D:$xd_in), (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVMSUB_D LASX256D:$xd_in, LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(v8i32 (int_loongarch_lasx_xvftintrz_wu_s (v8f32 LASX256W:$xj))), ++ (XVFTINTRZ_WU_S (v8f32 LASX256W:$xj))>; ++def : LASXPat<(v4i64 (int_loongarch_lasx_xvftintrz_lu_d (v4f64 LASX256D:$xj))), ++ (XVFTINTRZ_LU_D (v4f64 LASX256D:$xj))>; ++ ++def : LASXPat<(v8i32 (int_loongarch_lasx_xvftintrz_w_s (v8f32 LASX256W:$xj))), ++ (XVFTINTRZ_W_S (v8f32 LASX256W:$xj))>; ++def : LASXPat<(v4i64 (int_loongarch_lasx_xvftintrz_l_d (v4f64 LASX256D:$xj))), ++ (XVFTINTRZ_L_D (v4f64 LASX256D:$xj))>; ++ ++def : LASXPat<(int_loongarch_lasx_xvbitclr_b (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk)), ++ (XVBITCLR_B LASX256B:$xj, LASX256B:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvbitclr_h (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk)), ++ (XVBITCLR_H LASX256H:$xj, LASX256H:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvbitclr_w (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk)), ++ (XVBITCLR_W LASX256W:$xj, LASX256W:$xk)>; ++def : LASXPat<(int_loongarch_lasx_xvbitclr_d (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk)), ++ (XVBITCLR_D LASX256D:$xj, LASX256D:$xk)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvclz_b (v32i8 LASX256B:$xj)), ++ (XVCLZ_B LASX256B:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvclz_h (v16i16 LASX256H:$xj)), ++ (XVCLZ_H LASX256H:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvclz_w (v8i32 LASX256W:$xj)), ++ (XVCLZ_W LASX256W:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvclz_d (v4i64 LASX256D:$xj)), ++ (XVCLZ_D LASX256D:$xj)>; ++ ++def : LASXPat<(int_loongarch_lasx_xvpcnt_b (v32i8 LASX256B:$xj)), ++ (XVPCNT_B LASX256B:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvpcnt_h (v16i16 LASX256H:$xj)), ++ (XVPCNT_H LASX256H:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvpcnt_w (v8i32 LASX256W:$xj)), ++ (XVPCNT_W LASX256W:$xj)>; ++def : LASXPat<(int_loongarch_lasx_xvpcnt_d (v4i64 LASX256D:$xj)), ++ (XVPCNT_D LASX256D:$xj)>; ++ ++ ++def : LASXPat<(v32i8 (load (add iPTR:$xj, iPTR:$xk))), ++ (XVLDX PtrRC:$xj, PtrRC:$xk)>; ++ ++def : LASXPat<(store (v32i8 LASX256B:$xd), (add iPTR:$xj, iPTR:$xk)), ++ (XVSTX LASX256B:$xd, PtrRC:$xj, PtrRC:$xk)>; ++ ++ ++def : LASXPat<(v4i64 (sext_invec (v8i32 LASX256W:$xj))), ++ (VEXT2XV_D_W LASX256W:$xj)>; ++def : LASXPat<(v8i32 (sext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_W_H LASX256H:$xj)>; ++def : LASXPat<(v16i16 (sext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_H_B LASX256B:$xj)>; ++ ++ ++def : LASXPat<(v4i64 (zext_invec (v8i32 LASX256W:$xj))), ++ (VEXT2XV_DU_WU LASX256W:$xj)>; ++def : LASXPat<(v8i32 (zext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_WU_HU LASX256H:$xj)>; ++def : LASXPat<(v16i16 (zext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_HU_BU LASX256B:$xj)>; ++ ++ ++def : LASXPat<(v4i64 (sext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_D_H LASX256H:$xj)>; ++def : LASXPat<(v4i64 (sext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_D_B LASX256B:$xj)>; ++def : LASXPat<(v8i32 (sext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_W_B LASX256B:$xj)>; ++ ++ ++def : LASXPat<(v4i64 (zext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_DU_HU LASX256H:$xj)>; ++def : LASXPat<(v4i64 (zext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_DU_BU LASX256B:$xj)>; ++def : LASXPat<(v8i32 (zext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_WU_BU LASX256B:$xj)>; ++ ++ ++def : LASXPat<(v4i64 (sext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_D_H LASX256H:$xj)>; ++def : LASXPat<(v4i64 (sext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_D_B LASX256B:$xj)>; ++def : LASXPat<(v8i32 (sext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_W_B LASX256B:$xj)>; ++ ++def : LASXPat<(v4i64 (zext_invec (v16i16 LASX256H:$xj))), ++ (VEXT2XV_DU_HU LASX256H:$xj)>; ++def : LASXPat<(v4i64 (zext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_DU_BU LASX256B:$xj)>; ++def : LASXPat<(v8i32 (zext_invec (v32i8 LASX256B:$xj))), ++ (VEXT2XV_WU_BU LASX256B:$xj)>; ++ ++ ++def : LASXPat<(v16i16 (sext (v16i8 LSX128B:$vj))), ++ (VEXT2XV_H_B ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$vj, sub_128))>; ++ ++def : LASXPat<(v8i32 (sext (v8i16 LSX128H:$vj))), ++ (VEXT2XV_W_H ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$vj, sub_128))>; ++ ++def : LASXPat<(v4i64 (sext (v4i32 LSX128W:$vj))), ++ (VEXT2XV_D_W ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$vj, sub_128))>; ++ ++def : LASXPat<(v16i16 (zext (v16i8 LSX128B:$vj))), ++ (VEXT2XV_HU_BU ++ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), LSX128B:$vj, sub_128))>; ++ ++def : LASXPat<(v8i32 (zext (v8i16 LSX128H:$vj))), ++ (VEXT2XV_WU_HU ++ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), LSX128H:$vj, sub_128))>; ++ ++def : LASXPat<(v4i64 (zext (v4i32 LSX128W:$vj))), ++ (VEXT2XV_DU_WU ++ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), LSX128W:$vj, sub_128))>; ++ ++ ++def : LASXPat<(xor ++ (v16i16 LASX256H:$xj), (xvsplati16 imm_mask) ++ ), ++ (XNOR_V_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xj))>; ++ ++def : LASXPat<(xor ++ (v8i32 LASX256W:$xj), (xvsplati32 imm_mask) ++ ), ++ (XNOR_V_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xj))>; ++ ++def : LASXPat<(xor ++ (v4i64 LASX256D:$xj), (xvsplati64 imm_mask_64) ++ ), ++ (XNOR_V_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xj))>; ++ ++ ++def : LASXPat<(and ++ (v32i8 (xor (v32i8 LASX256B:$xj), (xvsplati8 imm_mask))), ++ (v32i8 LASX256B:$xk) ++ ), ++ (XVANDN_V (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk))>; ++ ++def : LASXPat<(and ++ (v16i16 (xor (v16i16 LASX256H:$xj), (xvsplati16 imm_mask))), ++ (v16i16 LASX256H:$xk) ++ ), ++ (XVANDN_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk))>; ++ ++def : LASXPat<(and ++ (v8i32 (xor (v8i32 LASX256W:$xj), (xvsplati32 imm_mask))), ++ (v8i32 LASX256W:$xk) ++ ), ++ (XVANDN_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk))>; ++ ++def : LASXPat<(and ++ (v4i64 (xor (v4i64 LASX256D:$xj), (xvsplati64 imm_mask_64))), ++ (v4i64 LASX256D:$xk) ++ ), ++ (XVANDN_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk))>; ++ ++ ++def : LASXPat<(or ++ (v32i8 LASX256B:$xj), ++ (v32i8 (xor (v32i8 LASX256B:$xk), (xvsplati8 imm_mask))) ++ ), ++ (XVORN_V (v32i8 LASX256B:$xj), (v32i8 LASX256B:$xk))>; ++ ++def : LASXPat<(or ++ (v16i16 LASX256H:$xj), ++ (v16i16 (xor (v16i16 LASX256H:$xk), (xvsplati16 imm_mask))) ++ ), ++ (XVORN_H_PSEUDO (v16i16 LASX256H:$xj), (v16i16 LASX256H:$xk))>; ++ ++def : LASXPat<(or ++ (v8i32 LASX256W:$xj), ++ (v8i32 (xor (v8i32 LASX256W:$xk), (xvsplati32 imm_mask))) ++ ), ++ (XVORN_W_PSEUDO (v8i32 LASX256W:$xj), (v8i32 LASX256W:$xk))>; ++ ++def : LASXPat<(or ++ (v4i64 LASX256D:$xj), ++ (v4i64 (xor (v4i64 LASX256D:$xk), (xvsplati64 imm_mask_64))) ++ ), ++ (XVORN_D_PSEUDO (v4i64 LASX256D:$xj), (v4i64 LASX256D:$xk))>; ++ ++ ++def : LASXPat<(add (v4i64 (abs LASX256D:$a)), (v4i64 (abs LASX256D:$b))), ++ (XVADDA_D (v4i64 LASX256D:$a),(v4i64 LASX256D:$b))>; ++ ++def : LASXPat<(add (v8i32 (abs LASX256W:$a)), (v8i32 (abs LASX256W:$b))), ++ (XVADDA_W (v8i32 LASX256W:$a),(v8i32 LASX256W:$b))>; ++ ++def : LASXPat<(add (v16i16 (abs LASX256H:$a)), (v16i16 (abs LASX256H:$b))), ++ (XVADDA_H (v16i16 LASX256H:$a),(v16i16 LASX256H:$b))>; ++ ++def : LASXPat<(add (v32i8 (abs LASX256B:$a)), (v32i8 (abs LASX256B:$b))), ++ (XVADDA_B (v32i8 LASX256B:$a),(v32i8 LASX256B:$b))>; ++ ++ ++def : LASXPat<(and v32i8:$xj, (xor (shl xvsplat_imm_eq_1, v32i8:$xk), ++ (xvsplati8 imm_mask))), ++ (XVBITCLR_B v32i8:$xj, v32i8:$xk)>; ++ ++def : LASXPat<(and v16i16:$xj, (xor (shl xvsplat_imm_eq_1, v16i16:$xk), ++ (xvsplati16 imm_mask))), ++ (XVBITCLR_H v16i16:$xj, v16i16:$xk)>; ++ ++def : LASXPat<(and v8i32:$xj, (xor (shl xvsplat_imm_eq_1, v8i32:$xk), ++ (xvsplati32 imm_mask))), ++ (XVBITCLR_W v8i32:$xj, v8i32:$xk)>; ++ ++def : LASXPat<(and v4i64:$xj, (xor (shl xvsplat_imm_eq_1, v4i64:$xk), ++ (xvsplati64 imm_mask_64))), ++ (XVBITCLR_D v4i64:$xj, v4i64:$xk)>; ++ ++ ++def : LASXPat<(insert_subvector (v16i16 LASX256H:$dst), ++ (v8i16 LSX128H:$src), (i64 0)), ++ (XVPERMI_QH (v16i16 LASX256H:$dst), ++ (v16i16 (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), ++ LSX128H:$src, sub_128)), ++ (i32 48))>; ++ ++def : LASXPat<(insert_subvector (v8i32 LASX256W:$dst), ++ (v4i32 LSX128W:$src), (i64 0)), ++ (XVPERMI_QW (v8i32 LASX256W:$dst), ++ (v8i32 (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), ++ LSX128W:$src, sub_128)), ++ (i32 48))>; ++ ++def : LASXPat<(insert_subvector (v4i64 LASX256D:$dst), ++ (v2i64 LSX128D:$src), (i64 0)), ++ (XVPERMI_QD (v4i64 LASX256D:$dst), ++ (v4i64 (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), ++ LSX128D:$src, sub_128)), ++ (i32 48))>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td +new file mode 100644 +index 000000000..50df4d724 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrFormats.td +@@ -0,0 +1,449 @@ ++//===- LoongArchLSXInstrFormats.td - LoongArch LSX Instruction Formats ---*- tablegen -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++class LSXInst : InstLA<(outs), (ins), "", [], FrmOther>, ++ EXT_LSX { ++} ++ ++class LSXCBranch : LSXInst { ++} ++ ++class LSXSpecial : LSXInst { ++} ++ ++class LSXPseudo pattern>: ++ LoongArchPseudo { ++ let Predicates = [HasLSX]; ++} ++ ++class LSX_3R op>: LSXInst { ++ bits<5> vk; ++ bits<5> vj; ++ bits<5> vd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = vk; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_3R_1GP op>: LSXInst { ++ bits<5> rk; ++ bits<5> vj; ++ bits<5> vd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I5 op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<5> si5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = si5; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I5_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<5> ui5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = ui5; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_2R op>: LSXInst { ++ bits<5> vj; ++ bits<5> vd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_2R_1GP op>: LSXInst { ++ bits<5> rj; ++ bits<5> vd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I1_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I2_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I3_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I4_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I6_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<6> ui6; ++ ++ let Inst{31-16} = op; ++ let Inst{15-10} = ui6; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I1_R_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I2_R_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I3_R_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I4_R_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_ELM_COPY_B op>: LSXInst { ++ bits<5> rd; ++ bits<5> vj; ++ bits<4> ui4; ++ ++ let Inst{31-14} = op; ++ let Inst{13-10} = ui4; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = rd; ++} ++ ++class LSX_ELM_COPY_H op>: LSXInst { ++ bits<5> rd; ++ bits<5> vj; ++ bits<3> ui3; ++ ++ let Inst{31-13} = op; ++ let Inst{12-10} = ui3; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = rd; ++} ++ ++class LSX_ELM_COPY_W op>: LSXInst { ++ bits<5> rd; ++ bits<5> vj; ++ bits<2> ui2; ++ ++ let Inst{31-12} = op; ++ let Inst{11-10} = ui2; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = rd; ++} ++ ++class LSX_ELM_COPY_D op>: LSXInst { ++ bits<5> rd; ++ bits<5> vj; ++ bits<1> ui1; ++ ++ let Inst{31-11} = op; ++ let Inst{10} = ui1; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = rd; ++} ++ ++class LSX_I8_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<8> ui8; ++ ++ let Inst{31-18} = op; ++ let Inst{17-10} = ui8; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I7_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<7> ui7; ++ ++ let Inst{31-17} = op; ++ let Inst{16-10} = ui7; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I12_S op>: LSXInst { ++ bits<5> vd; ++// bits<5> rj; ++// bits<12> si12; ++ bits<17> addr; ++ ++ let Inst{31-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI12_S op>: LSXInst { ++ bits<5> vd; ++ bits<17> addr; ++ ++ let Inst{31-22} = op; ++ let Inst{21-10} = addr{11-0}; ++ let Inst{9-5} = addr{16-12}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI11_S op>: LSXInst { ++ bits<5> vd; ++ bits<16> addr; ++ ++ let Inst{31-21} = op; ++ let Inst{20-10} = addr{10-0}; ++ let Inst{9-5} = addr{15-11}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI10_S op>: LSXInst { ++ bits<5> vd; ++ bits<15> addr; ++ ++ let Inst{31-20} = op; ++ let Inst{19-10} = addr{9-0}; ++ let Inst{9-5} = addr{14-10}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI9_S op>: LSXInst { ++ bits<5> vd; ++ bits<14> addr; ++ ++ let Inst{31-19} = op; ++ let Inst{18-10} = addr{8-0}; ++ let Inst{9-5} = addr{13-9}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SET op>: LSXInst { ++ bits<5> vj; ++ bits<3> cd; ++ ++ let Inst{31-10} = op; ++ let Inst{9-5} = vj; ++ let Inst{4-3} = 0b00; ++ let Inst{2-0} = cd; ++} ++ ++class LSX_VR4MUL op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<5> vk; ++ bits<5> va; ++ ++ let Inst{31-20} = op; ++ let Inst{19-15} = va; ++ let Inst{14-10} = vk; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_VFCMP op>: LSXInst { ++ bits<5> vd; ++ bits<5> vj; ++ bits<5> vk; ++ bits<5> cond; ++ ++ let Inst{31-20} = op; ++ let Inst{19-15} = cond; ++ let Inst{14-10} = vk; ++ let Inst{9-5} = vj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_Addr_SI8_idx1 op>: LSXInst { ++ bits<5> vd; ++ bits<13> addr; ++ bits<1> idx; ++ ++ let Inst{31-19} = op; ++ let Inst{18-11} = addr{7-0}; ++ let Inst{10} = idx; ++ let Inst{9-5} = addr{12-8}; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI8_idx1 op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<1> idx; ++ ++ let Inst{31-19} = op; ++ let Inst{18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI8_idx2 op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<2> idx; ++ ++ let Inst{31-20} = op; ++ let Inst{19-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI8_idx3 op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<3> idx; ++ ++ let Inst{31-21} = op; ++ let Inst{20-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_SI8_idx4 op>: LSXInst { ++ bits<5> vd; ++ bits<5> rj; ++ bits<8> si8; ++ bits<4> idx; ++ ++ let Inst{31-22} = op; ++ let Inst{21-18} = idx; ++ let Inst{17-10} = si8; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_3R_2GP op>: LSXInst { ++ bits<5> rk; ++ bits<5> rj; ++ bits<5> vd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = rk; ++ let Inst{9-5} = rj; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_I5_mode_U op>: LSXInst { ++ bits<5> vd; ++ bits<5> mode; ++ bits<5> ui5; ++ ++ let Inst{31-15} = op; ++ let Inst{14-10} = ui5; ++ let Inst{9-5} = mode; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_1R_I13 op>: LSXInst { ++ bits<13> i13; ++ bits<5> vd; ++ ++ let Inst{31-18} = op; ++ let Inst{17-5} = i13; ++ let Inst{4-0} = vd; ++} ++ ++class LSX_1R_I13_I10 op>: LSXInst { ++ bits<10> i10; ++ bits<5> vd; ++ ++ let Inst{31-15} = op; ++ let Inst{14-5} = i10; ++ let Inst{4-0} = vd; ++} ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td +new file mode 100644 +index 000000000..3d0ea3901 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td +@@ -0,0 +1,5906 @@ ++//===- LoongArchLSXInstrInfo.td - LSX instructions -*- tablegen ------------*-=// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file describes LoongArch LSX instructions. ++// ++//===----------------------------------------------------------------------===// ++ ++def SDT_LoongArchVecCond : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<1>]>; ++def SDT_VSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, ++ SDTCisInt<1>, ++ SDTCisSameAs<1, 2>, ++ SDTCisVT<3, OtherVT>]>; ++def SDT_VFSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, ++ SDTCisFP<1>, ++ SDTCisSameAs<1, 2>, ++ SDTCisVT<3, OtherVT>]>; ++def SDT_VSHF : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>, ++ SDTCisInt<1>, SDTCisVec<1>, ++ SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; ++def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, ++ SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>; ++def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, ++ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>; ++def SDTVABSD : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, ++ SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; ++ ++def SDT_VBROADCAST : SDTypeProfile<1, 1, [SDTCisVec<0>]>; ++def LoongArchVBROADCAST : SDNode<"LoongArchISD::VBROADCAST", SDT_VBROADCAST>; ++ ++def LoongArchVAllNonZero : SDNode<"LoongArchISD::VALL_NONZERO", SDT_LoongArchVecCond>; ++def LoongArchVAnyNonZero : SDNode<"LoongArchISD::VANY_NONZERO", SDT_LoongArchVecCond>; ++def LoongArchVAllZero : SDNode<"LoongArchISD::VALL_ZERO", SDT_LoongArchVecCond>; ++def LoongArchVAnyZero : SDNode<"LoongArchISD::VANY_ZERO", SDT_LoongArchVecCond>; ++def LoongArchVNOR : SDNode<"LoongArchISD::VNOR", SDTIntBinOp, ++ [SDNPCommutative, SDNPAssociative]>; ++def LoongArchVSHF : SDNode<"LoongArchISD::VSHF", SDT_VSHF>; ++def LoongArchSHF : SDNode<"LoongArchISD::SHF", SDT_SHF>; ++def LoongArchVPACKEV : SDNode<"LoongArchISD::VPACKEV", SDT_ILV>; ++def LoongArchVPACKOD : SDNode<"LoongArchISD::VPACKOD", SDT_ILV>; ++def LoongArchVILVH : SDNode<"LoongArchISD::VILVH", SDT_ILV>; ++def LoongArchVILVL : SDNode<"LoongArchISD::VILVL", SDT_ILV>; ++def LoongArchVPICKEV : SDNode<"LoongArchISD::VPICKEV", SDT_ILV>; ++def LoongArchVPICKOD : SDNode<"LoongArchISD::VPICKOD", SDT_ILV>; ++def LoongArchVABSD : SDNode<"LoongArchISD::VABSD", SDTVABSD>; ++def LoongArchUVABSD : SDNode<"LoongArchISD::UVABSD", SDTVABSD>; ++ ++def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>; ++def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>; ++ ++def LoongArchVExtractSExt : SDNode<"LoongArchISD::VEXTRACT_SEXT_ELT", ++ SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; ++def LoongArchVExtractZExt : SDNode<"LoongArchISD::VEXTRACT_ZEXT_ELT", ++ SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; ++ ++def immZExt1Ptr : ImmLeaf(Imm);}]>; ++def immZExt2Ptr : ImmLeaf(Imm);}]>; ++def immZExt3Ptr : ImmLeaf(Imm);}]>; ++def immZExt4Ptr : ImmLeaf(Imm);}]>; ++def immZExt5Ptr : ImmLeaf(Imm);}]>; ++def immZExt10 : ImmLeaf(Imm);}]>; ++def immZExt8 : ImmLeaf(Imm);}]>; ++def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>; ++def immZExt6 : ImmLeaf; ++def immZExt4 : ImmLeaf(Imm);}]>; ++def immZExt3 : ImmLeaf(Imm);}]>; ++def immZExt2 : ImmLeaf(Imm);}]>; ++def immZExt1 : ImmLeaf(Imm);}]>; ++def immSExt12_l : ImmLeaf(Imm);}]>; ++def immSExt11Ptr : ImmLeaf(Imm);}]>; ++ ++def immSExt11_1 : ImmLeaf(Imm<<1);}]>; ++def immSExt10Ptr : ImmLeaf(Imm);}]>; ++def immSExt10_2 : ImmLeaf(Imm<<2);}]>; ++def immSExt9Ptr : ImmLeaf(Imm);}]>; ++def immSExt9_3 : ImmLeaf(Imm<<3);}]>; ++def immSExt8 : ImmLeaf(Imm);}]>; ++def immSExt5 : ImmLeaf(Imm);}]>; ++def immSExt8_1 : ImmLeaf(Imm<<1);}]>; ++def immSExt8_2 : ImmLeaf(Imm<<2);}]>; ++def immSExt8_3 : ImmLeaf(Imm<<3);}]>; ++ ++def addrimm10 : ComplexPattern; ++def addrimm10lsl2 : ComplexPattern; ++def addrimm9lsl3 : ComplexPattern; ++def addrimm11lsl1 : ComplexPattern; ++ ++ ++class SimmLslAsmOperandClass Supers = [], ++ int Shift = 0> : AsmOperandClass { ++ let Name = "Simm" # Bits # "_Lsl" # Shift; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift; ++} ++ ++def Simm11Lsl1AsmOperand ++ : SimmLslAsmOperandClass<11, [], 1>; ++ ++def immSExt11_1_O : Operand { ++ let EncoderMethod = "getSImm11Lsl1Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; ++ let ParserMatchClass = Simm11Lsl1AsmOperand; ++} ++ ++def Simm10Lsl2AsmOperand ++ : SimmLslAsmOperandClass<10, [], 2>; ++ ++def immSExt10_2_O : Operand { ++ let EncoderMethod = "getSImm10Lsl2Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<4>"; ++ let ParserMatchClass = Simm10Lsl2AsmOperand; ++} ++ ++def Simm9Lsl3AsmOperand ++ : SimmLslAsmOperandClass<9, [], 3>; ++ ++def immSExt9_3_O : Operand { ++ let EncoderMethod = "getSImm9Lsl3Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; ++ let ParserMatchClass = Simm9Lsl3AsmOperand; ++} ++ ++def Simm8Lsl3AsmOperand ++ : SimmLslAsmOperandClass<8, [], 3>; ++ ++def immSExt8_3_O : Operand { ++ let EncoderMethod = "getSImm8Lsl3Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<8>"; ++ let ParserMatchClass = Simm8Lsl3AsmOperand; ++} ++ ++def Simm8Lsl2AsmOperand ++ : SimmLslAsmOperandClass<8, [], 2>; ++ ++def immSExt8_2_O : Operand { ++ let EncoderMethod = "getSImm8Lsl2Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<4>"; ++ let ParserMatchClass = Simm8Lsl2AsmOperand; ++} ++ ++def Simm8Lsl1AsmOperand ++ : SimmLslAsmOperandClass<8, [], 1>; ++ ++def immSExt8_1_O : Operand { ++ let EncoderMethod = "getSImm8Lsl1Encoding"; ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<2>"; ++ let ParserMatchClass = Simm8Lsl1AsmOperand; ++} ++ ++ ++class ConstantSImmAsmOperandClass Supers = [], ++ int Offset = 0> : AsmOperandClass { ++ let Name = "ConstantSImm" # Bits # "_" # Offset; ++ let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">"; ++ let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "SImm" # Bits # "_" # Offset; ++} ++ ++class ConstantUImmRangeAsmOperandClass Supers = []> ++ : AsmOperandClass { ++ let Name = "ConstantUImmRange" # Bottom # "_" # Top; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">"; ++ let SuperClasses = Supers; ++ let DiagnosticType = "UImmRange" # Bottom # "_" # Top; ++} ++ ++def SImm16RelaxedAsmOperandClass ++ : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { ++ let Name = "SImm16_Relaxed"; ++ let PredicateMethod = "isAnyImm<16>"; ++ let DiagnosticType = "SImm16_Relaxed"; ++} ++ ++def ConstantSImm11Lsl1AsmOperandClass : AsmOperandClass { ++ let Name = "SImm11Lsl1"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<11, 1>"; ++ let SuperClasses = [SImm12Operand]; ++ let DiagnosticType = "SImm11_Lsl1"; ++} ++ ++def ConstantSImm9Lsl3AsmOperandClass : AsmOperandClass { ++ let Name = "SImm9Lsl3"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<9, 3>"; ++ let SuperClasses = [SImm12Operand]; ++ let DiagnosticType = "SImm9_Lsl3"; ++} ++ ++def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { ++ let Name = "SImm10Lsl2"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<10, 2>"; ++ let SuperClasses = [SImm12Operand]; ++ let DiagnosticType = "SImm10_Lsl2"; ++} ++def ConstantSImm11AsmOperandClass ++ : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>; ++def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass { ++ let Name = "SImm10Lsl1"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<10, 1>"; ++ let SuperClasses = [ConstantSImm11AsmOperandClass]; ++ let DiagnosticType = "SImm10_Lsl1"; ++} ++def ConstantUImm10AsmOperandClass ++ : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>; ++def ConstantSImm10AsmOperandClass ++ : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>; ++def ConstantSImm9AsmOperandClass ++ : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>; ++def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass { ++ let Name = "SImm7Lsl2"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledSImm<7, 2>"; ++ let SuperClasses = [ConstantSImm9AsmOperandClass]; ++ let DiagnosticType = "SImm7_Lsl2"; ++} ++def ConstantUImm8AsmOperandClass ++ : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>; ++def ConstantUImm7Sub1AsmOperandClass ++ : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> { ++ // Specify the names since the -1 offset causes invalid identifiers otherwise. ++ let Name = "UImm7_N1"; ++ let DiagnosticType = "UImm7_N1"; ++} ++def ConstantUImm7AsmOperandClass ++ : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>; ++def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass { ++ let Name = "UImm6Lsl2"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledUImm<6, 2>"; ++ let SuperClasses = [ConstantUImm7AsmOperandClass]; ++ let DiagnosticType = "UImm6_Lsl2"; ++} ++def ConstantUImm6AsmOperandClass ++ : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>; ++def ConstantSImm6AsmOperandClass ++ : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>; ++def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { ++ let Name = "UImm5Lsl2"; ++ let RenderMethod = "addImmOperands"; ++ let PredicateMethod = "isScaledUImm<5, 2>"; ++ let SuperClasses = [ConstantSImm6AsmOperandClass]; ++ let DiagnosticType = "UImm5_Lsl2"; ++} ++def ConstantUImm5_Range2_64AsmOperandClass ++ : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>; ++def ConstantUImm5Plus33AsmOperandClass ++ : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass], ++ 33>; ++def ConstantUImm5ReportUImm6AsmOperandClass ++ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> { ++ let Name = "ConstantUImm5_0_Report_UImm6"; ++ let DiagnosticType = "UImm5_0_Report_UImm6"; ++} ++def ConstantUImm5Plus32AsmOperandClass ++ : ConstantUImmAsmOperandClass< ++ 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>; ++def ConstantUImm5Plus32NormalizeAsmOperandClass ++ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> { ++ let Name = "ConstantUImm5_32_Norm"; ++ // We must also subtract 32 when we render the operand. ++ let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; ++} ++def ConstantUImm5Plus1ReportUImm6AsmOperandClass ++ : ConstantUImmAsmOperandClass< ++ 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>{ ++ let Name = "ConstantUImm5_Plus1_Report_UImm6"; ++} ++def ConstantUImm5Plus1AsmOperandClass ++ : ConstantUImmAsmOperandClass< ++ 5, [ConstantUImm5Plus1ReportUImm6AsmOperandClass], 1>; ++def ConstantUImm5AsmOperandClass ++ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>; ++def ConstantSImm5AsmOperandClass ++ : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>; ++def ConstantUImm4AsmOperandClass ++ : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>; ++def ConstantSImm4AsmOperandClass ++ : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>; ++def ConstantUImm3AsmOperandClass ++ : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>; ++def ConstantUImm2AsmOperandClass ++ : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass]>; ++def ConstantUImm1AsmOperandClass ++ : ConstantUImmAsmOperandClass<1, [ConstantUImm2AsmOperandClass]>; ++def ConstantImmzAsmOperandClass : AsmOperandClass { ++ let Name = "ConstantImmz"; ++ let RenderMethod = "addConstantUImmOperands<1>"; ++ let PredicateMethod = "isConstantImmz"; ++ let SuperClasses = [ConstantUImm1AsmOperandClass]; ++ let DiagnosticType = "Immz"; ++} ++ ++foreach I = {1, 2, 3, 4, 5, 6, 8} in ++ def vsplat_uimm # I : Operand { ++ let PrintMethod = "printUImm<" # I # ">"; ++ let ParserMatchClass = ++ !cast("ConstantUImm" # I # "AsmOperandClass"); ++ } ++ ++foreach I = {5, 10} in ++ def vsplat_simm # I : Operand { ++ let ParserMatchClass = ++ !cast("ConstantSImm" # I # "AsmOperandClass"); ++ } ++ ++foreach I = {1, 4, 7, 8, 10, 20, 26} in ++ def uimm # I : Operand { ++ let PrintMethod = "printUImm<" # I # ">"; ++ let ParserMatchClass = ++ !cast("ConstantUImm" # I # "AsmOperandClass"); ++ } ++ ++foreach I = {1, 2, 3, 4, 5, 6, 7, 8} in ++ def uimm # I # _ptr : Operand { ++ let PrintMethod = "printUImm<" # I # ">"; ++ let ParserMatchClass = ++ !cast("ConstantUImm" # I # "AsmOperandClass"); ++ } ++ ++ ++def addrimm12 : ComplexPattern; ++ ++ ++def LoongArchMemSimm12AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm12"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<12>"; ++ let DiagnosticType = "MemSImm12"; ++} ++ ++def mem_simm12 : mem_generic { ++ let MIOperandInfo = (ops ptr_rc, simm12); ++ let EncoderMethod = "getMemEncoding"; ++ let ParserMatchClass = LoongArchMemSimm12AsmOperand; ++} ++ ++foreach I = {4, 6, 9, 10, 11} in ++ def simm # I : Operand { ++ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; ++ let ParserMatchClass = ++ !cast("ConstantSImm" # I # "AsmOperandClass"); ++ } ++ ++def LoongArchMemSimm9AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm9"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<9>"; ++ let DiagnosticType = "MemSImm9"; ++} ++ ++def LoongArchMemSimm10AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm10"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<10>"; ++ let DiagnosticType = "MemSImm10"; ++} ++ ++def LoongArchMemSimm11AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm11"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<11>"; ++ let DiagnosticType = "MemSImm11"; ++} ++ ++def simm13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; ++ ++def simm10Op : Operand { ++ let DecoderMethod = "DecodeSIMM10"; ++} ++ ++def simm13Op : Operand { ++ let DecoderMethod = "DecodeSIMM13"; ++} ++ ++def LoongArchMemSimm10Lsl2AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm10_2"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<10, 2>"; ++ let DiagnosticType = "MemSImm10Lsl2"; ++} ++ ++ ++def simm10_lsl2 : Operand { ++// let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, 2>"; ++ let ParserMatchClass = ++ !cast("ConstantSImm10Lsl2AsmOperandClass"); ++} ++ ++def mem_simm10_lsl2 : mem_generic { ++ let MIOperandInfo = (ops ptr_rc, !cast("simm10_lsl2")); ++ let EncoderMethod = "getMemEncoding10l2"; ++ let ParserMatchClass = ++ !cast("LoongArchMemSimm10Lsl2AsmOperand"); ++} ++ ++ ++def LoongArchMemSimm11Lsl1AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm11_1"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<11, 1>"; ++ let DiagnosticType = "MemSImm11Lsl1"; ++} ++ ++ ++def simm11_lsl1 : Operand { ++ // let DecoderMethod = "DecodeSImmWithOffsetAndScale<11, 1>"; ++ let ParserMatchClass = ++ !cast("ConstantSImm11Lsl1AsmOperandClass"); ++} ++ ++def mem_simm11_lsl1 : mem_generic { ++ let MIOperandInfo = (ops ptr_rc, !cast("simm11_lsl1")); ++ let EncoderMethod = "getMemEncoding11l1"; ++ let ParserMatchClass = ++ !cast("LoongArchMemSimm11Lsl1AsmOperand"); ++} ++ ++def LoongArchMemSimm9Lsl3AsmOperand : AsmOperandClass { ++ let Name = "MemOffsetSimm9_3"; ++ let SuperClasses = [LoongArchMemAsmOperand]; ++ let RenderMethod = "addMemOperands"; ++ let ParserMethod = "parseMemOperand"; ++ let PredicateMethod = "isMemWithSimmOffset<9, 3>"; ++ let DiagnosticType = "MemSImm9Lsl3"; ++} ++ ++ ++def simm9_lsl3 : Operand { ++ // let DecoderMethod = "DecodeSImmWithOffsetAndScale<9, 3>"; ++ let ParserMatchClass = ++ !cast("ConstantSImm9Lsl3AsmOperandClass"); ++} ++ ++def mem_simm9_lsl3 : mem_generic { ++ let MIOperandInfo = (ops ptr_rc, !cast("simm9_lsl3")); ++ let EncoderMethod = "getMemEncoding9l3"; ++ let ParserMatchClass = ++ !cast("LoongArchMemSimm9Lsl3AsmOperand"); ++} ++ ++ ++ ++ ++// Operands ++ ++def immZExt2Lsa : ImmLeaf(Imm - 1);}]>; ++ ++// Pattern fragments ++def vextract_sext_i8 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractSExt node:$vec, node:$idx, i8)>; ++def vextract_sext_i16 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractSExt node:$vec, node:$idx, i16)>; ++def vextract_sext_i32 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractSExt node:$vec, node:$idx, i32)>; ++def vextract_sext_i64 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractSExt node:$vec, node:$idx, i64)>; ++ ++def vextract_zext_i8 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractZExt node:$vec, node:$idx, i8)>; ++def vextract_zext_i16 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractZExt node:$vec, node:$idx, i16)>; ++def vextract_zext_i32 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractZExt node:$vec, node:$idx, i32)>; ++def vextract_zext_i64 : PatFrag<(ops node:$vec, node:$idx), ++ (LoongArchVExtractZExt node:$vec, node:$idx, i64)>; ++ ++def vldrepl_v16i8 : PatFrag<(ops node:$v1), ++ (v16i8 (LoongArchVBROADCAST node:$v1))>; ++def vldrepl_v8i16 : PatFrag<(ops node:$v1), ++ (v8i16 (LoongArchVBROADCAST node:$v1))>; ++def vldrepl_v4i32 : PatFrag<(ops node:$v1), ++ (v4i32 (LoongArchVBROADCAST node:$v1))>; ++def vldrepl_v2i64 : PatFrag<(ops node:$v1), ++ (v2i64 (LoongArchVBROADCAST node:$v1))>; ++ ++def vinsert_v16i8 : PatFrag<(ops node:$vec, node:$val, node:$idx), ++ (v16i8 (vector_insert node:$vec, node:$val, node:$idx))>; ++def vinsert_v8i16 : PatFrag<(ops node:$vec, node:$val, node:$idx), ++ (v8i16 (vector_insert node:$vec, node:$val, node:$idx))>; ++def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx), ++ (v4i32 (vector_insert node:$vec, node:$val, node:$idx))>; ++def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx), ++ (v2i64 (vector_insert node:$vec, node:$val, node:$idx))>; ++ ++class vfsetcc_type : ++ PatFrag<(ops node:$lhs, node:$rhs), ++ (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>; ++ ++// ISD::SETFALSE cannot occur ++def vfseteq_v4f32 : vfsetcc_type; ++def vfseteq_v2f64 : vfsetcc_type; ++def vfsetge_v4f32 : vfsetcc_type; ++def vfsetge_v2f64 : vfsetcc_type; ++def vfsetgt_v4f32 : vfsetcc_type; ++def vfsetgt_v2f64 : vfsetcc_type; ++def vfsetle_v4f32 : vfsetcc_type; ++def vfsetle_v2f64 : vfsetcc_type; ++def vfsetlt_v4f32 : vfsetcc_type; ++def vfsetlt_v2f64 : vfsetcc_type; ++def vfsetne_v4f32 : vfsetcc_type; ++def vfsetne_v2f64 : vfsetcc_type; ++def vfsetoeq_v4f32 : vfsetcc_type; ++def vfsetoeq_v2f64 : vfsetcc_type; ++def vfsetoge_v4f32 : vfsetcc_type; ++def vfsetoge_v2f64 : vfsetcc_type; ++def vfsetogt_v4f32 : vfsetcc_type; ++def vfsetogt_v2f64 : vfsetcc_type; ++def vfsetole_v4f32 : vfsetcc_type; ++def vfsetole_v2f64 : vfsetcc_type; ++def vfsetolt_v4f32 : vfsetcc_type; ++def vfsetolt_v2f64 : vfsetcc_type; ++def vfsetone_v4f32 : vfsetcc_type; ++def vfsetone_v2f64 : vfsetcc_type; ++def vfsetord_v4f32 : vfsetcc_type; ++def vfsetord_v2f64 : vfsetcc_type; ++def vfsetun_v4f32 : vfsetcc_type; ++def vfsetun_v2f64 : vfsetcc_type; ++def vfsetueq_v4f32 : vfsetcc_type; ++def vfsetueq_v2f64 : vfsetcc_type; ++def vfsetuge_v4f32 : vfsetcc_type; ++def vfsetuge_v2f64 : vfsetcc_type; ++def vfsetugt_v4f32 : vfsetcc_type; ++def vfsetugt_v2f64 : vfsetcc_type; ++def vfsetule_v4f32 : vfsetcc_type; ++def vfsetule_v2f64 : vfsetcc_type; ++def vfsetult_v4f32 : vfsetcc_type; ++def vfsetult_v2f64 : vfsetcc_type; ++def vfsetune_v4f32 : vfsetcc_type; ++def vfsetune_v2f64 : vfsetcc_type; ++ ++ ++ ++// ISD::SETTRUE cannot occur ++// ISD::SETFALSE2 cannot occur ++// ISD::SETTRUE2 cannot occur ++ ++class vsetcc_type : ++ PatFrag<(ops node:$lhs, node:$rhs), ++ (ResTy (vsetcc node:$lhs, node:$rhs, CC))>; ++ ++def vseteq_v16i8 : vsetcc_type; ++def vseteq_v8i16 : vsetcc_type; ++def vseteq_v4i32 : vsetcc_type; ++def vseteq_v2i64 : vsetcc_type; ++def vsetle_v16i8 : vsetcc_type; ++def vsetle_v8i16 : vsetcc_type; ++def vsetle_v4i32 : vsetcc_type; ++def vsetle_v2i64 : vsetcc_type; ++def vsetlt_v16i8 : vsetcc_type; ++def vsetlt_v8i16 : vsetcc_type; ++def vsetlt_v4i32 : vsetcc_type; ++def vsetlt_v2i64 : vsetcc_type; ++def vsetule_v16i8 : vsetcc_type; ++def vsetule_v8i16 : vsetcc_type; ++def vsetule_v4i32 : vsetcc_type; ++def vsetule_v2i64 : vsetcc_type; ++def vsetult_v16i8 : vsetcc_type; ++def vsetult_v8i16 : vsetcc_type; ++def vsetult_v4i32 : vsetcc_type; ++def vsetult_v2i64 : vsetcc_type; ++ ++def vsplati8 : PatFrag<(ops node:$e0), ++ (v16i8 (build_vector node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0))>; ++def vsplati16 : PatFrag<(ops node:$e0), ++ (v8i16 (build_vector node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0, ++ node:$e0, node:$e0))>; ++def vsplati32 : PatFrag<(ops node:$e0), ++ (v4i32 (build_vector node:$e0, node:$e0, ++ node:$e0, node:$e0))>; ++ ++def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ ++ APInt Imm; ++ SDNode *BV = N->getOperand(0).getNode(); ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; ++}]>; ++ ++def vsplati64 : PatFrag<(ops node:$e0), ++ (v2i64 (build_vector node:$e0, node:$e0))>; ++ ++def vsplati64_splat_d : PatFrag<(ops node:$e0), ++ (v2i64 (bitconvert ++ (v4i32 (and ++ (v4i32 (build_vector node:$e0, ++ node:$e0, ++ node:$e0, ++ node:$e0)), ++ vsplati64_imm_eq_1))))>; ++ ++def vsplatf32 : PatFrag<(ops node:$e0), ++ (v4f32 (build_vector node:$e0, node:$e0, ++ node:$e0, node:$e0))>; ++def vsplatf64 : PatFrag<(ops node:$e0), ++ (v2f64 (build_vector node:$e0, node:$e0))>; ++ ++def vsplati8_elt : PatFrag<(ops node:$v, node:$i), ++ (LoongArchVSHF (vsplati8 node:$i), node:$v, node:$v)>; ++def vsplati16_elt : PatFrag<(ops node:$v, node:$i), ++ (LoongArchVSHF (vsplati16 node:$i), node:$v, node:$v)>; ++def vsplati32_elt : PatFrag<(ops node:$v, node:$i), ++ (LoongArchVSHF (vsplati32 node:$i), node:$v, node:$v)>; ++def vsplati64_elt : PatFrag<(ops node:$v, node:$i), ++ (LoongArchVSHF (vsplati64_splat_d node:$i),node:$v, node:$v)>; ++ ++class SplatPatLeaf ++ : PatLeaf { ++ Operand OpClass = opclass; ++} ++ ++class SplatComplexPattern roots = [], ++ list props = []> : ++ ComplexPattern { ++ Operand OpClass = opclass; ++} ++ ++def vsplati8_uimm3 : SplatComplexPattern; ++ ++def vsplati8_uimm4 : SplatComplexPattern; ++ ++def vsplati8_uimm5 : SplatComplexPattern; ++ ++def vsplati8_uimm8 : SplatComplexPattern; ++ ++def vsplati8_simm5 : SplatComplexPattern; ++ ++def vsplati16_uimm3 : SplatComplexPattern; ++ ++def vsplati16_uimm4 : SplatComplexPattern; ++ ++def vsplati16_uimm5 : SplatComplexPattern; ++ ++def vsplati16_simm5 : SplatComplexPattern; ++ ++def vsplati32_uimm2 : SplatComplexPattern; ++ ++def vsplati32_uimm5 : SplatComplexPattern; ++ ++def vsplati32_simm5 : SplatComplexPattern; ++ ++def vsplati64_uimm1 : SplatComplexPattern; ++ ++def vsplati64_uimm5 : SplatComplexPattern; ++ ++def vsplati64_uimm6 : SplatComplexPattern; ++ ++def vsplati64_simm5 : SplatComplexPattern; ++ ++ ++// Any build_vector that is a constant splat with a value that equals 1 ++// FIXME: These should be a ComplexPattern but we can't use them because the ++// ISel generator requires the uses to have a name, but providing a name ++// causes other errors ("used in pattern but not operand list") ++def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{ ++ APInt Imm; ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ return selectVSplat(N, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; ++}]>; ++ ++def vbitclr_b : PatFrag<(ops node:$vj, node:$vk), ++ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), ++ immAllOnesV))>; ++def vbitclr_h : PatFrag<(ops node:$vj, node:$vk), ++ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), ++ immAllOnesV))>; ++def vbitclr_w : PatFrag<(ops node:$vj, node:$vk), ++ (and node:$vj, (xor (shl vsplat_imm_eq_1, node:$vk), ++ immAllOnesV))>; ++def vbitclr_d : PatFrag<(ops node:$vj, node:$vk), ++ (and node:$vj, (xor (shl (v2i64 vsplati64_imm_eq_1), ++ node:$vk), ++ (bitconvert (v4i32 immAllOnesV))))>; ++ ++def vbneg_b : PatFrag<(ops node:$vj, node:$vk), ++ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbneg_h : PatFrag<(ops node:$vj, node:$vk), ++ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbneg_w : PatFrag<(ops node:$vj, node:$vk), ++ (xor node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbneg_d : PatFrag<(ops node:$vj, node:$vk), ++ (xor node:$vj, (shl (v2i64 vsplati64_imm_eq_1), ++ node:$vk))>; ++ ++def vbset_b : PatFrag<(ops node:$vj, node:$vk), ++ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbset_h : PatFrag<(ops node:$vj, node:$vk), ++ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbset_w : PatFrag<(ops node:$vj, node:$vk), ++ (or node:$vj, (shl vsplat_imm_eq_1, node:$vk))>; ++def vbset_d : PatFrag<(ops node:$vj, node:$vk), ++ (or node:$vj, (shl (v2i64 vsplati64_imm_eq_1), ++ node:$vk))>; ++ ++def muladd : PatFrag<(ops node:$vd, node:$vj, node:$vk), ++ (add node:$vd, (mul node:$vj, node:$vk))>; ++ ++def mulsub : PatFrag<(ops node:$vd, node:$vj, node:$vk), ++ (sub node:$vd, (mul node:$vj, node:$vk))>; ++ ++class IsCommutable { ++ bit isCommutable = 1; ++} ++ ++ ++ ++//class ++class LSX_3R_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; ++} ++ ++class LSX_3RN_DESC_BASE : ++ LSX_3R_DESC_BASE; ++ ++class LSX_3R_4R_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, ++ ROVK:$vk))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_3R_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, GPR32Opnd:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $rk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, GPR32Opnd:$rk))]; ++} ++ ++class LSX_VEC_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; ++} ++ ++class LSX_VEC_PSEUDO_BASE : ++ LSXPseudo<(outs ROVD:$vd), (ins ROVJ:$vj, ROVK:$vk), ++ [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]>; ++ ++class LSX_3RF_DESC_BASE : ++ LSX_3R_DESC_BASE; ++ ++class LSX_3RFN_DESC_BASE : ++ LSX_3R_DESC_BASE; ++ ++class LSX_3R_DESC_BASE1 { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vk, ROVK:$vj))]; ++} ++ ++class LSX_3RF_DESC_BASE1 : ++ LSX_3R_DESC_BASE1; ++ ++class LSX_3R_VSHF_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF ROVD:$vd_in, ROVJ:$vj, ++ ROVK:$vk))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_3R_4R_VSHF_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVD:$va); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF ROVD:$va, ROVJ:$vj, ++ ROVK:$vk))]; ++} ++ ++class LSX_I5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $si5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$si5))]; ++} ++ ++class LSX_I5_U_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui5))]; ++} ++ ++class LSX_BIT_3_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui3))]; ++} ++ ++class LSX_BIT_3N_DESC_BASE : ++ LSX_BIT_3_DESC_BASE; ++ ++class LSX_BIT_4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui4))]; ++} ++ ++class LSX_BIT_4N_DESC_BASE : ++ LSX_BIT_4_DESC_BASE; ++ ++class LSX_BIT_5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui5))]; ++} ++ ++class LSX_BIT_5N_DESC_BASE : ++ LSX_BIT_5_DESC_BASE; ++ ++class LSX_BIT_6_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui6))]; ++} ++ ++class LSX_BIT_6N_DESC_BASE : ++ LSX_BIT_6_DESC_BASE; ++ ++class LSX_2R_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; ++} ++ ++class LSX_2RN_DESC_BASE : ++ LSX_2R_DESC_BASE; ++ ++class LSX_2RF_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; ++} ++ ++class LSX_2RFN_DESC_BASE : ++ LSX_2R_DESC_BASE; ++ ++class LSX_2RF_DESC_BASE_CVT { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj))]; ++} ++ ++class LSX_2RFN_DESC_BASE_CVT : ++ LSX_2RF_DESC_BASE_CVT; ++ ++class LSX_2RF_DESC_BASE_tmp { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj"); ++ list Pattern = []; ++} ++ ++class LSX_2R_REPL_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROS:$rj); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj"); ++ list Pattern = [(set ROVD:$vd, (VT (OpNode ROS:$rj)))]; ++} ++ ++class LSX_INSERT_U4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$rj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$rj, Imm:$ui4))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_INSERT_U4N_DESC_BASE : ++ LSX_INSERT_U4_DESC_BASE; ++ ++class LSX_INSERT_U3_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui3))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_INSERT_U3N_DESC_BASE : ++ LSX_INSERT_U3_DESC_BASE; ++ ++class LSX_INSERT_U2_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui2"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui2))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_INSERT_U2N_DESC_BASE : ++ LSX_INSERT_U2_DESC_BASE; ++ ++class LSX_INSERT_U1_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROS:$rj, ImmOp:$ui1); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $ui1"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROS:$rj, Imm:$ui1))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_INSERT_U1N_DESC_BASE : ++ LSX_INSERT_U1_DESC_BASE; ++ ++class LSX_PICK_U1_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui1); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui1"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui1))]; ++} ++ ++class LSX_PICK_U2_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui2"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui2))]; ++} ++ ++class LSX_PICK_U3_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui3"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui3))]; ++} ++ ++class LSX_PICK_U4_DESC_BASE { ++ dag OutOperandList = (outs ROD:$rd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$rd, $vj, $ui4"); ++ list Pattern = [(set ROD:$rd, (OpNode (VecTy ROVJ:$vj), Imm:$ui4))]; ++} ++ ++class LSX_ELM_U3_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui3, ROVJ:$vj, ++ ROVJ:$vj))]; ++} ++ ++class LSX_ELM_U2_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui2"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui2, ROVJ:$vj, ++ ROVJ:$vj))]; ++} ++ ++class LSX_ELM_U1_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui1); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui1"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui1, ROVJ:$vj, ++ ROVJ:$vj))]; ++} ++ ++class LSX_ELM_U4_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVSHF SplatImm:$ui4, ROVJ:$vj, ++ ROVJ:$vj))]; ++} ++ ++class LSX_ELM_U4_SLD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, ++ Imm:$ui4))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_ELM_U3_SLD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, ++ Imm:$ui3))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_ELM_U2_SLD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui2); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui2"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, ++ Imm:$ui2))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_ELM_U1_SLD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui1); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui1"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, ++ Imm:$ui1))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_BIT_U3_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui3))]; ++} ++ ++class LSX_BIT_U4_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui4))]; ++} ++ ++class LSX_BIT_U5_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui5))]; ++} ++ ++class LSX_BIT_U6_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui6))]; ++} ++ ++class LSX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm6:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt6:$ui6))]; ++} ++ ++class LSX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm3:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt3:$ui3))]; ++} ++ ++class LSX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt4:$ui4))]; ++} ++ ++class LSX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; ++} ++ ++class LSX_I8_SHF_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (LoongArchSHF immZExt8:$ui8, ROVJ:$vj))]; ++} ++ ++class LSX_I8_SHUF_DESC_BASE_D { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt8:$ui8))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++def LoongArchSelect : SDNode<"LoongArchISD::VSELECT" ,SDTSelect>; ++def LoongArchVROR : SDNode<"LoongArchISD::VROR", ++ SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, ++ SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]>, []>; ++def LoongArchVRORI : SDNode<"LoongArchISD::VRORI", ++ SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisInt<0>, ++ SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>, []>; ++ ++class LSX2_RORI_U3_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui3))]; ++} ++ ++class LSX2_RORI_U4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui4))]; ++} ++ ++class LSX2_RORI_U5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui5))]; ++} ++ ++class LSX2_RORI_U6_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (LoongArchVRORI ROVJ:$vj, Imm:$ui6))]; ++} ++ ++class LSX_BIND_U4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui4))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_BIND_U4N_DESC_BASE : ++ LSX_BIND_U4_DESC_BASE; ++ ++class LSX_BIND_U5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui5))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_BIND_U5N_DESC_BASE : ++ LSX_BIND_U5_DESC_BASE; ++ ++class LSX_BIND_U6_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, ImmOp:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, Imm:$ui6))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_BIND_U6N_DESC_BASE : ++ LSX_BIND_U6_DESC_BASE; ++ ++class LSX_BIND_U7_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm7:$ui7); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui7"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt7:$ui7))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_BIND_U7N_DESC_BASE : ++ LSX_BIND_U7_DESC_BASE; ++ ++ ++class LD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); ++ list Pattern = [(set ROVD:$vd, (TyNode (OpNode Addr:$addr)))]; ++ string DecoderMethod = "DecodeLSX128Mem"; ++} ++ ++class ST_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); ++ list Pattern = [(OpNode (TyNode ROVD:$vd), Addr:$addr)]; ++ string DecoderMethod = "DecodeLSX128Mem"; ++} ++ ++class LSX_VEC_ADDR_PSEUDO_BASE : ++ LSXPseudo<(outs), (ins ROVD:$vd, MemOpnd:$addr), ++ [(OpNode (TyNode ROVD:$vd), MemOpnd:$addr)]>; ++ ++ ++class LSX_SET_DESC_BASE { ++ dag OutOperandList = (outs FCFROpnd:$cd); ++ dag InOperandList = (ins ROVD:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$cd, $vj"); ++ list Pattern = []; ++} ++ ++class LSX_SET_DESC_BASE_tmp { ++ dag OutOperandList = (outs FCFROpnd:$cd); ++ dag InOperandList = (ins ROVD:$vj); ++ string AsmString = !strconcat(instr_asm, "\t$cd, $vj"); ++ list Pattern = []; ++} ++ ++class LSX_VMul_Reg4 { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVA:$va); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk, ROVA:$va))]; ++} ++ ++class LSX_4RF { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk, ROVA:$va); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk, $va"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk, ROVA:$va))]; ++} ++ ++ ++class LSX_VFCMP_Reg3 { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ROVK:$vk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $vk"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, ROVK:$vk))]; ++} ++ ++class LSX_I12_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si12); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si12"); ++ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si12))]; ++} ++ ++class LSX_I11_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si11); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si11"); ++ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si11))]; ++} ++ ++class LSX_I10_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si10); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si10"); ++ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si10))]; ++} ++ ++class LSX_I9_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins PtrRC:$rj, ImmOp:$si9); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si9"); ++ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, Imm:$si9))]; ++} ++ ++ ++class LSX_I8_U1_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm1:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt1:$idx)]; ++ string DecoderMethod = "DecodeLSX128memstl"; ++} ++ ++ ++class LSX_I8_U2_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm2:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt2:$idx)]; ++ string DecoderMethod = "DecodeLSX128memstl"; ++} ++ ++class LSX_I8_U3_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm3:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt3:$idx)]; ++ string DecoderMethod = "DecodeLSX128memstl"; ++} ++ ++class LSX_I8_U4_DESC_BASE { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, ImmOp:$si8, uimm4:$idx); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $si8, $idx"); ++ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, Imm:$si8, immZExt4:$idx)]; ++ string DecoderMethod = "DecodeLSX128memstl"; ++} ++ ++class LSX_I5_U_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$ui5))]; ++} ++ ++class LSX_I5_DESC_BASE_Intrinsic { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, ImmOp:$si5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $si5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, Imm:$si5))]; ++} ++ ++class LSX_LDX_LA { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins PtrRC:$rj, RORK:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk"); ++ list Pattern = [(set ROVD:$vd, (OpNode iPTR:$rj, RORK:$rk))]; ++} ++ ++class LSX_SDX_LA { ++ dag OutOperandList = (outs); ++ dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, RORK:$rk); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk"); ++ list Pattern = [(OpNode ROVD:$vd, iPTR:$rj, RORK:$rk)]; ++} ++ ++class LSX_U5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; ++} ++ ++class LSX_U5_4R_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt5:$ui5))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_U3_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm3:$ui3); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui3"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt3:$ui3))]; ++} ++ ++class LSX_2R_U4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt4:$ui4))]; ++} ++ ++class LSX_2R_U5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt5:$ui5))]; ++} ++ ++class LSX_2R_U6_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm6:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt6:$ui6))]; ++} ++ ++class LSX_2R_3R_U4_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm4:$ui4); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui4"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt4:$ui4))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_3R_U5_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm5:$ui5); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui5"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt5:$ui5))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_3R_U6_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm6:$ui6); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui6"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt6:$ui6))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_3R_U7_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm7:$ui7); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui7"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt7:$ui7))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_3R_U8_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, ROVJ:$vj, immZExt8:$ui8))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_3R_SELECT { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVD:$vd_in, ROVJ:$vj, vsplat_uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVD:$vd_in, vsplati8_uimm8:$ui8, ROVJ:$vj))]; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class LSX_2R_U8_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, uimm8:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, immZExt8:$ui8))]; ++} ++ ++class LSX_I13_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins immOp:$i13); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $i13"); ++ list Pattern = [(set ROVD:$vd, (OpNode (Ty simm13:$i13)))]; ++ string DecoderMethod = "DecodeLSX128Mem13"; ++} ++ ++class LSX_I13_DESC_BASE_10 { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ImmOp:$i10); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $i10"); ++ list Pattern = [(set ROVD:$vd, (OpNode Imm:$i10))]; ++ bit hasSideEffects = 0; ++ string DecoderMethod = "DecodeLSX128Mem10"; ++} ++ ++class LSX_BIT_U8_VREPLVE_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins ROVJ:$vj, SplatImm.OpClass:$ui8); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8"); ++ list Pattern = [(set ROVD:$vd, (OpNode ROVJ:$vj, SplatImm:$ui8))]; ++} ++ ++ ++class LSXPat pred = [HasLSX]> : ++ Pat, Requires; ++ ++// Instruction encoding. ++ ++ ++def VSADD_B : LSX_3R<0b01110000010001100>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.b", LSX128BOpnd>; ++ ++def VSADD_H : LSX_3R<0b01110000010001101>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.h", LSX128HOpnd>; ++ ++def VSADD_W : LSX_3R<0b01110000010001110>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.w", LSX128WOpnd>; ++ ++def VSADD_D : LSX_3R<0b01110000010001111>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.d", LSX128DOpnd>; ++ ++ ++def VSSUB_B : LSX_3R<0b01110000010010000>, ++ LSX_3RN_DESC_BASE<"vssub.b", LSX128BOpnd>; ++ ++def VSSUB_H : LSX_3R<0b01110000010010001>, ++ LSX_3RN_DESC_BASE<"vssub.h", LSX128HOpnd>; ++ ++def VSSUB_W : LSX_3R<0b01110000010010010>, ++ LSX_3RN_DESC_BASE<"vssub.w", LSX128WOpnd>; ++ ++def VSSUB_D : LSX_3R<0b01110000010010011>, ++ LSX_3RN_DESC_BASE<"vssub.d", LSX128DOpnd>; ++ ++ ++def VSADD_BU : LSX_3R<0b01110000010010100>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.bu", LSX128BOpnd>; ++ ++def VSADD_HU : LSX_3R<0b01110000010010101>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.hu", LSX128HOpnd>; ++ ++def VSADD_WU : LSX_3R<0b01110000010010110>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.wu", LSX128WOpnd>; ++ ++def VSADD_DU : LSX_3R<0b01110000010010111>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vsadd.du", LSX128DOpnd>; ++ ++ ++def VSSUB_BU : LSX_3R<0b01110000010011000>, ++ LSX_3RN_DESC_BASE<"vssub.bu", LSX128BOpnd>; ++ ++def VSSUB_HU : LSX_3R<0b01110000010011001>, ++ LSX_3RN_DESC_BASE<"vssub.hu", LSX128HOpnd>; ++ ++def VSSUB_WU : LSX_3R<0b01110000010011010>, ++ LSX_3RN_DESC_BASE<"vssub.wu", LSX128WOpnd>; ++ ++def VSSUB_DU : LSX_3R<0b01110000010011011>, ++ LSX_3RN_DESC_BASE<"vssub.du", LSX128DOpnd>; ++ ++ ++def VHADDW_H_B : LSX_3R<0b01110000010101000>, ++ LSX_3RN_DESC_BASE<"vhaddw.h.b", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VHADDW_W_H : LSX_3R<0b01110000010101001>, ++ LSX_3RN_DESC_BASE<"vhaddw.w.h", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VHADDW_D_W : LSX_3R<0b01110000010101010>, ++ LSX_3RN_DESC_BASE<"vhaddw.d.w", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++ ++def VHSUBW_H_B : LSX_3R<0b01110000010101100>, ++ LSX_3RN_DESC_BASE<"vhsubw.h.b", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VHSUBW_W_H : LSX_3R<0b01110000010101101>, ++ LSX_3RN_DESC_BASE<"vhsubw.w.h", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VHSUBW_D_W : LSX_3R<0b01110000010101110>, ++ LSX_3RN_DESC_BASE<"vhsubw.d.w", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++ ++def VHADDW_HU_BU : LSX_3R<0b01110000010110000>, ++ LSX_3RN_DESC_BASE<"vhaddw.hu.bu", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VHADDW_WU_HU : LSX_3R<0b01110000010110001>, ++ LSX_3RN_DESC_BASE<"vhaddw.wu.hu", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VHADDW_DU_WU : LSX_3R<0b01110000010110010>, ++ LSX_3RN_DESC_BASE<"vhaddw.du.wu", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++ ++def VHSUBW_HU_BU : LSX_3R<0b01110000010110100>, ++ LSX_3RN_DESC_BASE<"vhsubw.hu.bu", LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VHSUBW_WU_HU : LSX_3R<0b01110000010110101>, ++ LSX_3RN_DESC_BASE<"vhsubw.wu.hu", LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VHSUBW_DU_WU : LSX_3R<0b01110000010110110>, ++ LSX_3RN_DESC_BASE<"vhsubw.du.wu", LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++ ++def VADDA_B : LSX_3R<0b01110000010111000>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vadda.b", LSX128BOpnd>; ++ ++def VADDA_H : LSX_3R<0b01110000010111001>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vadda.h", LSX128HOpnd>; ++ ++def VADDA_W : LSX_3R<0b01110000010111010>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vadda.w", LSX128WOpnd>; ++ ++def VADDA_D : LSX_3R<0b01110000010111011>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vadda.d", LSX128DOpnd>; ++ ++ ++def VABSD_B : LSX_3R<0b01110000011000000>, ++ LSX_3RN_DESC_BASE<"vabsd.b", LSX128BOpnd>; ++ ++def VABSD_H : LSX_3R<0b01110000011000001>, ++ LSX_3RN_DESC_BASE<"vabsd.h", LSX128HOpnd>; ++ ++def VABSD_W : LSX_3R<0b01110000011000010>, ++ LSX_3RN_DESC_BASE<"vabsd.w", LSX128WOpnd>; ++ ++def VABSD_D : LSX_3R<0b01110000011000011>, ++ LSX_3RN_DESC_BASE<"vabsd.d", LSX128DOpnd>; ++ ++ ++def VABSD_BU : LSX_3R<0b01110000011000100>, ++ LSX_3RN_DESC_BASE<"vabsd.bu", LSX128BOpnd>; ++ ++def VABSD_HU : LSX_3R<0b01110000011000101>, ++ LSX_3RN_DESC_BASE<"vabsd.hu", LSX128HOpnd>; ++ ++def VABSD_WU : LSX_3R<0b01110000011000110>, ++ LSX_3RN_DESC_BASE<"vabsd.wu", LSX128WOpnd>; ++ ++def VABSD_DU : LSX_3R<0b01110000011000111>, ++ LSX_3RN_DESC_BASE<"vabsd.du", LSX128DOpnd>; ++ ++ ++def VAVG_B : LSX_3R<0b01110000011001000>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.b", LSX128BOpnd>; ++ ++def VAVG_H : LSX_3R<0b01110000011001001>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.h", LSX128HOpnd>; ++ ++def VAVG_W : LSX_3R<0b01110000011001010>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.w", LSX128WOpnd>; ++ ++def VAVG_D : LSX_3R<0b01110000011001011>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.d", LSX128DOpnd>; ++ ++ ++def VAVG_BU : LSX_3R<0b01110000011001100>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.bu", LSX128BOpnd>; ++ ++def VAVG_HU : LSX_3R<0b01110000011001101>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.hu", LSX128HOpnd>; ++ ++def VAVG_WU : LSX_3R<0b01110000011001110>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.wu", LSX128WOpnd>; ++ ++def VAVG_DU : LSX_3R<0b01110000011001111>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavg.du", LSX128DOpnd>; ++ ++ ++def VAVGR_B : LSX_3R<0b01110000011010000>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.b", LSX128BOpnd>; ++ ++def VAVGR_H : LSX_3R<0b01110000011010001>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.h", LSX128HOpnd>; ++ ++def VAVGR_W : LSX_3R<0b01110000011010010>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.w", LSX128WOpnd>; ++ ++def VAVGR_D : LSX_3R<0b01110000011010011>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.d", LSX128DOpnd>; ++ ++ ++def VAVGR_BU : LSX_3R<0b01110000011010100>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.bu", LSX128BOpnd>; ++ ++def VAVGR_HU : LSX_3R<0b01110000011010101>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.hu", LSX128HOpnd>; ++ ++def VAVGR_WU : LSX_3R<0b01110000011010110>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.wu", LSX128WOpnd>; ++ ++def VAVGR_DU : LSX_3R<0b01110000011010111>, IsCommutable, ++ LSX_3RN_DESC_BASE<"vavgr.du", LSX128DOpnd>; ++ ++ ++def VMAX_B : LSX_3R<0b01110000011100000>, ++ LSX_3R_DESC_BASE<"vmax.b", smax, LSX128BOpnd>; ++ ++def VMAX_H : LSX_3R<0b01110000011100001>, ++ LSX_3R_DESC_BASE<"vmax.h", smax, LSX128HOpnd>; ++ ++def VMAX_W : LSX_3R<0b01110000011100010>, ++ LSX_3R_DESC_BASE<"vmax.w", smax, LSX128WOpnd>; ++ ++def VMAX_D : LSX_3R<0b01110000011100011>, ++ LSX_3R_DESC_BASE<"vmax.d", smax, LSX128DOpnd>; ++ ++ ++def VMIN_B : LSX_3R<0b01110000011100100>, ++ LSX_3R_DESC_BASE<"vmin.b", smin, LSX128BOpnd>; ++ ++def VMIN_H : LSX_3R<0b01110000011100101>, ++ LSX_3R_DESC_BASE<"vmin.h", smin, LSX128HOpnd>; ++ ++def VMIN_W : LSX_3R<0b01110000011100110>, ++ LSX_3R_DESC_BASE<"vmin.w", smin, LSX128WOpnd>; ++ ++def VMIN_D : LSX_3R<0b01110000011100111>, ++ LSX_3R_DESC_BASE<"vmin.d", smin, LSX128DOpnd>; ++ ++ ++def VMAX_BU : LSX_3R<0b01110000011101000>, ++ LSX_3R_DESC_BASE<"vmax.bu", umax, LSX128BOpnd>; ++ ++def VMAX_HU : LSX_3R<0b01110000011101001>, ++ LSX_3R_DESC_BASE<"vmax.hu", umax, LSX128HOpnd>; ++ ++def VMAX_WU : LSX_3R<0b01110000011101010>, ++ LSX_3R_DESC_BASE<"vmax.wu", umax, LSX128WOpnd>; ++ ++def VMAX_DU : LSX_3R<0b01110000011101011>, ++ LSX_3R_DESC_BASE<"vmax.du", umax, LSX128DOpnd>; ++ ++ ++def VMIN_BU : LSX_3R<0b01110000011101100>, ++ LSX_3R_DESC_BASE<"vmin.bu", umin, LSX128BOpnd>; ++ ++def VMIN_HU : LSX_3R<0b01110000011101101>, ++ LSX_3R_DESC_BASE<"vmin.hu", umin, LSX128HOpnd>; ++ ++def VMIN_WU : LSX_3R<0b01110000011101110>, ++ LSX_3R_DESC_BASE<"vmin.wu", umin, LSX128WOpnd>; ++ ++def VMIN_DU : LSX_3R<0b01110000011101111>, ++ LSX_3R_DESC_BASE<"vmin.du", umin, LSX128DOpnd>; ++ ++ ++def VMUL_B : LSX_3R<0b01110000100001000>, ++ LSX_3R_DESC_BASE<"vmul.b", mul, LSX128BOpnd>; ++ ++def VMUL_H : LSX_3R<0b01110000100001001>, ++ LSX_3R_DESC_BASE<"vmul.h", mul, LSX128HOpnd>; ++ ++def VMUL_W : LSX_3R<0b01110000100001010>, ++ LSX_3R_DESC_BASE<"vmul.w", mul, LSX128WOpnd>; ++ ++def VMUL_D : LSX_3R<0b01110000100001011>, ++ LSX_3R_DESC_BASE<"vmul.d", mul, LSX128DOpnd>; ++ ++ ++def VMADD_B : LSX_3R<0b01110000101010000>, ++ LSX_3R_4R_DESC_BASE<"vmadd.b", muladd, LSX128BOpnd>; ++ ++def VMADD_H : LSX_3R<0b01110000101010001>, ++ LSX_3R_4R_DESC_BASE<"vmadd.h", muladd, LSX128HOpnd>; ++ ++def VMADD_W : LSX_3R<0b01110000101010010>, ++ LSX_3R_4R_DESC_BASE<"vmadd.w", muladd, LSX128WOpnd>; ++ ++def VMADD_D : LSX_3R<0b01110000101010011>, ++ LSX_3R_4R_DESC_BASE<"vmadd.d", muladd, LSX128DOpnd>; ++ ++ ++def VMSUB_B : LSX_3R<0b01110000101010100>, ++ LSX_3R_4R_DESC_BASE<"vmsub.b", mulsub, LSX128BOpnd>; ++ ++def VMSUB_H : LSX_3R<0b01110000101010101>, ++ LSX_3R_4R_DESC_BASE<"vmsub.h", mulsub, LSX128HOpnd>; ++ ++def VMSUB_W : LSX_3R<0b01110000101010110>, ++ LSX_3R_4R_DESC_BASE<"vmsub.w", mulsub, LSX128WOpnd>; ++ ++def VMSUB_D : LSX_3R<0b01110000101010111>, ++ LSX_3R_4R_DESC_BASE<"vmsub.d", mulsub, LSX128DOpnd>; ++ ++ ++def VDIV_B : LSX_3R<0b01110000111000000>, ++ LSX_3R_DESC_BASE<"vdiv.b", sdiv, LSX128BOpnd>; ++ ++def VDIV_H : LSX_3R<0b01110000111000001>, ++ LSX_3R_DESC_BASE<"vdiv.h", sdiv, LSX128HOpnd>; ++ ++def VDIV_W : LSX_3R<0b01110000111000010>, ++ LSX_3R_DESC_BASE<"vdiv.w", sdiv, LSX128WOpnd>; ++ ++def VDIV_D : LSX_3R<0b01110000111000011>, ++ LSX_3R_DESC_BASE<"vdiv.d", sdiv, LSX128DOpnd>; ++ ++ ++def VMOD_B : LSX_3R<0b01110000111000100>, ++ LSX_3R_DESC_BASE<"vmod.b", srem, LSX128BOpnd>; ++ ++def VMOD_H : LSX_3R<0b01110000111000101>, ++ LSX_3R_DESC_BASE<"vmod.h", srem, LSX128HOpnd>; ++ ++def VMOD_W : LSX_3R<0b01110000111000110>, ++ LSX_3R_DESC_BASE<"vmod.w", srem, LSX128WOpnd>; ++ ++def VMOD_D : LSX_3R<0b01110000111000111>, ++ LSX_3R_DESC_BASE<"vmod.d", srem, LSX128DOpnd>; ++ ++ ++def VDIV_BU : LSX_3R<0b01110000111001000>, ++ LSX_3R_DESC_BASE<"vdiv.bu", udiv, LSX128BOpnd>; ++ ++def VDIV_HU : LSX_3R<0b01110000111001001>, ++ LSX_3R_DESC_BASE<"vdiv.hu", udiv, LSX128HOpnd>; ++ ++def VDIV_WU : LSX_3R<0b01110000111001010>, ++ LSX_3R_DESC_BASE<"vdiv.wu", udiv, LSX128WOpnd>; ++ ++def VDIV_DU : LSX_3R<0b01110000111001011>, ++ LSX_3R_DESC_BASE<"vdiv.du", udiv, LSX128DOpnd>; ++ ++ ++def VMOD_BU : LSX_3R<0b01110000111001100>, ++ LSX_3R_DESC_BASE<"vmod.bu", urem, LSX128BOpnd>; ++ ++def VMOD_HU : LSX_3R<0b01110000111001101>, ++ LSX_3R_DESC_BASE<"vmod.hu", urem, LSX128HOpnd>; ++ ++def VMOD_WU : LSX_3R<0b01110000111001110>, ++ LSX_3R_DESC_BASE<"vmod.wu", urem, LSX128WOpnd>; ++ ++def VMOD_DU : LSX_3R<0b01110000111001111>, ++ LSX_3R_DESC_BASE<"vmod.du", urem, LSX128DOpnd>; ++ ++ ++def VSLL_B : LSX_3R<0b01110000111010000>, ++ LSX_3R_DESC_BASE<"vsll.b", shl, LSX128BOpnd>; ++ ++def VSLL_H : LSX_3R<0b01110000111010001>, ++ LSX_3R_DESC_BASE<"vsll.h", shl, LSX128HOpnd>; ++ ++def VSLL_W : LSX_3R<0b01110000111010010>, ++ LSX_3R_DESC_BASE<"vsll.w", shl, LSX128WOpnd>; ++ ++def VSLL_D : LSX_3R<0b01110000111010011>, ++ LSX_3R_DESC_BASE<"vsll.d", shl, LSX128DOpnd>; ++ ++ ++def VSRL_B : LSX_3R<0b01110000111010100>, ++ LSX_3R_DESC_BASE<"vsrl.b", srl, LSX128BOpnd>; ++ ++def VSRL_H : LSX_3R<0b01110000111010101>, ++ LSX_3R_DESC_BASE<"vsrl.h", srl, LSX128HOpnd>; ++ ++def VSRL_W : LSX_3R<0b01110000111010110>, ++ LSX_3R_DESC_BASE<"vsrl.w", srl, LSX128WOpnd>; ++ ++def VSRL_D : LSX_3R<0b01110000111010111>, ++ LSX_3R_DESC_BASE<"vsrl.d", srl, LSX128DOpnd>; ++ ++ ++def VSRA_B : LSX_3R<0b01110000111011000>, ++ LSX_3R_DESC_BASE<"vsra.b", sra, LSX128BOpnd>; ++ ++def VSRA_H : LSX_3R<0b01110000111011001>, ++ LSX_3R_DESC_BASE<"vsra.h", sra, LSX128HOpnd>; ++ ++def VSRA_W : LSX_3R<0b01110000111011010>, ++ LSX_3R_DESC_BASE<"vsra.w", sra, LSX128WOpnd>; ++ ++def VSRA_D : LSX_3R<0b01110000111011011>, ++ LSX_3R_DESC_BASE<"vsra.d", sra, LSX128DOpnd>; ++ ++ ++def VSRLR_B : LSX_3R<0b01110000111100000>, ++ LSX_3RN_DESC_BASE<"vsrlr.b", LSX128BOpnd>; ++ ++def VSRLR_H : LSX_3R<0b01110000111100001>, ++ LSX_3RN_DESC_BASE<"vsrlr.h", LSX128HOpnd>; ++ ++def VSRLR_W : LSX_3R<0b01110000111100010>, ++ LSX_3RN_DESC_BASE<"vsrlr.w", LSX128WOpnd>; ++ ++def VSRLR_D : LSX_3R<0b01110000111100011>, ++ LSX_3RN_DESC_BASE<"vsrlr.d", LSX128DOpnd>; ++ ++ ++def VSRAR_B : LSX_3R<0b01110000111100100>, ++ LSX_3RN_DESC_BASE<"vsrar.b", LSX128BOpnd>; ++ ++def VSRAR_H : LSX_3R<0b01110000111100101>, ++ LSX_3RN_DESC_BASE<"vsrar.h", LSX128HOpnd>; ++ ++def VSRAR_W : LSX_3R<0b01110000111100110>, ++ LSX_3RN_DESC_BASE<"vsrar.w", LSX128WOpnd>; ++ ++def VSRAR_D : LSX_3R<0b01110000111100111>, ++ LSX_3RN_DESC_BASE<"vsrar.d", LSX128DOpnd>; ++ ++ ++def VBITCLR_B : LSX_3R<0b01110001000011000>, ++ LSX_3R_DESC_BASE<"vbitclr.b", vbitclr_b, LSX128BOpnd>; ++ ++def VBITCLR_H : LSX_3R<0b01110001000011001>, ++ LSX_3R_DESC_BASE<"vbitclr.h", vbitclr_h, LSX128HOpnd>; ++ ++def VBITCLR_W : LSX_3R<0b01110001000011010>, ++ LSX_3R_DESC_BASE<"vbitclr.w", vbitclr_w, LSX128WOpnd>; ++ ++def VBITCLR_D : LSX_3R<0b01110001000011011>, ++ LSX_3R_DESC_BASE<"vbitclr.d", vbitclr_d, LSX128DOpnd>; ++ ++ ++def VBITSET_B : LSX_3R<0b01110001000011100>, ++ LSX_3RN_DESC_BASE<"vbitset.b", LSX128BOpnd>; ++ ++def VBITSET_H : LSX_3R<0b01110001000011101>, ++ LSX_3RN_DESC_BASE<"vbitset.h", LSX128HOpnd>; ++ ++def VBITSET_W : LSX_3R<0b01110001000011110>, ++ LSX_3RN_DESC_BASE<"vbitset.w", LSX128WOpnd>; ++ ++def VBITSET_D : LSX_3R<0b01110001000011111>, ++ LSX_3RN_DESC_BASE<"vbitset.d", LSX128DOpnd>; ++ ++ ++def VBITREV_B : LSX_3R<0b01110001000100000>, ++ LSX_3RN_DESC_BASE<"vbitrev.b", LSX128BOpnd>; ++ ++def VBITREV_H : LSX_3R<0b01110001000100001>, ++ LSX_3RN_DESC_BASE<"vbitrev.h", LSX128HOpnd>; ++ ++def VBITREV_W : LSX_3R<0b01110001000100010>, ++ LSX_3RN_DESC_BASE<"vbitrev.w", LSX128WOpnd>; ++ ++def VBITREV_D : LSX_3R<0b01110001000100011>, ++ LSX_3RN_DESC_BASE<"vbitrev.d", LSX128DOpnd>; ++ ++ ++def VPACKEV_B : LSX_3R<0b01110001000101100>, ++ LSX_3R_DESC_BASE<"vpackev.b", LoongArchVPACKEV, LSX128BOpnd>; ++ ++def VPACKEV_H : LSX_3R<0b01110001000101101>, ++ LSX_3R_DESC_BASE<"vpackev.h", LoongArchVPACKEV, LSX128HOpnd>; ++ ++def VPACKEV_W : LSX_3R<0b01110001000101110>, ++ LSX_3R_DESC_BASE<"vpackev.w", LoongArchVPACKEV, LSX128WOpnd>; ++ ++def VPACKEV_D : LSX_3R<0b01110001000101111>, ++ LSX_3R_DESC_BASE<"vpackev.d", LoongArchVPACKEV, LSX128DOpnd>; ++ ++ ++def VPACKOD_B : LSX_3R<0b01110001000110000>, ++ LSX_3R_DESC_BASE<"vpackod.b", LoongArchVPACKOD, LSX128BOpnd>; ++ ++def VPACKOD_H : LSX_3R<0b01110001000110001>, ++ LSX_3R_DESC_BASE<"vpackod.h", LoongArchVPACKOD, LSX128HOpnd>; ++ ++def VPACKOD_W : LSX_3R<0b01110001000110010>, ++ LSX_3R_DESC_BASE<"vpackod.w", LoongArchVPACKOD, LSX128WOpnd>; ++ ++def VPACKOD_D : LSX_3R<0b01110001000110011>, ++ LSX_3R_DESC_BASE<"vpackod.d", LoongArchVPACKOD, LSX128DOpnd>; ++ ++ ++def VILVL_B : LSX_3R<0b01110001000110100>, ++ LSX_3R_DESC_BASE<"vilvl.b", LoongArchVILVL, LSX128BOpnd>; ++ ++def VILVL_H : LSX_3R<0b01110001000110101>, ++ LSX_3R_DESC_BASE<"vilvl.h", LoongArchVILVL, LSX128HOpnd>; ++ ++def VILVL_W : LSX_3R<0b01110001000110110>, ++ LSX_3R_DESC_BASE<"vilvl.w", LoongArchVILVL, LSX128WOpnd>; ++ ++def VILVL_D : LSX_3R<0b01110001000110111>, ++ LSX_3R_DESC_BASE<"vilvl.d", LoongArchVILVL, LSX128DOpnd>; ++ ++ ++def VILVH_B : LSX_3R<0b01110001000111000>, ++ LSX_3R_DESC_BASE<"vilvh.b", LoongArchVILVH, LSX128BOpnd>; ++ ++def VILVH_H : LSX_3R<0b01110001000111001>, ++ LSX_3R_DESC_BASE<"vilvh.h", LoongArchVILVH, LSX128HOpnd>; ++ ++def VILVH_W : LSX_3R<0b01110001000111010>, ++ LSX_3R_DESC_BASE<"vilvh.w", LoongArchVILVH, LSX128WOpnd>; ++ ++def VILVH_D : LSX_3R<0b01110001000111011>, ++ LSX_3R_DESC_BASE<"vilvh.d", LoongArchVILVH, LSX128DOpnd>; ++ ++ ++def VPICKEV_B : LSX_3R<0b01110001000111100>, ++ LSX_3R_DESC_BASE<"vpickev.b", LoongArchVPICKEV, LSX128BOpnd>; ++ ++def VPICKEV_H : LSX_3R<0b01110001000111101>, ++ LSX_3R_DESC_BASE<"vpickev.h", LoongArchVPICKEV, LSX128HOpnd>; ++ ++def VPICKEV_W : LSX_3R<0b01110001000111110>, ++ LSX_3R_DESC_BASE<"vpickev.w", LoongArchVPICKEV, LSX128WOpnd>; ++ ++def VPICKEV_D : LSX_3R<0b01110001000111111>, ++ LSX_3R_DESC_BASE<"vpickev.d", LoongArchVPICKEV, LSX128DOpnd>; ++ ++ ++def VPICKOD_B : LSX_3R<0b01110001001000000>, ++ LSX_3R_DESC_BASE<"vpickod.b", LoongArchVPICKOD, LSX128BOpnd>; ++ ++def VPICKOD_H : LSX_3R<0b01110001001000001>, ++ LSX_3R_DESC_BASE<"vpickod.h", LoongArchVPICKOD, LSX128HOpnd>; ++ ++def VPICKOD_W : LSX_3R<0b01110001001000010>, ++ LSX_3R_DESC_BASE<"vpickod.w", LoongArchVPICKOD, LSX128WOpnd>; ++ ++def VPICKOD_D : LSX_3R<0b01110001001000011>, ++ LSX_3R_DESC_BASE<"vpickod.d", LoongArchVPICKOD, LSX128DOpnd>; ++ ++ ++def VREPLVE_B : LSX_3R_1GP<0b01110001001000100>, ++ LSX_3R_VREPLVE_DESC_BASE<"vreplve.b", vsplati8_elt, LSX128BOpnd>; ++ ++def VREPLVE_H : LSX_3R_1GP<0b01110001001000101>, ++ LSX_3R_VREPLVE_DESC_BASE<"vreplve.h", vsplati16_elt, LSX128HOpnd>; ++ ++def VREPLVE_W : LSX_3R_1GP<0b01110001001000110>, ++ LSX_3R_VREPLVE_DESC_BASE<"vreplve.w", vsplati32_elt, LSX128WOpnd>; ++ ++def VREPLVE_D : LSX_3R_1GP<0b01110001001000111>, ++ LSX_3R_VREPLVE_DESC_BASE<"vreplve.d", vsplati64_elt, LSX128DOpnd>; ++ ++ ++def VAND_V : LSX_3R<0b01110001001001100>, ++ LSX_VEC_DESC_BASE<"vand.v", and, LSX128BOpnd>; ++class AND_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class AND_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class AND_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++ ++def AND_V_H_PSEUDO : AND_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def AND_V_W_PSEUDO : AND_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def AND_V_D_PSEUDO : AND_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(VAND_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++ ++def VOR_V : LSX_3R<0b01110001001001101>, ++ LSX_VEC_DESC_BASE<"vor.v", or, LSX128BOpnd>; ++class OR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class OR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class OR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++ ++def OR_V_H_PSEUDO : OR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def OR_V_W_PSEUDO : OR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def OR_V_D_PSEUDO : OR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(VOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++ ++def VXOR_V : LSX_3R<0b01110001001001110>, ++ LSX_VEC_DESC_BASE<"vxor.v", xor, LSX128BOpnd>; ++class XOR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class XOR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class XOR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++ ++def XOR_V_H_PSEUDO : XOR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def XOR_V_W_PSEUDO : XOR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def XOR_V_D_PSEUDO : XOR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(VXOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++ ++def VNOR_V : LSX_3R<0b01110001001001111>, ++ LSX_VEC_DESC_BASE<"vnor.v", LoongArchVNOR, LSX128BOpnd>; ++class NOR_V_H_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class NOR_V_W_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++class NOR_V_D_PSEUDO_DESC : LSX_VEC_PSEUDO_BASE; ++ ++def NOR_V_H_PSEUDO : NOR_V_H_PSEUDO_DESC, ++ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def NOR_V_W_PSEUDO : NOR_V_W_PSEUDO_DESC, ++ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++def NOR_V_D_PSEUDO : NOR_V_D_PSEUDO_DESC, ++ PseudoInstExpansion<(VNOR_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++ ++def VFADD_S : LSX_3R<0b01110001001100001>, IsCommutable, ++ LSX_3RF_DESC_BASE<"vfadd.s", fadd, LSX128WOpnd>; ++ ++def VFADD_D : LSX_3R<0b01110001001100010>, IsCommutable, ++ LSX_3RF_DESC_BASE<"vfadd.d", fadd, LSX128DOpnd>; ++ ++ ++def VFSUB_S : LSX_3R<0b01110001001100101>, ++ LSX_3RF_DESC_BASE<"vfsub.s", fsub, LSX128WOpnd>; ++ ++def VFSUB_D : LSX_3R<0b01110001001100110>, ++ LSX_3RF_DESC_BASE<"vfsub.d", fsub, LSX128DOpnd>; ++ ++ ++def VFMUL_S : LSX_3R<0b01110001001110001>, ++ LSX_3RF_DESC_BASE<"vfmul.s", fmul, LSX128WOpnd>; ++ ++def VFMUL_D : LSX_3R<0b01110001001110010>, ++ LSX_3RF_DESC_BASE<"vfmul.d", fmul, LSX128DOpnd>; ++ ++ ++def VFDIV_S : LSX_3R<0b01110001001110101>, ++ LSX_3RF_DESC_BASE<"vfdiv.s", fdiv, LSX128WOpnd>; ++ ++def VFDIV_D : LSX_3R<0b01110001001110110>, ++ LSX_3RF_DESC_BASE<"vfdiv.d", fdiv, LSX128DOpnd>; ++ ++ ++def VFMAX_S : LSX_3R<0b01110001001111001>, ++ LSX_3RFN_DESC_BASE<"vfmax.s", LSX128WOpnd>; ++ ++def VFMAX_D : LSX_3R<0b01110001001111010>, ++ LSX_3RFN_DESC_BASE<"vfmax.d", LSX128DOpnd>; ++ ++ ++def VFMIN_S : LSX_3R<0b01110001001111101>, ++ LSX_3RFN_DESC_BASE<"vfmin.s", LSX128WOpnd>; ++ ++def VFMIN_D : LSX_3R<0b01110001001111110>, ++ LSX_3RFN_DESC_BASE<"vfmin.d", LSX128DOpnd>; ++ ++ ++def VFMAXA_S : LSX_3R<0b01110001010000001>, ++ LSX_3RFN_DESC_BASE<"vfmaxa.s", LSX128WOpnd>; ++ ++def VFMAXA_D : LSX_3R<0b01110001010000010>, ++ LSX_3RFN_DESC_BASE<"vfmaxa.d", LSX128DOpnd>; ++ ++ ++def VFMINA_S : LSX_3R<0b01110001010000101>, ++ LSX_3RFN_DESC_BASE<"vfmina.s", LSX128WOpnd>; ++ ++def VFMINA_D : LSX_3R<0b01110001010000110>, ++ LSX_3RFN_DESC_BASE<"vfmina.d", LSX128DOpnd>; ++ ++ ++def VSHUF_H : LSX_3R<0b01110001011110101>, ++ LSX_3R_VSHF_DESC_BASE<"vshuf.h", LSX128HOpnd>; ++ ++def VSHUF_W : LSX_3R<0b01110001011110110>, ++ LSX_3R_VSHF_DESC_BASE<"vshuf.w", LSX128WOpnd>; ++ ++def VSHUF_D : LSX_3R<0b01110001011110111>, ++ LSX_3R_VSHF_DESC_BASE<"vshuf.d", LSX128DOpnd>; ++ ++ ++def VSEQI_B : LSX_I5<0b01110010100000000>, ++ LSX_I5_DESC_BASE_Intrinsic<"vseqi.b", int_loongarch_lsx_vseqi_b, simm5_32, immSExt5, LSX128BOpnd>; ++ ++def VSEQI_H : LSX_I5<0b01110010100000001>, ++ LSX_I5_DESC_BASE_Intrinsic<"vseqi.h", int_loongarch_lsx_vseqi_h, simm5_32, immSExt5, LSX128HOpnd>; ++ ++def VSEQI_W : LSX_I5<0b01110010100000010>, ++ LSX_I5_DESC_BASE_Intrinsic<"vseqi.w", int_loongarch_lsx_vseqi_w, simm5_32, immSExt5, LSX128WOpnd>; ++ ++def VSEQI_D : LSX_I5<0b01110010100000011>, ++ LSX_I5_DESC_BASE_Intrinsic<"vseqi.d", int_loongarch_lsx_vseqi_d, simm5_32, immSExt5, LSX128DOpnd>; ++ ++ ++def VSLEI_B : LSX_I5<0b01110010100000100>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslei.b", int_loongarch_lsx_vslei_b, simm5_32, immSExt5, LSX128BOpnd>; ++ ++def VSLEI_H : LSX_I5<0b01110010100000101>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslei.h", int_loongarch_lsx_vslei_h, simm5_32, immSExt5, LSX128HOpnd>; ++ ++def VSLEI_W : LSX_I5<0b01110010100000110>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslei.w", int_loongarch_lsx_vslei_w, simm5_32, immSExt5, LSX128WOpnd>; ++ ++def VSLEI_D : LSX_I5<0b01110010100000111>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslei.d", int_loongarch_lsx_vslei_d, simm5_32, immSExt5, LSX128DOpnd>; ++ ++ ++def VSLEI_BU : LSX_I5_U<0b01110010100001000>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.bu", int_loongarch_lsx_vslei_bu, uimm5, immZExt5, LSX128BOpnd>; ++ ++def VSLEI_HU : LSX_I5_U<0b01110010100001001>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.hu", int_loongarch_lsx_vslei_hu, uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSLEI_WU : LSX_I5_U<0b01110010100001010>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.wu", int_loongarch_lsx_vslei_wu, uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSLEI_DU : LSX_I5_U<0b01110010100001011>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslei.du", int_loongarch_lsx_vslei_du, uimm5, immZExt5, LSX128DOpnd>; ++ ++ ++def VSLTI_B : LSX_I5<0b01110010100001100>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslti.b", int_loongarch_lsx_vslti_b, simm5_32, immSExt5, LSX128BOpnd>; ++ ++def VSLTI_H : LSX_I5<0b01110010100001101>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslti.h", int_loongarch_lsx_vslti_h, simm5_32, immSExt5, LSX128HOpnd>; ++ ++def VSLTI_W : LSX_I5<0b01110010100001110>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslti.w", int_loongarch_lsx_vslti_w, simm5_32, immSExt5, LSX128WOpnd>; ++ ++def VSLTI_D : LSX_I5<0b01110010100001111>, ++ LSX_I5_DESC_BASE_Intrinsic<"vslti.d", int_loongarch_lsx_vslti_d, simm5_32, immSExt5, LSX128DOpnd>; ++ ++ ++def VSLTI_BU : LSX_I5_U<0b01110010100010000>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.bu", int_loongarch_lsx_vslti_bu, uimm5, immZExt5, LSX128BOpnd>; ++ ++def VSLTI_HU : LSX_I5_U<0b01110010100010001>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.hu", int_loongarch_lsx_vslti_hu, uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSLTI_WU : LSX_I5_U<0b01110010100010010>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.wu", int_loongarch_lsx_vslti_wu, uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSLTI_DU : LSX_I5_U<0b01110010100010011>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vslti.du", int_loongarch_lsx_vslti_du, uimm5, immZExt5, LSX128DOpnd>; ++ ++ ++def VADDI_BU : LSX_I5_U<0b01110010100010100>, ++ LSX_I5_U_DESC_BASE<"vaddi.bu", add, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VADDI_HU : LSX_I5_U<0b01110010100010101>, ++ LSX_I5_U_DESC_BASE<"vaddi.hu", add, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VADDI_WU : LSX_I5_U<0b01110010100010110>, ++ LSX_I5_U_DESC_BASE<"vaddi.wu", add, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VADDI_DU : LSX_I5_U<0b01110010100010111>, ++ LSX_I5_U_DESC_BASE<"vaddi.du", add, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VSUBI_BU : LSX_I5_U<0b01110010100011000>, ++ LSX_I5_U_DESC_BASE<"vsubi.bu", sub, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VSUBI_HU : LSX_I5_U<0b01110010100011001>, ++ LSX_I5_U_DESC_BASE<"vsubi.hu", sub, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VSUBI_WU : LSX_I5_U<0b01110010100011010>, ++ LSX_I5_U_DESC_BASE<"vsubi.wu", sub, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSUBI_DU : LSX_I5_U<0b01110010100011011>, ++ LSX_I5_U_DESC_BASE<"vsubi.du", sub, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VMAXI_B : LSX_I5<0b01110010100100000>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.b", int_loongarch_lsx_vmaxi_b, simm5_32, immSExt5, LSX128BOpnd>; ++ ++def VMAXI_H : LSX_I5<0b01110010100100001>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.h", int_loongarch_lsx_vmaxi_h, simm5_32, immSExt5, LSX128HOpnd>; ++ ++def VMAXI_W : LSX_I5<0b01110010100100010>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.w", int_loongarch_lsx_vmaxi_w, simm5_32, immSExt5, LSX128WOpnd>; ++ ++def VMAXI_D : LSX_I5<0b01110010100100011>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmaxi.d", int_loongarch_lsx_vmaxi_d, simm5_32, immSExt5, LSX128DOpnd>; ++ ++ ++def VMINI_B : LSX_I5<0b01110010100100100>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmini.b", int_loongarch_lsx_vmini_b, simm5_32, immSExt5, LSX128BOpnd>; ++ ++def VMINI_H : LSX_I5<0b01110010100100101>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmini.h", int_loongarch_lsx_vmini_h, simm5_32, immSExt5, LSX128HOpnd>; ++ ++def VMINI_W : LSX_I5<0b01110010100100110>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmini.w", int_loongarch_lsx_vmini_w, simm5_32, immSExt5, LSX128WOpnd>; ++ ++def VMINI_D : LSX_I5<0b01110010100100111>, ++ LSX_I5_DESC_BASE_Intrinsic<"vmini.d", int_loongarch_lsx_vmini_d, simm5_32, immSExt5, LSX128DOpnd>; ++ ++ ++def VMAXI_BU : LSX_I5_U<0b01110010100101000>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.bu", int_loongarch_lsx_vmaxi_bu, uimm5, immZExt5, LSX128BOpnd>; ++ ++def VMAXI_HU : LSX_I5_U<0b01110010100101001>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.hu", int_loongarch_lsx_vmaxi_hu, uimm5, immZExt5, LSX128HOpnd>; ++ ++def VMAXI_WU : LSX_I5_U<0b01110010100101010>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.wu", int_loongarch_lsx_vmaxi_wu, uimm5, immZExt5, LSX128WOpnd>; ++ ++def VMAXI_DU : LSX_I5_U<0b01110010100101011>, ++ LSX_I5_U_DESC_BASE_Intrinsic<"vmaxi.du", int_loongarch_lsx_vmaxi_du, uimm5, immZExt5, LSX128DOpnd>; ++ ++ ++def VMINI_BU : LSX_I5_U<0b01110010100101100>, ++ LSX_I5_U_DESC_BASE<"vmini.bu", umin, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VMINI_HU : LSX_I5_U<0b01110010100101101>, ++ LSX_I5_U_DESC_BASE<"vmini.hu", umin, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VMINI_WU : LSX_I5_U<0b01110010100101110>, ++ LSX_I5_U_DESC_BASE<"vmini.wu", umin, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VMINI_DU : LSX_I5_U<0b01110010100101111>, ++ LSX_I5_U_DESC_BASE<"vmini.du", umin, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VCLO_B : LSX_2R<0b0111001010011100000000>, ++ LSX_2RN_DESC_BASE<"vclo.b", LSX128BOpnd>; ++ ++def VCLO_H : LSX_2R<0b0111001010011100000001>, ++ LSX_2RN_DESC_BASE<"vclo.h", LSX128HOpnd>; ++ ++def VCLO_W : LSX_2R<0b0111001010011100000010>, ++ LSX_2RN_DESC_BASE<"vclo.w", LSX128WOpnd>; ++ ++def VCLO_D : LSX_2R<0b0111001010011100000011>, ++ LSX_2RN_DESC_BASE<"vclo.d", LSX128DOpnd>; ++ ++ ++def VCLZ_B : LSX_2R<0b0111001010011100000100>, ++ LSX_2R_DESC_BASE<"vclz.b", ctlz, LSX128BOpnd>; ++ ++def VCLZ_H : LSX_2R<0b0111001010011100000101>, ++ LSX_2R_DESC_BASE<"vclz.h", ctlz, LSX128HOpnd>; ++ ++def VCLZ_W : LSX_2R<0b0111001010011100000110>, ++ LSX_2R_DESC_BASE<"vclz.w", ctlz, LSX128WOpnd>; ++ ++def VCLZ_D : LSX_2R<0b0111001010011100000111>, ++ LSX_2R_DESC_BASE<"vclz.d", ctlz, LSX128DOpnd>; ++ ++ ++def VPCNT_B : LSX_2R<0b0111001010011100001000>, ++ LSX_2R_DESC_BASE<"vpcnt.b", ctpop, LSX128BOpnd>; ++ ++def VPCNT_H : LSX_2R<0b0111001010011100001001>, ++ LSX_2R_DESC_BASE<"vpcnt.h", ctpop, LSX128HOpnd>; ++ ++def VPCNT_W : LSX_2R<0b0111001010011100001010>, ++ LSX_2R_DESC_BASE<"vpcnt.w", ctpop, LSX128WOpnd>; ++ ++def VPCNT_D : LSX_2R<0b0111001010011100001011>, ++ LSX_2R_DESC_BASE<"vpcnt.d", ctpop, LSX128DOpnd>; ++ ++ ++def VFLOGB_S : LSX_2R<0b0111001010011100110001>, ++ LSX_2RFN_DESC_BASE<"vflogb.s", LSX128WOpnd>; ++ ++def VFLOGB_D : LSX_2R<0b0111001010011100110010>, ++ LSX_2RFN_DESC_BASE<"vflogb.d", LSX128DOpnd>; ++ ++ ++def VFCLASS_S : LSX_2R<0b0111001010011100110101>, ++ LSX_2RFN_DESC_BASE<"vfclass.s", LSX128WOpnd>; ++ ++def VFCLASS_D : LSX_2R<0b0111001010011100110110>, ++ LSX_2RFN_DESC_BASE<"vfclass.d", LSX128DOpnd>; ++ ++ ++def VFSQRT_S : LSX_2R<0b0111001010011100111001>, ++ LSX_2RF_DESC_BASE<"vfsqrt.s", fsqrt, LSX128WOpnd>; ++ ++def VFSQRT_D : LSX_2R<0b0111001010011100111010>, ++ LSX_2RF_DESC_BASE<"vfsqrt.d", fsqrt, LSX128DOpnd>; ++ ++ ++def VFRECIP_S : LSX_2R<0b0111001010011100111101>, ++ LSX_2RFN_DESC_BASE<"vfrecip.s", LSX128WOpnd>; ++ ++def VFRECIP_D : LSX_2R<0b0111001010011100111110>, ++ LSX_2RFN_DESC_BASE<"vfrecip.d", LSX128DOpnd>; ++ ++ ++def VFRSQRT_S : LSX_2R<0b0111001010011101000001>, ++ LSX_2RFN_DESC_BASE<"vfrsqrt.s", LSX128WOpnd>; ++ ++def VFRSQRT_D : LSX_2R<0b0111001010011101000010>, ++ LSX_2RFN_DESC_BASE<"vfrsqrt.d", LSX128DOpnd>; ++ ++ ++def VFRINT_S : LSX_2R<0b0111001010011101001101>, ++ LSX_2RF_DESC_BASE<"vfrint.s", frint, LSX128WOpnd>; ++ ++def VFRINT_D : LSX_2R<0b0111001010011101001110>, ++ LSX_2RF_DESC_BASE<"vfrint.d", frint, LSX128DOpnd>; ++ ++ ++def VFCVTL_S_H : LSX_2R<0b0111001010011101111010>, ++ LSX_2RFN_DESC_BASE_CVT<"vfcvtl.s.h", LSX128WOpnd, LSX128HOpnd>; ++ ++def VFCVTH_S_H : LSX_2R<0b0111001010011101111011>, ++ LSX_2RFN_DESC_BASE_CVT<"vfcvth.s.h", LSX128WOpnd, LSX128HOpnd>; ++ ++ ++def VFCVTL_D_S : LSX_2R<0b0111001010011101111100>, ++ LSX_2RFN_DESC_BASE_CVT<"vfcvtl.d.s", LSX128DOpnd, LSX128WOpnd>; ++ ++def VFCVTH_D_S : LSX_2R<0b0111001010011101111101>, ++ LSX_2RFN_DESC_BASE_CVT<"vfcvth.d.s", LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFFINT_S_W : LSX_2R<0b0111001010011110000000>, ++ LSX_2RF_DESC_BASE<"vffint.s.w", sint_to_fp, LSX128WOpnd>; ++ ++def VFFINT_S_WU : LSX_2R<0b0111001010011110000001>, ++ LSX_2RF_DESC_BASE<"vffint.s.wu", uint_to_fp, LSX128WOpnd>; ++ ++ ++def VFFINT_D_L : LSX_2R<0b0111001010011110000010>, ++ LSX_2RF_DESC_BASE<"vffint.d.l", sint_to_fp, LSX128DOpnd>; ++ ++def VFFINT_D_LU : LSX_2R<0b0111001010011110000011>, ++ LSX_2RF_DESC_BASE<"vffint.d.lu", uint_to_fp, LSX128DOpnd>; ++ ++ ++def VFTINT_W_S : LSX_2R<0b0111001010011110001100>, ++ LSX_2RFN_DESC_BASE<"vftint.w.s", LSX128WOpnd>; ++ ++def VFTINT_L_D : LSX_2R<0b0111001010011110001101>, ++ LSX_2RFN_DESC_BASE<"vftint.l.d", LSX128DOpnd>; ++ ++ ++def VFTINT_WU_S : LSX_2R<0b0111001010011110010110>, ++ LSX_2RFN_DESC_BASE<"vftint.wu.s", LSX128WOpnd>; ++ ++def VFTINT_LU_D : LSX_2R<0b0111001010011110010111>, ++ LSX_2RFN_DESC_BASE<"vftint.lu.d", LSX128DOpnd>; ++ ++ ++def VFTINTRZ_WU_S : LSX_2R<0b0111001010011110011100>, ++ LSX_2RF_DESC_BASE<"vftintrz.wu.s", fp_to_uint, LSX128WOpnd>; ++ ++def VFTINTRZ_LU_D : LSX_2R<0b0111001010011110011101>, ++ LSX_2RF_DESC_BASE<"vftintrz.lu.d", fp_to_uint, LSX128DOpnd>; ++ ++ ++def VREPLGR2VR_B : LSX_2R_1GP<0b0111001010011111000000>, ++ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.b", v16i8, vsplati8, LSX128BOpnd, GPR32Opnd>; ++ ++def VREPLGR2VR_H : LSX_2R_1GP<0b0111001010011111000001>, ++ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.h", v8i16, vsplati16, LSX128HOpnd, GPR32Opnd>; ++ ++def VREPLGR2VR_W : LSX_2R_1GP<0b0111001010011111000010>, ++ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.w", v4i32, vsplati32, LSX128WOpnd, GPR32Opnd>; ++ ++def VREPLGR2VR_D : LSX_2R_1GP<0b0111001010011111000011>, ++ LSX_2R_REPL_DESC_BASE<"vreplgr2vr.d", v2i64, vsplati64, LSX128DOpnd, GPR64Opnd>; ++ ++ ++class LSX_2R_FILL_PSEUDO_BASE : ++ LSXPseudo<(outs RCVD:$vd), (ins RCVS:$fs), ++ [(set RCVD:$vd, (OpNode RCVS:$fs))]> { ++ let usesCustomInserter = 1; ++} ++ ++class FILL_FW_PSEUDO_DESC : LSX_2R_FILL_PSEUDO_BASE; ++class FILL_FD_PSEUDO_DESC : LSX_2R_FILL_PSEUDO_BASE; ++ ++def FILL_FW_PSEUDO : FILL_FW_PSEUDO_DESC; ++def FILL_FD_PSEUDO : FILL_FD_PSEUDO_DESC; ++ ++ ++def VSRLRI_B : LSX_I3_U<0b0111001010100100001>, ++ LSX_BIT_3N_DESC_BASE<"vsrlri.b", uimm3, immZExt3, LSX128BOpnd>; ++ ++def VSRLRI_H : LSX_I4_U<0b011100101010010001>, ++ LSX_BIT_4N_DESC_BASE<"vsrlri.h", uimm4, immZExt4, LSX128HOpnd>; ++ ++def VSRLRI_W : LSX_I5_U<0b01110010101001001>, ++ LSX_BIT_5N_DESC_BASE<"vsrlri.w", uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSRLRI_D : LSX_I6_U<0b0111001010100101>, ++ LSX_BIT_6N_DESC_BASE<"vsrlri.d", uimm6, immZExt6, LSX128DOpnd>; ++ ++ ++def VSRARI_B : LSX_I3_U<0b0111001010101000001>, ++ LSX_BIT_3N_DESC_BASE<"vsrari.b", uimm3, immZExt3, LSX128BOpnd>; ++ ++def VSRARI_H : LSX_I4_U<0b011100101010100001>, ++ LSX_BIT_4N_DESC_BASE<"vsrari.h", uimm4, immZExt4, LSX128HOpnd>; ++ ++def VSRARI_W : LSX_I5_U<0b01110010101010001>, ++ LSX_BIT_5N_DESC_BASE<"vsrari.w", uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSRARI_D : LSX_I6_U<0b0111001010101001>, ++ LSX_BIT_6N_DESC_BASE<"vsrari.d", uimm6, immZExt6, LSX128DOpnd>; ++ ++ ++def VINSGR2VR_B : LSX_I4_R_U<0b011100101110101110>, ++ LSX_INSERT_U4_DESC_BASE<"vinsgr2vr.b", vinsert_v16i8, uimm4, immZExt4Ptr, LSX128BOpnd, GPR32Opnd>; ++ ++def VINSGR2VR_H : LSX_I3_R_U<0b0111001011101011110>, ++ LSX_INSERT_U3_DESC_BASE<"vinsgr2vr.h", vinsert_v8i16, uimm3, immZExt3Ptr, LSX128HOpnd, GPR32Opnd>; ++ ++def VINSGR2VR_W : LSX_I2_R_U<0b01110010111010111110>, ++ LSX_INSERT_U2_DESC_BASE<"vinsgr2vr.w", vinsert_v4i32, uimm2, immZExt2Ptr, LSX128WOpnd, GPR32Opnd>; ++ ++def VINSGR2VR_D : LSX_I1_R_U<0b011100101110101111110>, ++ LSX_INSERT_U1_DESC_BASE<"vinsgr2vr.d", vinsert_v2i64, uimm1, immZExt1Ptr, LSX128DOpnd, GPR64Opnd>; ++ ++ ++def VPICKVE2GR_B : LSX_ELM_COPY_B<0b011100101110111110>, ++ LSX_PICK_U4_DESC_BASE<"vpickve2gr.b", vextract_sext_i8, v16i8, uimm4_ptr, immZExt4Ptr, GPR32Opnd, LSX128BOpnd>; ++ ++def VPICKVE2GR_H : LSX_ELM_COPY_H<0b0111001011101111110>, ++ LSX_PICK_U3_DESC_BASE<"vpickve2gr.h", vextract_sext_i16, v8i16, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LSX128HOpnd>; ++ ++def VPICKVE2GR_W : LSX_ELM_COPY_W<0b01110010111011111110>, ++ LSX_PICK_U2_DESC_BASE<"vpickve2gr.w", vextract_sext_i32, v4i32, uimm2_ptr, immZExt2Ptr, GPR32Opnd, LSX128WOpnd>; ++ ++def VPICKVE2GR_D : LSX_ELM_COPY_D<0b011100101110111111110>, ++ LSX_PICK_U1_DESC_BASE<"vpickve2gr.d", vextract_sext_i64, v2i64, uimm1_ptr, immZExt1Ptr, GPR64Opnd, LSX128DOpnd>; ++ ++ ++def VPICKVE2GR_BU : LSX_ELM_COPY_B<0b011100101111001110>, ++ LSX_PICK_U4_DESC_BASE<"vpickve2gr.bu", vextract_zext_i8, v16i8, uimm4_ptr, immZExt4Ptr, GPR32Opnd, LSX128BOpnd>; ++ ++def VPICKVE2GR_HU : LSX_ELM_COPY_H<0b0111001011110011110>, ++ LSX_PICK_U3_DESC_BASE<"vpickve2gr.hu", vextract_zext_i16, v8i16, uimm3_ptr, immZExt3Ptr, GPR32Opnd, LSX128HOpnd>; ++ ++def VPICKVE2GR_WU : LSX_ELM_COPY_W<0b01110010111100111110>, ++ LSX_PICK_U2_DESC_BASE<"vpickve2gr.wu", vextract_zext_i32, v4i32, uimm2_ptr, immZExt2Ptr, GPR32Opnd, LSX128WOpnd>; ++ ++def VPICKVE2GR_DU : LSX_ELM_COPY_D<0b011100101111001111110>, ++ LSX_PICK_U1_DESC_BASE<"vpickve2gr.du", int_loongarch_lsx_vpickve2gr_du, v2i64, uimm1, immZExt1, GPR64Opnd, LSX128DOpnd>; ++ ++ ++def : LSXPat<(vextract_zext_i64 (v2i64 LSX128D:$vj), immZExt1Ptr:$idx), ++ (VPICKVE2GR_D LSX128D:$vj, immZExt1:$idx)>; ++def : LSXPat<(vextract_zext_i64 (v2f64 LSX128D:$vj), immZExt1Ptr:$idx), ++ (VPICKVE2GR_D LSX128D:$vj, immZExt1:$idx)>; ++ ++ ++def VREPLVEI_B : LSX_I4_U<0b011100101111011110>, ++ LSX_ELM_U4_VREPLVE_DESC_BASE<"vreplvei.b", vsplati8_uimm4, LSX128BOpnd>; ++ ++def VREPLVEI_H : LSX_I3_U<0b0111001011110111110>, ++ LSX_ELM_U3_VREPLVE_DESC_BASE<"vreplvei.h", vsplati16_uimm3, LSX128HOpnd>; ++ ++def VREPLVEI_W : LSX_I2_U<0b01110010111101111110>, ++ LSX_ELM_U2_VREPLVE_DESC_BASE<"vreplvei.w", vsplati32_uimm2, LSX128WOpnd>; ++ ++def VREPLVEI_D : LSX_I1_U<0b011100101111011111110>, ++ LSX_ELM_U1_VREPLVE_DESC_BASE<"vreplvei.d", vsplati64_uimm1, LSX128DOpnd>; ++ ++ ++def VSAT_B : LSX_I3_U<0b0111001100100100001>, ++ LSX_BIT_3N_DESC_BASE<"vsat.b", uimm3, immZExt3, LSX128BOpnd>; ++ ++def VSAT_H : LSX_I4_U<0b011100110010010001>, ++ LSX_BIT_4N_DESC_BASE<"vsat.h", uimm4, immZExt4, LSX128HOpnd>; ++ ++def VSAT_W : LSX_I5_U<0b01110011001001001>, ++ LSX_BIT_5N_DESC_BASE<"vsat.w", uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSAT_D : LSX_I6_U<0b0111001100100101>, ++ LSX_BIT_6N_DESC_BASE<"vsat.d", uimm6, immZExt6, LSX128DOpnd>; ++ ++ ++def VSAT_BU : LSX_I3_U<0b0111001100101000001>, ++ LSX_BIT_3N_DESC_BASE<"vsat.bu", uimm3, immZExt3, LSX128BOpnd>; ++ ++def VSAT_HU : LSX_I4_U<0b011100110010100001>, ++ LSX_BIT_4N_DESC_BASE<"vsat.hu", uimm4, immZExt4, LSX128HOpnd>; ++ ++def VSAT_WU : LSX_I5_U<0b01110011001010001>, ++ LSX_BIT_5N_DESC_BASE<"vsat.wu", uimm5, immZExt5, LSX128WOpnd>; ++ ++def VSAT_DU : LSX_I6_U<0b0111001100101001>, ++ LSX_BIT_6N_DESC_BASE<"vsat.du", uimm6, immZExt6, LSX128DOpnd>; ++ ++ ++def VSLLI_B : LSX_I3_U<0b0111001100101100001>, ++ LSX_BIT_U3_VREPLVE_DESC_BASE<"vslli.b", shl, vsplati8_uimm3, LSX128BOpnd>; ++ ++def VSLLI_H : LSX_I4_U<0b011100110010110001>, ++ LSX_BIT_U4_VREPLVE_DESC_BASE<"vslli.h", shl, vsplati16_uimm4, LSX128HOpnd>; ++ ++def VSLLI_W : LSX_I5_U<0b01110011001011001>, ++ LSX_BIT_U5_VREPLVE_DESC_BASE<"vslli.w", shl, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSLLI_D : LSX_I6_U<0b0111001100101101>, ++ LSX_BIT_U6_VREPLVE_DESC_BASE<"vslli.d", shl, vsplati64_uimm6, LSX128DOpnd>; ++ ++ ++def VSRLI_B : LSX_I3_U<0b0111001100110000001>, ++ LSX_BIT_U3_VREPLVE_DESC_BASE<"vsrli.b", srl, vsplati8_uimm3, LSX128BOpnd>; ++ ++def VSRLI_H : LSX_I4_U<0b011100110011000001>, ++ LSX_BIT_U4_VREPLVE_DESC_BASE<"vsrli.h", srl, vsplati16_uimm4, LSX128HOpnd>; ++ ++def VSRLI_W : LSX_I5_U<0b01110011001100001>, ++ LSX_BIT_U5_VREPLVE_DESC_BASE<"vsrli.w", srl, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSRLI_D : LSX_I6_U<0b0111001100110001>, ++ LSX_BIT_U6_VREPLVE_DESC_BASE<"vsrli.d", srl, vsplati64_uimm6, LSX128DOpnd>; ++ ++ ++def VSRAI_B : LSX_I3_U<0b0111001100110100001>, ++ LSX_BIT_U3_VREPLVE_DESC_BASE_Intrinsic<"vsrai.b", int_loongarch_lsx_vsrai_b, LSX128BOpnd>; ++ ++def VSRAI_H : LSX_I4_U<0b011100110011010001>, ++ LSX_BIT_U4_VREPLVE_DESC_BASE_Intrinsic<"vsrai.h", int_loongarch_lsx_vsrai_h, LSX128HOpnd>; ++ ++def VSRAI_W : LSX_I5_U<0b01110011001101001>, ++ LSX_BIT_U5_VREPLVE_DESC_BASE_Intrinsic<"vsrai.w", int_loongarch_lsx_vsrai_w, LSX128WOpnd>; ++ ++def VSRAI_D : LSX_I6_U<0b0111001100110101>, ++ LSX_BIT_U6_VREPLVE_DESC_BASE_Intrinsic<"vsrai.d", int_loongarch_lsx_vsrai_d, LSX128DOpnd>; ++ ++ ++def VSHUF4I_B : LSX_I8_U<0b01110011100100>, ++ LSX_I8_SHF_DESC_BASE<"vshuf4i.b", LSX128BOpnd>; ++ ++def VSHUF4I_H : LSX_I8_U<0b01110011100101>, ++ LSX_I8_SHF_DESC_BASE<"vshuf4i.h", LSX128HOpnd>; ++ ++def VSHUF4I_W : LSX_I8_U<0b01110011100110>, ++ LSX_I8_SHF_DESC_BASE<"vshuf4i.w", LSX128WOpnd>; ++ ++def VSHUF4I_D : LSX_I8_U<0b01110011100111>, ++ LSX_I8_SHUF_DESC_BASE_D<"vshuf4i.d", int_loongarch_lsx_vshuf4i_d, LSX128DOpnd>; ++ ++ ++def VROTR_B : LSX_3R<0b01110000111011100>, ++ LSX_3R_DESC_BASE<"vrotr.b", LoongArchVROR, LSX128BOpnd>; ++ ++def VROTR_H : LSX_3R<0b01110000111011101>, ++ LSX_3R_DESC_BASE<"vrotr.h", LoongArchVROR, LSX128HOpnd>; ++ ++def VROTR_W : LSX_3R<0b01110000111011110>, ++ LSX_3R_DESC_BASE<"vrotr.w", LoongArchVROR, LSX128WOpnd>; ++ ++def VROTR_D : LSX_3R<0b01110000111011111>, ++ LSX_3R_DESC_BASE<"vrotr.d", LoongArchVROR, LSX128DOpnd>; ++ ++ ++def VMSKLTZ_B : LSX_2R<0b0111001010011100010000>, ++ LSX_2RN_DESC_BASE<"vmskltz.b", LSX128BOpnd>; ++ ++def VMSKLTZ_H : LSX_2R<0b0111001010011100010001>, ++ LSX_2RN_DESC_BASE<"vmskltz.h", LSX128HOpnd>; ++ ++def VMSKLTZ_W : LSX_2R<0b0111001010011100010010>, ++ LSX_2RN_DESC_BASE<"vmskltz.w", LSX128WOpnd>; ++ ++def VMSKLTZ_D : LSX_2R<0b0111001010011100010011>, ++ LSX_2RN_DESC_BASE<"vmskltz.d", LSX128DOpnd>; ++ ++ ++def VROTRI_B : LSX_I3_U<0b0111001010100000001>, ++ LSX2_RORI_U3_DESC_BASE<"vrotri.b", uimm3, immZExt3, LSX128BOpnd>; ++ ++def VROTRI_H : LSX_I4_U<0b011100101010000001>, ++ LSX2_RORI_U4_DESC_BASE<"vrotri.h", uimm4, immZExt4, LSX128HOpnd>; ++ ++def VROTRI_W : LSX_I5_U<0b01110010101000001>, ++ LSX2_RORI_U5_DESC_BASE<"vrotri.w", uimm5, immZExt5, LSX128WOpnd>; ++ ++def VROTRI_D : LSX_I6_U<0b0111001010100001>, ++ LSX2_RORI_U6_DESC_BASE<"vrotri.d", uimm6, immZExt6, LSX128DOpnd>; ++ ++ ++def VSRLNI_B_H : LSX_I4_U<0b011100110100000001>, ++ LSX_BIND_U4N_DESC_BASE<"vsrlni.b.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSRLNI_H_W : LSX_I5_U<0b01110011010000001>, ++ LSX_BIND_U5N_DESC_BASE<"vsrlni.h.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSRLNI_W_D : LSX_I6_U<0b0111001101000001>, ++ LSX_BIND_U6N_DESC_BASE<"vsrlni.w.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSRLNI_D_Q : LSX_I7_U<0b011100110100001>, ++ LSX_BIND_U7N_DESC_BASE<"vsrlni.d.q", LSX128DOpnd>; ++ ++ ++def VSRLRNI_B_H : LSX_I4_U<0b011100110100010001>, ++ LSX_BIND_U4_DESC_BASE<"vsrlrni.b.h", int_loongarch_lsx_vsrlrni_b_h, uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSRLRNI_H_W : LSX_I5_U<0b01110011010001001>, ++ LSX_BIND_U5_DESC_BASE<"vsrlrni.h.w", int_loongarch_lsx_vsrlrni_h_w, uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSRLRNI_W_D : LSX_I6_U<0b0111001101000101>, ++ LSX_BIND_U6_DESC_BASE<"vsrlrni.w.d", int_loongarch_lsx_vsrlrni_w_d, uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSRLRNI_D_Q : LSX_I7_U<0b011100110100011>, ++ LSX_BIND_U7_DESC_BASE<"vsrlrni.d.q", int_loongarch_lsx_vsrlrni_d_q, LSX128DOpnd>; ++ ++ ++def VSSRLNI_B_H : LSX_I4_U<0b011100110100100001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrlni.b.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRLNI_H_W : LSX_I5_U<0b01110011010010001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrlni.h.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRLNI_W_D : LSX_I6_U<0b0111001101001001>, ++ LSX_BIND_U6N_DESC_BASE<"vssrlni.w.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRLNI_D_Q : LSX_I7_U<0b011100110100101>, ++ LSX_BIND_U7N_DESC_BASE<"vssrlni.d.q", LSX128DOpnd>; ++ ++ ++def VSSRLNI_BU_H : LSX_I4_U<0b011100110100110001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrlni.bu.h", uimm4, immZExt4, LSX128BOpnd> ; ++ ++def VSSRLNI_HU_W : LSX_I5_U<0b01110011010011001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrlni.hu.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRLNI_WU_D : LSX_I6_U<0b0111001101001101>, ++ LSX_BIND_U6N_DESC_BASE<"vssrlni.wu.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRLNI_DU_Q : LSX_I7_U<0b011100110100111>, ++ LSX_BIND_U7N_DESC_BASE<"vssrlni.du.q", LSX128DOpnd>; ++ ++ ++def VSSRLRNI_BU_H : LSX_I4_U<0b011100110101010001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrlrni.bu.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRLRNI_HU_W : LSX_I5_U<0b01110011010101001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrlrni.hu.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRLRNI_WU_D : LSX_I6_U<0b0111001101010101>, ++ LSX_BIND_U6N_DESC_BASE<"vssrlrni.wu.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRLRNI_DU_Q : LSX_I7_U<0b011100110101011>, ++ LSX_BIND_U7N_DESC_BASE<"vssrlrni.du.q", LSX128DOpnd>; ++ ++ ++def VSRARNI_B_H : LSX_I4_U<0b011100110101110001>, ++ LSX_BIND_U4N_DESC_BASE<"vsrarni.b.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSRARNI_H_W : LSX_I5_U<0b01110011010111001>, ++ LSX_BIND_U5N_DESC_BASE<"vsrarni.h.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSRARNI_W_D : LSX_I6_U<0b0111001101011101>, ++ LSX_BIND_U6N_DESC_BASE<"vsrarni.w.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSRARNI_D_Q : LSX_I7_U<0b011100110101111>, ++ LSX_BIND_U7N_DESC_BASE<"vsrarni.d.q", LSX128DOpnd>; ++ ++ ++def VSSRANI_B_H : LSX_I4_U<0b011100110110000001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrani.b.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRANI_H_W : LSX_I5_U<0b01110011011000001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrani.h.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRANI_W_D : LSX_I6_U<0b0111001101100001>, ++ LSX_BIND_U6N_DESC_BASE<"vssrani.w.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRANI_D_Q : LSX_I7_U<0b011100110110001>, ++ LSX_BIND_U7N_DESC_BASE<"vssrani.d.q", LSX128DOpnd>; ++ ++ ++def VSSRANI_BU_H : LSX_I4_U<0b011100110110010001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrani.bu.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRANI_HU_W : LSX_I5_U<0b01110011011001001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrani.hu.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRANI_WU_D : LSX_I6_U<0b0111001101100101>, ++ LSX_BIND_U6N_DESC_BASE<"vssrani.wu.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRANI_DU_Q : LSX_I7_U<0b011100110110011>, ++ LSX_BIND_U7N_DESC_BASE<"vssrani.du.q", LSX128DOpnd>; ++ ++ ++def VSSRARNI_B_H : LSX_I4_U<0b011100110110100001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrarni.b.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRARNI_H_W : LSX_I5_U<0b01110011011010001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrarni.h.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRARNI_W_D : LSX_I6_U<0b0111001101101001>, ++ LSX_BIND_U6N_DESC_BASE<"vssrarni.w.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRARNI_D_Q : LSX_I7_U<0b011100110110101>, ++ LSX_BIND_U7N_DESC_BASE<"vssrarni.d.q", LSX128DOpnd>; ++ ++ ++def VSSRARNI_BU_H : LSX_I4_U<0b011100110110110001>, ++ LSX_BIND_U4N_DESC_BASE<"vssrarni.bu.h", uimm4, immZExt4, LSX128BOpnd>; ++ ++def VSSRARNI_HU_W : LSX_I5_U<0b01110011011011001>, ++ LSX_BIND_U5N_DESC_BASE<"vssrarni.hu.w", uimm5, immZExt5, LSX128HOpnd>; ++ ++def VSSRARNI_WU_D : LSX_I6_U<0b0111001101101101>, ++ LSX_BIND_U6N_DESC_BASE<"vssrarni.wu.d", uimm6, immZExt6, LSX128WOpnd>; ++ ++def VSSRARNI_DU_Q : LSX_I7_U<0b011100110110111>, ++ LSX_BIND_U7N_DESC_BASE<"vssrarni.du.q", LSX128DOpnd>; ++ ++ ++ ++def VLD : LSX_I12_S<0b0010110000>, ++ LD_DESC_BASE<"vld", load, v16i8, LSX128BOpnd, mem>; ++ ++def VST : LSX_I12_S<0b0010110001>, ++ ST_DESC_BASE<"vst", store, v16i8, LSX128BOpnd, mem_simm12>; ++ ++ ++def VSETEQZ_V : LSX_SET<0b0111001010011100100110>, ++ LSX_SET_DESC_BASE<"vseteqz.v", LSX128BOpnd>; ++ ++def VSETNEZ_V : LSX_SET<0b0111001010011100100111>, ++ LSX_SET_DESC_BASE<"vsetnez.v", LSX128BOpnd>; ++ ++ ++def VSETANYEQZ_B : LSX_SET<0b0111001010011100101000>, ++ LSX_SET_DESC_BASE<"vsetanyeqz.b", LSX128BOpnd>; ++ ++def VSETANYEQZ_H : LSX_SET<0b0111001010011100101001>, ++ LSX_SET_DESC_BASE<"vsetanyeqz.h", LSX128HOpnd>; ++ ++def VSETANYEQZ_W : LSX_SET<0b0111001010011100101010>, ++ LSX_SET_DESC_BASE<"vsetanyeqz.w", LSX128WOpnd>; ++ ++def VSETANYEQZ_D : LSX_SET<0b0111001010011100101011>, ++ LSX_SET_DESC_BASE<"vsetanyeqz.d", LSX128DOpnd>; ++ ++ ++def VSETALLNEZ_B : LSX_SET<0b0111001010011100101100>, ++ LSX_SET_DESC_BASE<"vsetallnez.b", LSX128BOpnd>; ++ ++def VSETALLNEZ_H : LSX_SET<0b0111001010011100101101>, ++ LSX_SET_DESC_BASE<"vsetallnez.h", LSX128HOpnd>; ++ ++def VSETALLNEZ_W : LSX_SET<0b0111001010011100101110>, ++ LSX_SET_DESC_BASE<"vsetallnez.w", LSX128WOpnd>; ++ ++def VSETALLNEZ_D : LSX_SET<0b0111001010011100101111>, ++ LSX_SET_DESC_BASE<"vsetallnez.d", LSX128DOpnd>; ++ ++class LSX_CBRANCH_PSEUDO_DESC_BASE : ++ LoongArchPseudo<(outs GPR32Opnd:$rd), ++ (ins RCVS:$vj), ++ [(set GPR32Opnd:$rd, (OpNode (TyNode RCVS:$vj)))]> { ++ bit usesCustomInserter = 1; ++} ++ ++def SNZ_B_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SNZ_H_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SNZ_W_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SNZ_D_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SNZ_V_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++ ++def SZ_B_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SZ_H_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SZ_W_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SZ_D_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++def SZ_V_PSEUDO : LSX_CBRANCH_PSEUDO_DESC_BASE; ++ ++ ++def VFMADD_S : LSX_VR4MUL<0b000010010001>, ++ LSX_4RF<"vfmadd.s", int_loongarch_lsx_vfmadd_s, LSX128WOpnd>; ++ ++def VFMADD_D : LSX_VR4MUL<0b000010010010>, ++ LSX_4RF<"vfmadd.d", int_loongarch_lsx_vfmadd_d, LSX128DOpnd>; ++ ++def VFMSUB_S : LSX_VR4MUL<0b000010010101>, ++ LSX_4RF<"vfmsub.s", int_loongarch_lsx_vfmsub_s, LSX128WOpnd>; ++ ++def VFMSUB_D : LSX_VR4MUL<0b000010010110>, ++ LSX_4RF<"vfmsub.d", int_loongarch_lsx_vfmsub_d, LSX128DOpnd>; ++ ++def VFNMADD_S : LSX_VR4MUL<0b000010011001>, ++ LSX_4RF<"vfnmadd.s", int_loongarch_lsx_vfnmadd_s, LSX128WOpnd>; ++ ++def VFNMADD_D : LSX_VR4MUL<0b000010011010>, ++ LSX_4RF<"vfnmadd.d", int_loongarch_lsx_vfnmadd_d, LSX128DOpnd>; ++ ++def VFNMSUB_S : LSX_VR4MUL<0b000010011101>, ++ LSX_4RF<"vfnmsub.s", int_loongarch_lsx_vfnmsub_s, LSX128WOpnd>; ++ ++def VFNMSUB_D : LSX_VR4MUL<0b000010011110>, ++ LSX_4RF<"vfnmsub.d", int_loongarch_lsx_vfnmsub_d, LSX128DOpnd>; ++ ++ ++// vfmadd: vj * vk + va ++def : LSXPat<(fma v2f64:$vj, v2f64:$vk, v2f64:$va), ++ (VFMADD_D $vj, $vk, $va)>; ++ ++def : LSXPat<(fma v4f32:$vj, v4f32:$vk, v4f32:$va), ++ (VFMADD_S $vj, $vk, $va)>; ++ ++ ++// vfmsub: vj * vk - va ++def : LSXPat<(fma v2f64:$vj, v2f64:$vk, (fneg v2f64:$va)), ++ (VFMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; ++ ++def : LSXPat<(fma v4f32:$vj, v4f32:$vk, (fneg v4f32:$va)), ++ (VFMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; ++ ++ ++// vfnmadd: -(vj * vk + va) ++def : LSXPat<(fma (fneg v2f64:$vj), v2f64:$vk, (fneg v2f64:$va)), ++ (VFNMADD_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; ++ ++def : LSXPat<(fma (fneg v4f32:$vj), v4f32:$vk, (fneg v4f32:$va)), ++ (VFNMADD_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; ++ ++// vfnmsub: -(vj * vk - va) ++def : LSXPat<(fma (fneg v2f64:$vj), v2f64:$vk, v2f64:$va), ++ (VFNMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>; ++ ++def : LSXPat<(fma (fneg v4f32:$vj), v4f32:$vk, v4f32:$va), ++ (VFNMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>; ++ ++ ++def VFCMP_CAF_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.caf.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_caf_s>{ ++ bits<5> cond=0x0; ++ } ++ ++def VFCMP_CAF_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.caf.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_caf_d>{ ++ bits<5> cond=0x0; ++ } ++ ++ ++def VFCMP_COR_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cor.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetord_v4f32>{ ++ bits<5> cond=0x14; ++ } ++ ++def VFCMP_COR_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cor.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetord_v2f64>{ ++ bits<5> cond=0x14; ++ } ++ ++ ++def VFCMP_CUN_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cun.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetun_v4f32>{ ++ bits<5> cond=0x8; ++ } ++ ++def VFCMP_CUN_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cun.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetun_v2f64>{ ++ bits<5> cond=0x8; ++ } ++ ++ ++def VFCMP_CUNE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cune.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetune_v4f32>{ ++ bits<5> cond=0x18; ++ } ++ ++def VFCMP_CUNE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cune.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetune_v2f64>{ ++ bits<5> cond=0x18; ++ } ++ ++ ++def VFCMP_CUEQ_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cueq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetueq_v4f32>{ ++ bits<5> cond=0xc; ++ } ++ ++def VFCMP_CUEQ_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cueq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetueq_v2f64>{ ++ bits<5> cond=0xc; ++ } ++ ++def VFCMP_CEQ_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.ceq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetoeq_v4f32>{ ++ bits<5> cond=0x4; ++ } ++ ++def VFCMP_CEQ_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.ceq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetoeq_v2f64>{ ++ bits<5> cond=0x4; ++ } ++ ++ ++def VFCMP_CNE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cne.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetone_v4f32>{ ++ bits<5> cond=0x10; ++ } ++ ++def VFCMP_CNE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cne.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetone_v2f64>{ ++ bits<5> cond=0x10; ++ } ++ ++ ++def VFCMP_CLT_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.clt.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetolt_v4f32>{ ++ bits<5> cond=0x2; ++ } ++ ++def VFCMP_CLT_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.clt.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetolt_v2f64>{ ++ bits<5> cond=0x2; ++ } ++ ++ ++def VFCMP_CULT_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cult.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetult_v4f32>{ ++ bits<5> cond=0xa; ++ } ++ ++def VFCMP_CULT_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cult.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetult_v2f64>{ ++ bits<5> cond=0xa; ++ } ++ ++ ++def VFCMP_CLE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cle.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetole_v4f32>{ ++ bits<5> cond=0x6; ++ } ++ ++def VFCMP_CLE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cle.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetole_v2f64>{ ++ bits<5> cond=0x6; ++ } ++ ++ ++def VFCMP_CULE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.cule.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, vfsetule_v4f32>{ ++ bits<5> cond=0xe; ++ } ++ ++def VFCMP_CULE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.cule.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, vfsetule_v2f64>{ ++ bits<5> cond=0xe; ++ } ++ ++ ++def VFCMP_SAF_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.saf.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_saf_s>{ ++ bits<5> cond=0x1; ++ } ++ ++def VFCMP_SAF_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.saf.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_saf_d>{ ++ bits<5> cond=0x1; ++ } ++ ++def VFCMP_SOR_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sor.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sor_s>{ ++ bits<5> cond=0x15; ++ } ++ ++def VFCMP_SOR_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sor.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sor_d>{ ++ bits<5> cond=0x15; ++ } ++ ++def VFCMP_SUN_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sun.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sun_s>{ ++ bits<5> cond=0x9; ++ } ++ ++def VFCMP_SUN_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sun.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sun_d>{ ++ bits<5> cond=0x9; ++ } ++ ++def VFCMP_SUNE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sune.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sune_s>{ ++ bits<5> cond=0x19; ++ } ++ ++def VFCMP_SUNE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sune.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sune_d>{ ++ bits<5> cond=0x19; ++ } ++ ++def VFCMP_SUEQ_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sueq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sueq_s>{ ++ bits<5> cond=0xd; ++ } ++ ++def VFCMP_SUEQ_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sueq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sueq_d>{ ++ bits<5> cond=0xd; ++ } ++ ++def VFCMP_SEQ_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.seq.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_seq_s>{ ++ bits<5> cond=0x5; ++ } ++ ++def VFCMP_SEQ_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.seq.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_seq_d>{ ++ bits<5> cond=0x5; ++ } ++ ++def VFCMP_SNE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sne.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sne_s>{ ++ bits<5> cond=0x11; ++ } ++ ++def VFCMP_SNE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sne.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sne_d>{ ++ bits<5> cond=0x11; ++ } ++ ++def VFCMP_SLT_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.slt.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_slt_s>{ ++ bits<5> cond=0x3; ++ } ++ ++def VFCMP_SLT_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.slt.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_slt_d>{ ++ bits<5> cond=0x3; ++ } ++ ++def VFCMP_SULT_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sult.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sult_s>{ ++ bits<5> cond=0xb; ++ } ++ ++def VFCMP_SULT_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sult.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sult_d>{ ++ bits<5> cond=0xb; ++ } ++ ++def VFCMP_SLE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sle.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sle_s>{ ++ bits<5> cond=0x7; ++ } ++ ++def VFCMP_SLE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sle.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sle_d>{ ++ bits<5> cond=0x7; ++ } ++ ++def VFCMP_SULE_S : LSX_VFCMP<0b000011000101>, ++ LSX_VFCMP_Reg3<"vfcmp.sule.s", LSX128WOpnd, LSX128WOpnd, LSX128WOpnd, int_loongarch_lsx_vfcmp_sule_s>{ ++ bits<5> cond=0xf; ++ } ++ ++def VFCMP_SULE_D : LSX_VFCMP<0b000011000110>, ++ LSX_VFCMP_Reg3<"vfcmp.sule.d", LSX128DOpnd, LSX128DOpnd, LSX128DOpnd, int_loongarch_lsx_vfcmp_sule_d>{ ++ bits<5> cond=0xf; ++ } ++ ++def VBITSEL_V : LSX_VR4MUL<0b000011010001>, ++ LSX_VMul_Reg4<"vbitsel.v", LSX128BOpnd, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd, int_loongarch_lsx_vbitsel_v>; ++ ++def VSHUF_B : LSX_VR4MUL<0b000011010101>, ++ LSX_3R_4R_VSHF_DESC_BASE<"vshuf.b", LSX128BOpnd>; ++ ++ ++class LSX_BSEL_PSEUDO_BASE : ++ LSXPseudo<(outs RO:$vd), (ins RO:$vd_in, RO:$vs, RO:$vt), ++ [(set RO:$vd, (Ty (vselect RO:$vd_in, RO:$vt, RO:$vs)))]>, ++ PseudoInstExpansion<(VBITSEL_V LSX128BOpnd:$vd, LSX128BOpnd:$vs, ++ LSX128BOpnd:$vt, LSX128BOpnd:$vd_in)> { ++ let Constraints = "$vd_in = $vd"; ++} ++ ++def BSEL_B_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++def BSEL_H_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++def BSEL_W_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++def BSEL_D_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++def BSEL_FW_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++def BSEL_FD_PSEUDO : LSX_BSEL_PSEUDO_BASE; ++ ++ ++class LSX_LD_DESC_BASE { ++ dag OutOperandList = (outs ROVD:$vd); ++ dag InOperandList = (ins MemOpnd:$addr); ++ string AsmString = !strconcat(instr_asm, "\t$vd, $addr"); ++ list Pattern = [(set ROVD:$vd, (OpNode (TyNode (load Addr:$addr))))]; ++ string DecoderMethod = "DecodeLSX128memlsl"; ++} ++ ++def VLDREPL_B : LSX_SI12_S<0b0011000010>, ++ LSX_LD_DESC_BASE<"vldrepl.b", vldrepl_v16i8, v16i8, LSX128BOpnd>; ++ ++def VLDREPL_H : LSX_SI11_S<0b00110000010>, ++ LSX_LD_DESC_BASE<"vldrepl.h", vldrepl_v8i16, v8i16, LSX128HOpnd, mem_simm11_lsl1, addrimm11lsl1>; ++ ++def VLDREPL_W : LSX_SI10_S<0b001100000010>, ++ LSX_LD_DESC_BASE<"vldrepl.w", vldrepl_v4i32, v4i32, LSX128WOpnd, mem_simm10_lsl2, addrimm10lsl2>; ++ ++def VLDREPL_D : LSX_SI9_S<0b0011000000010>, ++ LSX_LD_DESC_BASE<"vldrepl.d", vldrepl_v2i64, v2i64, LSX128DOpnd, mem_simm9_lsl3, addrimm9lsl3>; ++ ++ ++def VSTELM_B : LSX_SI8_idx4<0b0011000110>, ++ LSX_I8_U4_DESC_BASE<"vstelm.b", int_loongarch_lsx_vstelm_b, simm8_32, immSExt8, LSX128BOpnd>; ++ ++def VSTELM_H : LSX_SI8_idx3<0b00110001010>, ++ LSX_I8_U3_DESC_BASE<"vstelm.h", int_loongarch_lsx_vstelm_h, immSExt8_1_O, immSExt8, LSX128HOpnd>; ++ ++def VSTELM_W : LSX_SI8_idx2<0b001100010010>, ++ LSX_I8_U2_DESC_BASE<"vstelm.w", int_loongarch_lsx_vstelm_w, immSExt8_2_O, immSExt8, LSX128WOpnd>; ++ ++def VSTELM_D : LSX_SI8_idx1<0b0011000100010>, ++ LSX_I8_U1_DESC_BASE<"vstelm.d", int_loongarch_lsx_vstelm_d, immSExt8_3_O, immSExt8, LSX128DOpnd>; ++ ++ ++let mayLoad = 1, canFoldAsLoad = 1 in { ++ def VLDX : LSX_3R_2GP<0b00111000010000000>, ++ LSX_LDX_LA<"vldx", int_loongarch_lsx_vldx, GPR64Opnd, LSX128BOpnd>; ++} ++ ++let mayStore = 1 in{ ++ def VSTX : LSX_3R_2GP<0b00111000010001000>, ++ LSX_SDX_LA<"vstx", int_loongarch_lsx_vstx, GPR64Opnd, LSX128BOpnd>; ++} ++ ++ ++def VADDWEV_H_B : LSX_3R<0b01110000000111100>, ++ LSX_3R_DESC_BASE<"vaddwev.h.b", int_loongarch_lsx_vaddwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWEV_W_H : LSX_3R<0b01110000000111101>, ++ LSX_3R_DESC_BASE<"vaddwev.w.h", int_loongarch_lsx_vaddwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWEV_D_W : LSX_3R<0b01110000000111110>, ++ LSX_3R_DESC_BASE<"vaddwev.d.w", int_loongarch_lsx_vaddwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWEV_Q_D : LSX_3R<0b01110000000111111>, ++ LSX_3R_DESC_BASE<"vaddwev.q.d", int_loongarch_lsx_vaddwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSUBWEV_H_B : LSX_3R<0b01110000001000000>, ++ LSX_3R_DESC_BASE<"vsubwev.h.b", int_loongarch_lsx_vsubwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSUBWEV_W_H : LSX_3R<0b01110000001000001>, ++ LSX_3R_DESC_BASE<"vsubwev.w.h", int_loongarch_lsx_vsubwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSUBWEV_D_W : LSX_3R<0b01110000001000010>, ++ LSX_3R_DESC_BASE<"vsubwev.d.w", int_loongarch_lsx_vsubwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VSUBWEV_Q_D : LSX_3R<0b01110000001000011>, ++ LSX_3R_DESC_BASE<"vsubwev.q.d", int_loongarch_lsx_vsubwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VADDWOD_H_B : LSX_3R<0b01110000001000100>, ++ LSX_3R_DESC_BASE<"vaddwod.h.b", int_loongarch_lsx_vaddwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWOD_W_H : LSX_3R<0b01110000001000101>, ++ LSX_3R_DESC_BASE<"vaddwod.w.h", int_loongarch_lsx_vaddwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWOD_D_W : LSX_3R<0b01110000001000110>, ++ LSX_3R_DESC_BASE<"vaddwod.d.w", int_loongarch_lsx_vaddwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWOD_Q_D : LSX_3R<0b01110000001000111>, ++ LSX_3R_DESC_BASE<"vaddwod.q.d", int_loongarch_lsx_vaddwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSUBWOD_H_B : LSX_3R<0b01110000001001000>, ++ LSX_3R_DESC_BASE<"vsubwod.h.b", int_loongarch_lsx_vsubwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSUBWOD_W_H : LSX_3R<0b01110000001001001>, ++ LSX_3R_DESC_BASE<"vsubwod.w.h", int_loongarch_lsx_vsubwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSUBWOD_D_W : LSX_3R<0b01110000001001010>, ++ LSX_3R_DESC_BASE<"vsubwod.d.w", int_loongarch_lsx_vsubwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VSUBWOD_Q_D : LSX_3R<0b01110000001001011>, ++ LSX_3R_DESC_BASE<"vsubwod.q.d", int_loongarch_lsx_vsubwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VADDWEV_H_BU : LSX_3R<0b01110000001011100>, ++ LSX_3R_DESC_BASE<"vaddwev.h.bu", int_loongarch_lsx_vaddwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWEV_W_HU : LSX_3R<0b01110000001011101>, ++ LSX_3R_DESC_BASE<"vaddwev.w.hu", int_loongarch_lsx_vaddwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWEV_D_WU : LSX_3R<0b01110000001011110>, ++ LSX_3R_DESC_BASE<"vaddwev.d.wu", int_loongarch_lsx_vaddwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWEV_Q_DU : LSX_3R<0b01110000001011111>, ++ LSX_3R_DESC_BASE<"vaddwev.q.du", int_loongarch_lsx_vaddwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSUBWEV_H_BU : LSX_3R<0b01110000001100000>, ++ LSX_3R_DESC_BASE<"vsubwev.h.bu", int_loongarch_lsx_vsubwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSUBWEV_W_HU : LSX_3R<0b01110000001100001>, ++ LSX_3R_DESC_BASE<"vsubwev.w.hu", int_loongarch_lsx_vsubwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSUBWEV_D_WU : LSX_3R<0b01110000001100010>, ++ LSX_3R_DESC_BASE<"vsubwev.d.wu", int_loongarch_lsx_vsubwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VSUBWEV_Q_DU : LSX_3R<0b01110000001100011>, ++ LSX_3R_DESC_BASE<"vsubwev.q.du", int_loongarch_lsx_vsubwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VADDWOD_H_BU : LSX_3R<0b01110000001100100>, ++ LSX_3R_DESC_BASE<"vaddwod.h.bu", int_loongarch_lsx_vaddwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWOD_W_HU : LSX_3R<0b01110000001100101>, ++ LSX_3R_DESC_BASE<"vaddwod.w.hu", int_loongarch_lsx_vaddwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWOD_D_WU : LSX_3R<0b01110000001100110>, ++ LSX_3R_DESC_BASE<"vaddwod.d.wu", int_loongarch_lsx_vaddwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWOD_Q_DU : LSX_3R<0b01110000001100111>, ++ LSX_3R_DESC_BASE<"vaddwod.q.du", int_loongarch_lsx_vaddwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSUBWOD_H_BU : LSX_3R<0b01110000001101000>, ++ LSX_3R_DESC_BASE<"vsubwod.h.bu", int_loongarch_lsx_vsubwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSUBWOD_W_HU : LSX_3R<0b01110000001101001>, ++ LSX_3R_DESC_BASE<"vsubwod.w.hu", int_loongarch_lsx_vsubwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSUBWOD_D_WU : LSX_3R<0b01110000001101010>, ++ LSX_3R_DESC_BASE<"vsubwod.d.wu", int_loongarch_lsx_vsubwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VSUBWOD_Q_DU : LSX_3R<0b01110000001101011>, ++ LSX_3R_DESC_BASE<"vsubwod.q.du", int_loongarch_lsx_vsubwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VADDWEV_H_BU_B : LSX_3R<0b01110000001111100>, ++ LSX_3R_DESC_BASE<"vaddwev.h.bu.b", int_loongarch_lsx_vaddwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWEV_W_HU_H : LSX_3R<0b01110000001111101>, ++ LSX_3R_DESC_BASE<"vaddwev.w.hu.h", int_loongarch_lsx_vaddwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWEV_D_WU_W : LSX_3R<0b01110000001111110>, ++ LSX_3R_DESC_BASE<"vaddwev.d.wu.w", int_loongarch_lsx_vaddwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWEV_Q_DU_D : LSX_3R<0b01110000001111111>, ++ LSX_3R_DESC_BASE<"vaddwev.q.du.d", int_loongarch_lsx_vaddwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VADDWOD_H_BU_B : LSX_3R<0b01110000010000000>, ++ LSX_3R_DESC_BASE<"vaddwod.h.bu.b", int_loongarch_lsx_vaddwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VADDWOD_W_HU_H : LSX_3R<0b01110000010000001>, ++ LSX_3R_DESC_BASE<"vaddwod.w.hu.h", int_loongarch_lsx_vaddwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VADDWOD_D_WU_W : LSX_3R<0b01110000010000010>, ++ LSX_3R_DESC_BASE<"vaddwod.d.wu.w", int_loongarch_lsx_vaddwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VADDWOD_Q_DU_D : LSX_3R<0b01110000010000011>, ++ LSX_3R_DESC_BASE<"vaddwod.q.du.d", int_loongarch_lsx_vaddwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VHADDW_Q_D : LSX_3R<0b01110000010101011>, ++ LSX_3R_DESC_BASE<"vhaddw.q.d", int_loongarch_lsx_vhaddw_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VHSUBW_Q_D : LSX_3R<0b01110000010101111>, ++ LSX_3R_DESC_BASE<"vhsubw.q.d", int_loongarch_lsx_vhsubw_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VHADDW_QU_DU : LSX_3R<0b01110000010110011>, ++ LSX_3R_DESC_BASE<"vhaddw.qu.du", int_loongarch_lsx_vhaddw_qu_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VHSUBW_QU_DU : LSX_3R<0b01110000010110111>, ++ LSX_3R_DESC_BASE<"vhsubw.qu.du", int_loongarch_lsx_vhsubw_qu_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMUH_B : LSX_3R<0b01110000100001100>, ++ LSX_3R_DESC_BASE<"vmuh.b", int_loongarch_lsx_vmuh_b, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMUH_H : LSX_3R<0b01110000100001101>, ++ LSX_3R_DESC_BASE<"vmuh.h", int_loongarch_lsx_vmuh_h, LSX128HOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMUH_W : LSX_3R<0b01110000100001110>, ++ LSX_3R_DESC_BASE<"vmuh.w", int_loongarch_lsx_vmuh_w, LSX128WOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMUH_D : LSX_3R<0b01110000100001111>, ++ LSX_3R_DESC_BASE<"vmuh.d", int_loongarch_lsx_vmuh_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMUH_BU : LSX_3R<0b01110000100010000>, ++ LSX_3R_DESC_BASE<"vmuh.bu", int_loongarch_lsx_vmuh_bu, LSX128BOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMUH_HU : LSX_3R<0b01110000100010001>, ++ LSX_3R_DESC_BASE<"vmuh.hu", int_loongarch_lsx_vmuh_hu, LSX128HOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMUH_WU : LSX_3R<0b01110000100010010>, ++ LSX_3R_DESC_BASE<"vmuh.wu", int_loongarch_lsx_vmuh_wu, LSX128WOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMUH_DU : LSX_3R<0b01110000100010011>, ++ LSX_3R_DESC_BASE<"vmuh.du", int_loongarch_lsx_vmuh_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWEV_H_B : LSX_3R<0b01110000100100000>, ++ LSX_3R_DESC_BASE<"vmulwev.h.b", int_loongarch_lsx_vmulwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWEV_W_H : LSX_3R<0b01110000100100001>, ++ LSX_3R_DESC_BASE<"vmulwev.w.h", int_loongarch_lsx_vmulwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWEV_D_W : LSX_3R<0b01110000100100010>, ++ LSX_3R_DESC_BASE<"vmulwev.d.w", int_loongarch_lsx_vmulwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWEV_Q_D : LSX_3R<0b01110000100100011>, ++ LSX_3R_DESC_BASE<"vmulwev.q.d", int_loongarch_lsx_vmulwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWOD_H_B : LSX_3R<0b01110000100100100>, ++ LSX_3R_DESC_BASE<"vmulwod.h.b", int_loongarch_lsx_vmulwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWOD_W_H : LSX_3R<0b01110000100100101>, ++ LSX_3R_DESC_BASE<"vmulwod.w.h", int_loongarch_lsx_vmulwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWOD_D_W : LSX_3R<0b01110000100100110>, ++ LSX_3R_DESC_BASE<"vmulwod.d.w", int_loongarch_lsx_vmulwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWOD_Q_D : LSX_3R<0b01110000100100111>, ++ LSX_3R_DESC_BASE<"vmulwod.q.d", int_loongarch_lsx_vmulwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWEV_H_BU : LSX_3R<0b01110000100110000>, ++ LSX_3R_DESC_BASE<"vmulwev.h.bu", int_loongarch_lsx_vmulwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWEV_W_HU : LSX_3R<0b01110000100110001>, ++ LSX_3R_DESC_BASE<"vmulwev.w.hu", int_loongarch_lsx_vmulwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWEV_D_WU : LSX_3R<0b01110000100110010>, ++ LSX_3R_DESC_BASE<"vmulwev.d.wu", int_loongarch_lsx_vmulwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWEV_Q_DU : LSX_3R<0b01110000100110011>, ++ LSX_3R_DESC_BASE<"vmulwev.q.du", int_loongarch_lsx_vmulwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWOD_H_BU : LSX_3R<0b01110000100110100>, ++ LSX_3R_DESC_BASE<"vmulwod.h.bu", int_loongarch_lsx_vmulwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWOD_W_HU : LSX_3R<0b01110000100110101>, ++ LSX_3R_DESC_BASE<"vmulwod.w.hu", int_loongarch_lsx_vmulwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWOD_D_WU : LSX_3R<0b01110000100110110>, ++ LSX_3R_DESC_BASE<"vmulwod.d.wu", int_loongarch_lsx_vmulwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWOD_Q_DU : LSX_3R<0b01110000100110111>, ++ LSX_3R_DESC_BASE<"vmulwod.q.du", int_loongarch_lsx_vmulwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWEV_H_BU_B : LSX_3R<0b01110000101000000>, ++ LSX_3R_DESC_BASE<"vmulwev.h.bu.b", int_loongarch_lsx_vmulwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWEV_W_HU_H : LSX_3R<0b01110000101000001>, ++ LSX_3R_DESC_BASE<"vmulwev.w.hu.h", int_loongarch_lsx_vmulwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWEV_D_WU_W : LSX_3R<0b01110000101000010>, ++ LSX_3R_DESC_BASE<"vmulwev.d.wu.w", int_loongarch_lsx_vmulwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWEV_Q_DU_D : LSX_3R<0b01110000101000011>, ++ LSX_3R_DESC_BASE<"vmulwev.q.du.d", int_loongarch_lsx_vmulwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMULWOD_H_BU_B : LSX_3R<0b01110000101000100>, ++ LSX_3R_DESC_BASE<"vmulwod.h.bu.b", int_loongarch_lsx_vmulwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMULWOD_W_HU_H : LSX_3R<0b01110000101000101>, ++ LSX_3R_DESC_BASE<"vmulwod.w.hu.h", int_loongarch_lsx_vmulwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMULWOD_D_WU_W : LSX_3R<0b01110000101000110>, ++ LSX_3R_DESC_BASE<"vmulwod.d.wu.w", int_loongarch_lsx_vmulwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMULWOD_Q_DU_D : LSX_3R<0b01110000101000111>, ++ LSX_3R_DESC_BASE<"vmulwod.q.du.d", int_loongarch_lsx_vmulwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWEV_H_B : LSX_3R<0b01110000101011000>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.h.b", int_loongarch_lsx_vmaddwev_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWEV_W_H : LSX_3R<0b01110000101011001>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.w.h", int_loongarch_lsx_vmaddwev_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWEV_D_W : LSX_3R<0b01110000101011010>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.d.w", int_loongarch_lsx_vmaddwev_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VMADDWEV_Q_D : LSX_3R<0b01110000101011011>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.q.d", int_loongarch_lsx_vmaddwev_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWOD_H_B : LSX_3R<0b01110000101011100>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.h.b", int_loongarch_lsx_vmaddwod_h_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWOD_W_H : LSX_3R<0b01110000101011101>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.w.h", int_loongarch_lsx_vmaddwod_w_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWOD_D_W : LSX_3R<0b01110000101011110>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.d.w", int_loongarch_lsx_vmaddwod_d_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VMADDWOD_Q_D : LSX_3R<0b01110000101011111>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.q.d", int_loongarch_lsx_vmaddwod_q_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWEV_H_BU : LSX_3R<0b01110000101101000>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.h.bu", int_loongarch_lsx_vmaddwev_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWEV_W_HU : LSX_3R<0b01110000101101001>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.w.hu", int_loongarch_lsx_vmaddwev_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWEV_D_WU : LSX_3R<0b01110000101101010>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.d.wu", int_loongarch_lsx_vmaddwev_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VMADDWEV_Q_DU : LSX_3R<0b01110000101101011>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.q.du", int_loongarch_lsx_vmaddwev_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWOD_H_BU : LSX_3R<0b01110000101101100>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.h.bu", int_loongarch_lsx_vmaddwod_h_bu, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWOD_W_HU : LSX_3R<0b01110000101101101>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.w.hu", int_loongarch_lsx_vmaddwod_w_hu, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWOD_D_WU : LSX_3R<0b01110000101101110>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.d.wu", int_loongarch_lsx_vmaddwod_d_wu, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VMADDWOD_Q_DU : LSX_3R<0b01110000101101111>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.q.du", int_loongarch_lsx_vmaddwod_q_du, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWEV_H_BU_B : LSX_3R<0b01110000101111000>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.h.bu.b", int_loongarch_lsx_vmaddwev_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWEV_W_HU_H : LSX_3R<0b01110000101111001>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.w.hu.h", int_loongarch_lsx_vmaddwev_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWEV_D_WU_W : LSX_3R<0b01110000101111010>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.d.wu.w", int_loongarch_lsx_vmaddwev_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMADDWEV_Q_DU_D : LSX_3R<0b01110000101111011>, ++ LSX_3R_4R_DESC_BASE<"vmaddwev.q.du.d", int_loongarch_lsx_vmaddwev_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VMADDWOD_H_BU_B : LSX_3R<0b01110000101111100>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.h.bu.b", int_loongarch_lsx_vmaddwod_h_bu_b, LSX128HOpnd, LSX128BOpnd, LSX128BOpnd>; ++ ++def VMADDWOD_W_HU_H : LSX_3R<0b01110000101111101>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.w.hu.h", int_loongarch_lsx_vmaddwod_w_hu_h, LSX128WOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VMADDWOD_D_WU_W : LSX_3R<0b01110000101111110>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.d.wu.w", int_loongarch_lsx_vmaddwod_d_wu_w, LSX128DOpnd, LSX128WOpnd, LSX128WOpnd> ; ++ ++def VMADDWOD_Q_DU_D : LSX_3R<0b01110000101111111>, ++ LSX_3R_4R_DESC_BASE<"vmaddwod.q.du.d", int_loongarch_lsx_vmaddwod_q_du_d, LSX128DOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSRLN_B_H : LSX_3R<0b01110000111101001>, ++ LSX_3R_DESC_BASE<"vsrln.b.h", int_loongarch_lsx_vsrln_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSRLN_H_W : LSX_3R<0b01110000111101010>, ++ LSX_3R_DESC_BASE<"vsrln.h.w", int_loongarch_lsx_vsrln_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSRLN_W_D : LSX_3R<0b01110000111101011>, ++ LSX_3R_DESC_BASE<"vsrln.w.d", int_loongarch_lsx_vsrln_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSRAN_B_H : LSX_3R<0b01110000111101101>, ++ LSX_3R_DESC_BASE<"vsran.b.h", int_loongarch_lsx_vsran_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSRAN_H_W : LSX_3R<0b01110000111101110>, ++ LSX_3R_DESC_BASE<"vsran.h.w", int_loongarch_lsx_vsran_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSRAN_W_D : LSX_3R<0b01110000111101111>, ++ LSX_3R_DESC_BASE<"vsran.w.d", int_loongarch_lsx_vsran_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSRLRN_B_H : LSX_3R<0b01110000111110001>, ++ LSX_3R_DESC_BASE<"vsrlrn.b.h", int_loongarch_lsx_vsrlrn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSRLRN_H_W : LSX_3R<0b01110000111110010>, ++ LSX_3R_DESC_BASE<"vsrlrn.h.w", int_loongarch_lsx_vsrlrn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSRLRN_W_D : LSX_3R<0b01110000111110011>, ++ LSX_3R_DESC_BASE<"vsrlrn.w.d", int_loongarch_lsx_vsrlrn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSRARN_B_H : LSX_3R<0b01110000111110101>, ++ LSX_3R_DESC_BASE<"vsrarn.b.h", int_loongarch_lsx_vsrarn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSRARN_H_W : LSX_3R<0b01110000111110110>, ++ LSX_3R_DESC_BASE<"vsrarn.h.w", int_loongarch_lsx_vsrarn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSRARN_W_D : LSX_3R<0b01110000111110111>, ++ LSX_3R_DESC_BASE<"vsrarn.w.d", int_loongarch_lsx_vsrarn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRLN_B_H : LSX_3R<0b01110000111111001>, ++ LSX_3R_DESC_BASE<"vssrln.b.h", int_loongarch_lsx_vssrln_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRLN_H_W : LSX_3R<0b01110000111111010>, ++ LSX_3R_DESC_BASE<"vssrln.h.w", int_loongarch_lsx_vssrln_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRLN_W_D : LSX_3R<0b01110000111111011>, ++ LSX_3R_DESC_BASE<"vssrln.w.d", int_loongarch_lsx_vssrln_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRAN_B_H : LSX_3R<0b01110000111111101>, ++ LSX_3R_DESC_BASE<"vssran.b.h", int_loongarch_lsx_vssran_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRAN_H_W : LSX_3R<0b01110000111111110>, ++ LSX_3R_DESC_BASE<"vssran.h.w", int_loongarch_lsx_vssran_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRAN_W_D : LSX_3R<0b01110000111111111>, ++ LSX_3R_DESC_BASE<"vssran.w.d", int_loongarch_lsx_vssran_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRLRN_B_H : LSX_3R<0b01110001000000001>, ++ LSX_3R_DESC_BASE<"vssrlrn.b.h", int_loongarch_lsx_vssrlrn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRLRN_H_W : LSX_3R<0b01110001000000010>, ++ LSX_3R_DESC_BASE<"vssrlrn.h.w", int_loongarch_lsx_vssrlrn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRLRN_W_D : LSX_3R<0b01110001000000011>, ++ LSX_3R_DESC_BASE<"vssrlrn.w.d", int_loongarch_lsx_vssrlrn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRARN_B_H : LSX_3R<0b01110001000000101>, ++ LSX_3R_DESC_BASE<"vssrarn.b.h", int_loongarch_lsx_vssrarn_b_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRARN_H_W : LSX_3R<0b01110001000000110>, ++ LSX_3R_DESC_BASE<"vssrarn.h.w", int_loongarch_lsx_vssrarn_h_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRARN_W_D : LSX_3R<0b01110001000000111>, ++ LSX_3R_DESC_BASE<"vssrarn.w.d", int_loongarch_lsx_vssrarn_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRLN_BU_H : LSX_3R<0b01110001000001001>, ++ LSX_3R_DESC_BASE<"vssrln.bu.h", int_loongarch_lsx_vssrln_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRLN_HU_W : LSX_3R<0b01110001000001010>, ++ LSX_3R_DESC_BASE<"vssrln.hu.w", int_loongarch_lsx_vssrln_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRLN_WU_D : LSX_3R<0b01110001000001011>, ++ LSX_3R_DESC_BASE<"vssrln.wu.d", int_loongarch_lsx_vssrln_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRAN_BU_H : LSX_3R<0b01110001000001101>, ++ LSX_3R_DESC_BASE<"vssran.bu.h", int_loongarch_lsx_vssran_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRAN_HU_W : LSX_3R<0b01110001000001110>, ++ LSX_3R_DESC_BASE<"vssran.hu.w", int_loongarch_lsx_vssran_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRAN_WU_D : LSX_3R<0b01110001000001111>, ++ LSX_3R_DESC_BASE<"vssran.wu.d", int_loongarch_lsx_vssran_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRLRN_BU_H : LSX_3R<0b01110001000010001>, ++ LSX_3R_DESC_BASE<"vssrlrn.bu.h", int_loongarch_lsx_vssrlrn_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRLRN_HU_W : LSX_3R<0b01110001000010010>, ++ LSX_3R_DESC_BASE<"vssrlrn.hu.w", int_loongarch_lsx_vssrlrn_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRLRN_WU_D : LSX_3R<0b01110001000010011>, ++ LSX_3R_DESC_BASE<"vssrlrn.wu.d", int_loongarch_lsx_vssrlrn_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRARN_BU_H : LSX_3R<0b01110001000010101>, ++ LSX_3R_DESC_BASE<"vssrarn.bu.h", int_loongarch_lsx_vssrarn_bu_h, LSX128BOpnd, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRARN_HU_W : LSX_3R<0b01110001000010110>, ++ LSX_3R_DESC_BASE<"vssrarn.hu.w", int_loongarch_lsx_vssrarn_hu_w, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRARN_WU_D : LSX_3R<0b01110001000010111>, ++ LSX_3R_DESC_BASE<"vssrarn.wu.d", int_loongarch_lsx_vssrarn_wu_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VANDN_V : LSX_3R<0b01110001001010000>, ++ LSX_3R_DESC_BASE<"vandn.v", int_loongarch_lsx_vandn_v, LSX128BOpnd>; ++ ++ ++class LSX_VANDN_PSEUDO_BASE : ++ LSXPseudo<(outs RO:$vd), (ins RO:$vj, RO:$vk), ++ []>, ++ PseudoInstExpansion<(VANDN_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++def VANDN_H_PSEUDO : LSX_VANDN_PSEUDO_BASE; ++def VANDN_W_PSEUDO : LSX_VANDN_PSEUDO_BASE; ++def VANDN_D_PSEUDO : LSX_VANDN_PSEUDO_BASE; ++ ++ ++ ++def VORN_V : LSX_3R<0b01110001001010001>, ++ LSX_3R_DESC_BASE<"vorn.v", int_loongarch_lsx_vorn_v, LSX128BOpnd>; ++ ++ ++class LSX_VORN_PSEUDO_BASE : ++ LSXPseudo<(outs RO:$vd), (ins RO:$vj, RO:$vk), ++ []>, ++ PseudoInstExpansion<(VORN_V LSX128BOpnd:$vd, ++ LSX128BOpnd:$vj, ++ LSX128BOpnd:$vk)>; ++ ++def VORN_H_PSEUDO : LSX_VORN_PSEUDO_BASE; ++def VORN_W_PSEUDO : LSX_VORN_PSEUDO_BASE; ++def VORN_D_PSEUDO : LSX_VORN_PSEUDO_BASE; ++ ++ ++def VFRSTP_B : LSX_3R<0b01110001001010110>, ++ LSX_3R_4R_DESC_BASE<"vfrstp.b", int_loongarch_lsx_vfrstp_b, LSX128BOpnd>; ++ ++def VFRSTP_H : LSX_3R<0b01110001001010111>, ++ LSX_3R_4R_DESC_BASE<"vfrstp.h", int_loongarch_lsx_vfrstp_h, LSX128HOpnd>; ++ ++ ++def VADD_Q : LSX_3R<0b01110001001011010>, IsCommutable, ++ LSX_3R_DESC_BASE<"vadd.q", int_loongarch_lsx_vadd_q, LSX128DOpnd>; ++ ++def VSUB_Q : LSX_3R<0b01110001001011011>, ++ LSX_3R_DESC_BASE<"vsub.q", int_loongarch_lsx_vsub_q, LSX128DOpnd>; ++ ++ ++def VSIGNCOV_B : LSX_3R<0b01110001001011100>, ++ LSX_3R_DESC_BASE<"vsigncov.b", int_loongarch_lsx_vsigncov_b, LSX128BOpnd>; ++ ++def VSIGNCOV_H : LSX_3R<0b01110001001011101>, ++ LSX_3R_DESC_BASE<"vsigncov.h", int_loongarch_lsx_vsigncov_h, LSX128HOpnd>; ++ ++def VSIGNCOV_W : LSX_3R<0b01110001001011110>, ++ LSX_3R_DESC_BASE<"vsigncov.w", int_loongarch_lsx_vsigncov_w, LSX128WOpnd>; ++ ++def VSIGNCOV_D : LSX_3R<0b01110001001011111>, ++ LSX_3R_DESC_BASE<"vsigncov.d", int_loongarch_lsx_vsigncov_d, LSX128DOpnd>; ++ ++ ++def VFCVT_H_S : LSX_3R<0b01110001010001100>, ++ LSX_3RF_DESC_BASE<"vfcvt.h.s", int_loongarch_lsx_vfcvt_h_s, LSX128HOpnd, LSX128WOpnd, LSX128WOpnd>; ++ ++def VFCVT_S_D : LSX_3R<0b01110001010001101>, ++ LSX_3RF_DESC_BASE1<"vfcvt.s.d", int_loongarch_lsx_vfcvt_s_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VFFINT_S_L : LSX_3R<0b01110001010010000>, ++ LSX_3RF_DESC_BASE<"vffint.s.l", int_loongarch_lsx_vffint_s_l, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VFTINT_W_D : LSX_3R<0b01110001010010011>, ++ LSX_3RF_DESC_BASE<"vftint.w.d", int_loongarch_lsx_vftint_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VFTINTRZ_W_D : LSX_3R<0b01110001010010110>, ++ LSX_3RF_DESC_BASE<"vftintrz.w.d", int_loongarch_lsx_vftintrz_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VFTINTRP_W_D : LSX_3R<0b01110001010010101>, ++ LSX_3RF_DESC_BASE<"vftintrp.w.d", int_loongarch_lsx_vftintrp_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VFTINTRM_W_D : LSX_3R<0b01110001010010100>, ++ LSX_3RF_DESC_BASE<"vftintrm.w.d", int_loongarch_lsx_vftintrm_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++def VFTINTRNE_W_D : LSX_3R<0b01110001010010111>, ++ LSX_3RF_DESC_BASE<"vftintrne.w.d", int_loongarch_lsx_vftintrne_w_d, LSX128WOpnd, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VBSRL_V : LSX_I5_U<0b01110010100011101>, ++ LSX_U5_DESC_BASE<"vbsrl.v", int_loongarch_lsx_vbsrl_v, LSX128BOpnd>; ++ ++def VBSLL_V : LSX_I5_U<0b01110010100011100>, ++ LSX_U5_DESC_BASE<"vbsll.v", int_loongarch_lsx_vbsll_v, LSX128BOpnd>; ++ ++ ++def VFRSTPI_B : LSX_I5_U<0b01110010100110100>, ++ LSX_U5_4R_DESC_BASE<"vfrstpi.b", int_loongarch_lsx_vfrstpi_b, LSX128BOpnd>; ++ ++def VFRSTPI_H : LSX_I5_U<0b01110010100110101>, ++ LSX_U5_4R_DESC_BASE<"vfrstpi.h", int_loongarch_lsx_vfrstpi_h, LSX128HOpnd>; ++ ++ ++def VNEG_B : LSX_2R<0b0111001010011100001100>, ++ LSX_2R_DESC_BASE<"vneg.b", int_loongarch_lsx_vneg_b, LSX128BOpnd>; ++ ++def VNEG_H : LSX_2R<0b0111001010011100001101>, ++ LSX_2R_DESC_BASE<"vneg.h", int_loongarch_lsx_vneg_h, LSX128HOpnd>; ++ ++def VNEG_W : LSX_2R<0b0111001010011100001110>, ++ LSX_2R_DESC_BASE<"vneg.w", int_loongarch_lsx_vneg_w, LSX128WOpnd>; ++ ++def VNEG_D : LSX_2R<0b0111001010011100001111>, ++ LSX_2R_DESC_BASE<"vneg.d", int_loongarch_lsx_vneg_d, LSX128DOpnd>; ++ ++ ++def VMSKGEZ_B : LSX_2R<0b0111001010011100010100>, ++ LSX_2R_DESC_BASE<"vmskgez.b", int_loongarch_lsx_vmskgez_b, LSX128BOpnd>; ++ ++def VMSKNZ_B : LSX_2R<0b0111001010011100011000>, ++ LSX_2R_DESC_BASE<"vmsknz.b", int_loongarch_lsx_vmsknz_b, LSX128BOpnd>; ++ ++ ++def VFRINTRM_S : LSX_2R<0b0111001010011101010001>, ++ LSX_2RF_DESC_BASE<"vfrintrm.s", int_loongarch_lsx_vfrintrm_s, LSX128WOpnd>; ++ ++def VFRINTRM_D : LSX_2R<0b0111001010011101010010>, ++ LSX_2RF_DESC_BASE<"vfrintrm.d", int_loongarch_lsx_vfrintrm_d, LSX128DOpnd>; ++ ++ ++def VFRINTRP_S : LSX_2R<0b0111001010011101010101>, ++ LSX_2RF_DESC_BASE<"vfrintrp.s", int_loongarch_lsx_vfrintrp_s, LSX128WOpnd>; ++ ++def VFRINTRP_D : LSX_2R<0b0111001010011101010110>, ++ LSX_2RF_DESC_BASE<"vfrintrp.d", int_loongarch_lsx_vfrintrp_d, LSX128DOpnd>; ++ ++ ++def VFRINTRZ_S : LSX_2R<0b0111001010011101011001>, ++ LSX_2RF_DESC_BASE<"vfrintrz.s", int_loongarch_lsx_vfrintrz_s, LSX128WOpnd>; ++ ++def VFRINTRZ_D : LSX_2R<0b0111001010011101011010>, ++ LSX_2RF_DESC_BASE<"vfrintrz.d", int_loongarch_lsx_vfrintrz_d, LSX128DOpnd>; ++ ++ ++def VFRINTRNE_S : LSX_2R<0b0111001010011101011101>, ++ LSX_2RF_DESC_BASE<"vfrintrne.s", int_loongarch_lsx_vfrintrne_s, LSX128WOpnd>; ++ ++def VFRINTRNE_D : LSX_2R<0b0111001010011101011110>, ++ LSX_2RF_DESC_BASE<"vfrintrne.d", int_loongarch_lsx_vfrintrne_d, LSX128DOpnd>; ++ ++ ++def VFFINTL_D_W : LSX_2R<0b0111001010011110000100>, ++ LSX_2RF_DESC_BASE<"vffintl.d.w", int_loongarch_lsx_vffintl_d_w, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFFINTH_D_W : LSX_2R<0b0111001010011110000101>, ++ LSX_2RF_DESC_BASE<"vffinth.d.w", int_loongarch_lsx_vffinth_d_w, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFTINTRM_W_S : LSX_2R<0b0111001010011110001110>, ++ LSX_2RF_DESC_BASE<"vftintrm.w.s", int_loongarch_lsx_vftintrm_w_s, LSX128WOpnd>; ++ ++def VFTINTRM_L_D : LSX_2R<0b0111001010011110001111>, ++ LSX_2RF_DESC_BASE<"vftintrm.l.d", int_loongarch_lsx_vftintrm_l_d, LSX128DOpnd>; ++ ++ ++def VFTINTRP_W_S : LSX_2R<0b0111001010011110010000>, ++ LSX_2RF_DESC_BASE<"vftintrp.w.s", int_loongarch_lsx_vftintrp_w_s, LSX128WOpnd>; ++ ++def VFTINTRP_L_D : LSX_2R<0b0111001010011110010001>, ++ LSX_2RF_DESC_BASE<"vftintrp.l.d", int_loongarch_lsx_vftintrp_l_d, LSX128DOpnd>; ++ ++ ++def VFTINTRZ_W_S : LSX_2R<0b0111001010011110010010>, ++ LSX_2RF_DESC_BASE<"vftintrz.w.s", fp_to_sint, LSX128WOpnd>; ++ ++def VFTINTRZ_L_D : LSX_2R<0b0111001010011110010011>, ++ LSX_2RF_DESC_BASE<"vftintrz.l.d", fp_to_sint, LSX128DOpnd>; ++ ++ ++def VFTINTRNE_W_S : LSX_2R<0b0111001010011110010100>, ++ LSX_2RF_DESC_BASE<"vftintrne.w.s", int_loongarch_lsx_vftintrne_w_s, LSX128WOpnd>; ++ ++def VFTINTRNE_L_D : LSX_2R<0b0111001010011110010101>, ++ LSX_2RF_DESC_BASE<"vftintrne.l.d", int_loongarch_lsx_vftintrne_l_d, LSX128DOpnd>; ++ ++ ++def VFTINTL_L_S : LSX_2R<0b0111001010011110100000>, ++ LSX_2RF_DESC_BASE<"vftintl.l.s", int_loongarch_lsx_vftintl_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFTINTH_L_S : LSX_2R<0b0111001010011110100001>, ++ LSX_2RF_DESC_BASE<"vftinth.l.s", int_loongarch_lsx_vftinth_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFTINTRML_L_S : LSX_2R<0b0111001010011110100010>, ++ LSX_2RF_DESC_BASE<"vftintrml.l.s", int_loongarch_lsx_vftintrml_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFTINTRMH_L_S : LSX_2R<0b0111001010011110100011>, ++ LSX_2RF_DESC_BASE<"vftintrmh.l.s", int_loongarch_lsx_vftintrmh_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFTINTRPL_L_S : LSX_2R<0b0111001010011110100100>, ++ LSX_2RF_DESC_BASE<"vftintrpl.l.s", int_loongarch_lsx_vftintrpl_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFTINTRPH_L_S : LSX_2R<0b0111001010011110100101>, ++ LSX_2RF_DESC_BASE<"vftintrph.l.s", int_loongarch_lsx_vftintrph_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFTINTRZL_L_S : LSX_2R<0b0111001010011110100110>, ++ LSX_2RF_DESC_BASE<"vftintrzl.l.s", int_loongarch_lsx_vftintrzl_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFTINTRZH_L_S : LSX_2R<0b0111001010011110100111>, ++ LSX_2RF_DESC_BASE<"vftintrzh.l.s", int_loongarch_lsx_vftintrzh_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VFTINTRNEL_L_S : LSX_2R<0b0111001010011110101000>, ++ LSX_2RF_DESC_BASE<"vftintrnel.l.s", int_loongarch_lsx_vftintrnel_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++def VFTINTRNEH_L_S : LSX_2R<0b0111001010011110101001>, ++ LSX_2RF_DESC_BASE<"vftintrneh.l.s", int_loongarch_lsx_vftintrneh_l_s, LSX128DOpnd, LSX128WOpnd>; ++ ++ ++def VEXTH_H_B : LSX_2R<0b0111001010011110111000>, ++ LSX_2R_DESC_BASE<"vexth.h.b", int_loongarch_lsx_vexth_h_b, LSX128HOpnd, LSX128BOpnd>; ++ ++def VEXTH_W_H : LSX_2R<0b0111001010011110111001>, ++ LSX_2R_DESC_BASE<"vexth.w.h", int_loongarch_lsx_vexth_w_h, LSX128WOpnd, LSX128HOpnd>; ++ ++def VEXTH_D_W : LSX_2R<0b0111001010011110111010>, ++ LSX_2R_DESC_BASE<"vexth.d.w", int_loongarch_lsx_vexth_d_w, LSX128DOpnd, LSX128WOpnd> ; ++ ++def VEXTH_Q_D : LSX_2R<0b0111001010011110111011>, ++ LSX_2R_DESC_BASE<"vexth.q.d", int_loongarch_lsx_vexth_q_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VEXTH_HU_BU : LSX_2R<0b0111001010011110111100>, ++ LSX_2R_DESC_BASE<"vexth.hu.bu", int_loongarch_lsx_vexth_hu_bu, LSX128HOpnd, LSX128BOpnd>; ++ ++def VEXTH_WU_HU : LSX_2R<0b0111001010011110111101>, ++ LSX_2R_DESC_BASE<"vexth.wu.hu", int_loongarch_lsx_vexth_wu_hu, LSX128WOpnd, LSX128HOpnd>; ++ ++def VEXTH_DU_WU : LSX_2R<0b0111001010011110111110>, ++ LSX_2R_DESC_BASE<"vexth.du.wu", int_loongarch_lsx_vexth_du_wu, LSX128DOpnd, LSX128WOpnd> ; ++ ++def VEXTH_QU_DU : LSX_2R<0b0111001010011110111111>, ++ LSX_2R_DESC_BASE<"vexth.qu.du", int_loongarch_lsx_vexth_qu_du, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSLLWIL_H_B : LSX_I3_U<0b0111001100001000001>, ++ LSX_2R_U3_DESC_BASE<"vsllwil.h.b", int_loongarch_lsx_vsllwil_h_b, LSX128HOpnd, LSX128BOpnd>; ++ ++def VSLLWIL_W_H : LSX_I4_U<0b011100110000100001>, ++ LSX_2R_U4_DESC_BASE<"vsllwil.w.h", int_loongarch_lsx_vsllwil_w_h, LSX128WOpnd, LSX128HOpnd>; ++ ++def VSLLWIL_D_W : LSX_I5_U<0b01110011000010001>, ++ LSX_2R_U5_DESC_BASE<"vsllwil.d.w", int_loongarch_lsx_vsllwil_d_w, LSX128DOpnd, LSX128WOpnd> ; ++ ++ ++def VEXTL_Q_D : LSX_2R<0b0111001100001001000000>, ++ LSX_2R_DESC_BASE<"vextl.q.d", int_loongarch_lsx_vextl_q_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSLLWIL_HU_BU : LSX_I3_U<0b0111001100001100001>, ++ LSX_2R_U3_DESC_BASE<"vsllwil.hu.bu", int_loongarch_lsx_vsllwil_hu_bu, LSX128HOpnd, LSX128BOpnd>; ++ ++def VSLLWIL_WU_HU : LSX_I4_U<0b011100110000110001>, ++ LSX_2R_U4_DESC_BASE<"vsllwil.wu.hu", int_loongarch_lsx_vsllwil_wu_hu, LSX128WOpnd, LSX128HOpnd>; ++ ++def VSLLWIL_DU_WU : LSX_I5_U<0b01110011000011001>, ++ LSX_2R_U5_DESC_BASE<"vsllwil.du.wu", int_loongarch_lsx_vsllwil_du_wu, LSX128DOpnd, LSX128WOpnd> ; ++ ++ ++def VEXTL_QU_DU : LSX_2R<0b0111001100001101000000>, ++ LSX_2R_DESC_BASE<"vextl.qu.du", int_loongarch_lsx_vextl_qu_du, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VBITCLRI_B : LSX_I3_U<0b0111001100010000001>, ++ LSX_2R_U3_DESC_BASE<"vbitclri.b", int_loongarch_lsx_vbitclri_b, LSX128BOpnd, LSX128BOpnd>; ++ ++def VBITCLRI_H : LSX_I4_U<0b011100110001000001>, ++ LSX_2R_U4_DESC_BASE<"vbitclri.h", int_loongarch_lsx_vbitclri_h, LSX128HOpnd, LSX128HOpnd>; ++ ++def VBITCLRI_W : LSX_I5_U<0b01110011000100001>, ++ LSX_2R_U5_DESC_BASE<"vbitclri.w", int_loongarch_lsx_vbitclri_w, LSX128WOpnd, LSX128WOpnd>; ++ ++def VBITCLRI_D : LSX_I6_U<0b0111001100010001>, ++ LSX_2R_U6_DESC_BASE<"vbitclri.d", int_loongarch_lsx_vbitclri_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VBITSETI_B : LSX_I3_U<0b0111001100010100001>, ++ LSX_2R_U3_DESC_BASE<"vbitseti.b", int_loongarch_lsx_vbitseti_b, LSX128BOpnd, LSX128BOpnd>; ++ ++def VBITSETI_H : LSX_I4_U<0b011100110001010001>, ++ LSX_2R_U4_DESC_BASE<"vbitseti.h", int_loongarch_lsx_vbitseti_h, LSX128HOpnd, LSX128HOpnd>; ++ ++def VBITSETI_W : LSX_I5_U<0b01110011000101001>, ++ LSX_2R_U5_DESC_BASE<"vbitseti.w", int_loongarch_lsx_vbitseti_w, LSX128WOpnd, LSX128WOpnd>; ++ ++def VBITSETI_D : LSX_I6_U<0b0111001100010101>, ++ LSX_2R_U6_DESC_BASE<"vbitseti.d", int_loongarch_lsx_vbitseti_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VBITREVI_B : LSX_I3_U<0b0111001100011000001>, ++ LSX_2R_U3_DESC_BASE<"vbitrevi.b", int_loongarch_lsx_vbitrevi_b, LSX128BOpnd, LSX128BOpnd>; ++ ++def VBITREVI_H : LSX_I4_U<0b011100110001100001>, ++ LSX_2R_U4_DESC_BASE<"vbitrevi.h", int_loongarch_lsx_vbitrevi_h, LSX128HOpnd, LSX128HOpnd>; ++ ++def VBITREVI_W : LSX_I5_U<0b01110011000110001>, ++ LSX_2R_U5_DESC_BASE<"vbitrevi.w", int_loongarch_lsx_vbitrevi_w, LSX128WOpnd, LSX128WOpnd>; ++ ++def VBITREVI_D : LSX_I6_U<0b0111001100011001>, ++ LSX_2R_U6_DESC_BASE<"vbitrevi.d", int_loongarch_lsx_vbitrevi_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSSRLRNI_B_H : LSX_I4_U<0b011100110101000001>, ++ LSX_2R_3R_U4_DESC_BASE<"vssrlrni.b.h", int_loongarch_lsx_vssrlrni_b_h, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSSRLRNI_H_W : LSX_I5_U<0b01110011010100001>, ++ LSX_2R_3R_U5_DESC_BASE<"vssrlrni.h.w", int_loongarch_lsx_vssrlrni_h_w, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSSRLRNI_W_D : LSX_I6_U<0b0111001101010001>, ++ LSX_2R_3R_U6_DESC_BASE<"vssrlrni.w.d", int_loongarch_lsx_vssrlrni_w_d, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSSRLRNI_D_Q : LSX_I7_U<0b011100110101001>, ++ LSX_2R_3R_U7_DESC_BASE<"vssrlrni.d.q", int_loongarch_lsx_vssrlrni_d_q, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VSRANI_B_H : LSX_I4_U<0b011100110101100001>, ++ LSX_2R_3R_U4_DESC_BASE<"vsrani.b.h", int_loongarch_lsx_vsrani_b_h, LSX128BOpnd, LSX128BOpnd>; ++ ++def VSRANI_H_W : LSX_I5_U<0b01110011010110001>, ++ LSX_2R_3R_U5_DESC_BASE<"vsrani.h.w", int_loongarch_lsx_vsrani_h_w, LSX128HOpnd, LSX128HOpnd>; ++ ++def VSRANI_W_D : LSX_I6_U<0b0111001101011001>, ++ LSX_2R_3R_U6_DESC_BASE<"vsrani.w.d", int_loongarch_lsx_vsrani_w_d, LSX128WOpnd, LSX128WOpnd>; ++ ++def VSRANI_D_Q : LSX_I7_U<0b011100110101101>, ++ LSX_2R_3R_U7_DESC_BASE<"vsrani.d.q", int_loongarch_lsx_vsrani_d_q, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VEXTRINS_B : LSX_I8_U<0b01110011100011>, ++ LSX_2R_3R_U8_DESC_BASE<"vextrins.b", int_loongarch_lsx_vextrins_b, LSX128BOpnd, LSX128BOpnd>; ++ ++def VEXTRINS_H : LSX_I8_U<0b01110011100010>, ++ LSX_2R_3R_U8_DESC_BASE<"vextrins.h", int_loongarch_lsx_vextrins_h, LSX128HOpnd, LSX128HOpnd>; ++ ++def VEXTRINS_W : LSX_I8_U<0b01110011100001>, ++ LSX_2R_3R_U8_DESC_BASE<"vextrins.w", int_loongarch_lsx_vextrins_w, LSX128WOpnd, LSX128WOpnd>; ++ ++def VEXTRINS_D : LSX_I8_U<0b01110011100000>, ++ LSX_2R_3R_U8_DESC_BASE<"vextrins.d", int_loongarch_lsx_vextrins_d, LSX128DOpnd, LSX128DOpnd>; ++ ++ ++def VBITSELI_B : LSX_I8_U<0b01110011110001>, ++ LSX_2R_3R_U8_DESC_BASE<"vbitseli.b", int_loongarch_lsx_vbitseli_b, LSX128BOpnd, LSX128BOpnd>; ++ ++ ++def VANDI_B : LSX_I8_U<0b01110011110100>, ++ LSX_2R_U8_DESC_BASE<"vandi.b", int_loongarch_lsx_vandi_b, LSX128BOpnd, LSX128BOpnd>; ++ ++ ++def VORI_B : LSX_I8_U<0b01110011110101>, ++ LSX_2R_U8_DESC_BASE<"vori.b", int_loongarch_lsx_vori_b, LSX128BOpnd, LSX128BOpnd>; ++ ++ ++def VXORI_B : LSX_I8_U<0b01110011110110>, ++ LSX_2R_U8_DESC_BASE<"vxori.b", int_loongarch_lsx_vxori_b, LSX128BOpnd, LSX128BOpnd>; ++ ++ ++def VNORI_B : LSX_I8_U<0b01110011110111>, ++ LSX_2R_U8_DESC_BASE<"vnori.b", int_loongarch_lsx_vnori_b, LSX128BOpnd, LSX128BOpnd>; ++ ++ ++def VLDI : LSX_1R_I13<0b01110011111000>, ++ LSX_I13_DESC_BASE<"vldi", int_loongarch_lsx_vldi, i32, simm13Op, LSX128DOpnd>; ++ ++def VLDI_B : LSX_1R_I13_I10<0b01110011111000000>, ++ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_b, simm10, immZExt10, LSX128BOpnd>; ++ ++def VLDI_H : LSX_1R_I13_I10<0b01110011111000001>, ++ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_h, simm10, immZExt10, LSX128HOpnd>; ++ ++def VLDI_W : LSX_1R_I13_I10<0b01110011111000010>, ++ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_w, simm10, immZExt10, LSX128WOpnd>; ++ ++def VLDI_D : LSX_1R_I13_I10<0b01110011111000011>, ++ LSX_I13_DESC_BASE_10<"vldi", int_loongarch_lsx_vrepli_d, simm10, immZExt10, LSX128DOpnd>; ++ ++def VPERMI_W : LSX_I8_U<0b01110011111001>, ++ LSX_2R_3R_U8_DESC_BASE<"vpermi.w", int_loongarch_lsx_vpermi_w, LSX128WOpnd, LSX128WOpnd>; ++ ++ ++def VSEQ_B : LSX_3R<0b01110000000000000>, IsCommutable, ++ LSX_3R_DESC_BASE<"vseq.b", vseteq_v16i8, LSX128BOpnd>; ++ ++def VSEQ_H : LSX_3R<0b01110000000000001>, IsCommutable, ++ LSX_3R_DESC_BASE<"vseq.h", vseteq_v8i16, LSX128HOpnd>; ++ ++def VSEQ_W : LSX_3R<0b01110000000000010>, IsCommutable, ++ LSX_3R_DESC_BASE<"vseq.w", vseteq_v4i32, LSX128WOpnd> ; ++ ++def VSEQ_D : LSX_3R<0b01110000000000011>, IsCommutable, ++ LSX_3R_DESC_BASE<"vseq.d", vseteq_v2i64, LSX128DOpnd>; ++ ++ ++def VSLE_B : LSX_3R<0b01110000000000100>, ++ LSX_3R_DESC_BASE<"vsle.b", vsetle_v16i8, LSX128BOpnd>; ++ ++def VSLE_H : LSX_3R<0b01110000000000101>, ++ LSX_3R_DESC_BASE<"vsle.h", vsetle_v8i16, LSX128HOpnd>; ++ ++def VSLE_W : LSX_3R<0b01110000000000110>, ++ LSX_3R_DESC_BASE<"vsle.w", vsetle_v4i32, LSX128WOpnd>; ++ ++def VSLE_D : LSX_3R<0b01110000000000111>, ++ LSX_3R_DESC_BASE<"vsle.d", vsetle_v2i64, LSX128DOpnd>; ++ ++ ++def VSLE_BU : LSX_3R<0b01110000000001000>, ++ LSX_3R_DESC_BASE<"vsle.bu", vsetule_v16i8, LSX128BOpnd>; ++ ++def VSLE_HU : LSX_3R<0b01110000000001001>, ++ LSX_3R_DESC_BASE<"vsle.hu", vsetule_v8i16, LSX128HOpnd>; ++ ++def VSLE_WU : LSX_3R<0b01110000000001010>, ++ LSX_3R_DESC_BASE<"vsle.wu", vsetule_v4i32, LSX128WOpnd>; ++ ++def VSLE_DU : LSX_3R<0b01110000000001011>, ++ LSX_3R_DESC_BASE<"vsle.du", vsetule_v2i64, LSX128DOpnd>; ++ ++ ++def VSLT_B : LSX_3R<0b01110000000001100>, ++ LSX_3R_DESC_BASE<"vslt.b", vsetlt_v16i8, LSX128BOpnd>; ++ ++def VSLT_H : LSX_3R<0b01110000000001101>, ++ LSX_3R_DESC_BASE<"vslt.h", vsetlt_v8i16, LSX128HOpnd>; ++ ++def VSLT_W : LSX_3R<0b01110000000001110>, ++ LSX_3R_DESC_BASE<"vslt.w", vsetlt_v4i32, LSX128WOpnd>; ++ ++def VSLT_D : LSX_3R<0b01110000000001111>, ++ LSX_3R_DESC_BASE<"vslt.d", vsetlt_v2i64, LSX128DOpnd>; ++ ++ ++def VSLT_BU : LSX_3R<0b01110000000010000>, ++ LSX_3R_DESC_BASE<"vslt.bu", vsetult_v16i8, LSX128BOpnd>; ++ ++def VSLT_HU : LSX_3R<0b01110000000010001>, ++ LSX_3R_DESC_BASE<"vslt.hu", vsetult_v8i16, LSX128HOpnd>; ++ ++def VSLT_WU : LSX_3R<0b01110000000010010>, ++ LSX_3R_DESC_BASE<"vslt.wu", vsetult_v4i32, LSX128WOpnd>; ++ ++def VSLT_DU : LSX_3R<0b01110000000010011>, ++ LSX_3R_DESC_BASE<"vslt.du", vsetult_v2i64, LSX128DOpnd>; ++ ++ ++def VADD_B : LSX_3R<0b01110000000010100>, IsCommutable, ++ LSX_3R_DESC_BASE<"vadd.b", add, LSX128BOpnd>; ++ ++def VADD_H : LSX_3R<0b01110000000010101>, IsCommutable, ++ LSX_3R_DESC_BASE<"vadd.h", add, LSX128HOpnd>; ++ ++def VADD_W : LSX_3R<0b01110000000010110>, IsCommutable, ++ LSX_3R_DESC_BASE<"vadd.w", add, LSX128WOpnd>; ++ ++def VADD_D : LSX_3R<0b01110000000010111>, IsCommutable, ++ LSX_3R_DESC_BASE<"vadd.d", add, LSX128DOpnd>; ++ ++ ++def VSUB_B : LSX_3R<0b01110000000011000>, ++ LSX_3R_DESC_BASE<"vsub.b", sub, LSX128BOpnd>; ++ ++def VSUB_H : LSX_3R<0b01110000000011001>, ++ LSX_3R_DESC_BASE<"vsub.h", sub, LSX128HOpnd>; ++ ++def VSUB_W : LSX_3R<0b01110000000011010>, ++ LSX_3R_DESC_BASE<"vsub.w", sub, LSX128WOpnd>; ++ ++def VSUB_D : LSX_3R<0b01110000000011011>, ++ LSX_3R_DESC_BASE<"vsub.d", sub, LSX128DOpnd>; ++ ++ ++ ++//Pat ++class LSXBitconvertPat preds = [HasLSX]> : ++ LSXPat<(DstVT (bitconvert SrcVT:$src)), ++ (COPY_TO_REGCLASS SrcVT:$src, DstRC), preds>; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++def : LSXBitconvertPat; ++ ++ ++ ++ ++def : LSXPat<(i32 (vextract_sext_i8 v16i8:$vj, i32:$idx)), ++ (SRAI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_B v16i8:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32), (i32 24))>; ++def : LSXPat<(i32 (vextract_sext_i16 v8i16:$vj, i32:$idx)), ++ (SRAI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_H v8i16:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32), (i32 16))>; ++def : LSXPat<(i32 (vextract_sext_i32 v4i32:$vj, i32:$idx)), ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_W v4i32:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32)>; ++def : LSXPat<(i64 (vextract_sext_i64 v2i64:$vj, i32:$idx)), ++ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (VREPLVE_D v2i64:$vj, ++ i32:$idx), ++ sub_64)), ++ GPR64)>; ++ ++def : LSXPat<(i32 (vextract_zext_i8 v16i8:$vj, i32:$idx)), ++ (SRLI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_B v16i8:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32), (i32 24))>; ++def : LSXPat<(i32 (vextract_zext_i16 v8i16:$vj, i32:$idx)), ++ (SRLI_W (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_H v8i16:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32), (i32 16))>; ++def : LSXPat<(i32 (vextract_zext_i32 v4i32:$vj, i32:$idx)), ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (VREPLVE_W v4i32:$vj, ++ i32:$idx), ++ sub_lo)), ++ GPR32)>; ++ ++def : LSXPat<(i64 (vextract_zext_i64 v2i64:$vj, i32:$idx)), ++ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (VREPLVE_D v2i64:$vj, ++ i32:$idx), ++ sub_64)), ++ GPR64)>; ++ ++def : LSXPat<(f32 (vector_extract v4f32:$vj, i32:$idx)), ++ (f32 (EXTRACT_SUBREG (VREPLVE_W v4f32:$vj, ++ i32:$idx), ++ sub_lo))>; ++def : LSXPat<(f64 (vector_extract v2f64:$vj, i32:$idx)), ++ (f64 (EXTRACT_SUBREG (VREPLVE_D v2f64:$vj, ++ i32:$idx), ++ sub_64))>; ++ ++def : LSXPat< ++ (i32 (vextract_sext_i8 v16i8:$vj, i64:$idx)), ++ (SRAI_W (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_B v16i8:$vj, ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32), ++ (i32 24))>; ++def : LSXPat< ++ (i32 (vextract_sext_i16 v8i16:$vj, i64:$idx)), ++ (SRAI_W (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_H v8i16:$vj, ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32), ++ (i32 16))>; ++ ++def : LSXPat< ++ (i32 (vextract_sext_i32 v4i32:$vj, i64:$idx)), ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_W v4i32:$vj, ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32)>; ++ ++def : LSXPat< ++ (i64 (vextract_sext_i64 v2i64:$vj, i64:$idx)), ++ (COPY_TO_REGCLASS ++ (i64 (EXTRACT_SUBREG ++ (VREPLVE_D v2i64:$vj, ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_64)), ++ GPR64)>; ++ ++def : LSXPat< ++ (i32 (vextract_zext_i8 v16i8:$vj, i64:$idx)), ++ (SRLI_W (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_B v16i8:$vj, ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32), ++ (i32 24))>; ++def : LSXPat< ++ (i32 (vextract_zext_i16 v8i16:$vj, i64:$idx)), ++ (SRLI_W (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_H v8i16:$vj, ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32), ++ (i32 16))>; ++def : LSXPat< ++ (i32 (vextract_zext_i32 v4i32:$vj, i64:$idx)), ++ (COPY_TO_REGCLASS ++ (i32 (EXTRACT_SUBREG ++ (VREPLVE_W v4i32:$vj, ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo)), ++ GPR32)>; ++def : LSXPat< ++ (i64 (vextract_zext_i64 v2i64:$vj, i64:$idx)), ++ (COPY_TO_REGCLASS ++ (i64 (EXTRACT_SUBREG ++ (VREPLVE_D v2i64:$vj, ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_64)), ++ GPR64)>; ++ ++ def : LSXPat< ++ (f32 (vector_extract v4f32:$vj, i64:$idx)), ++ (f32 (EXTRACT_SUBREG ++ (VREPLVE_W v4f32:$vj, ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_lo))>; ++def : LSXPat< ++ (f64 (vector_extract v2f64:$vj, i64:$idx)), ++ (f64 (EXTRACT_SUBREG ++ (VREPLVE_D v2f64:$vj, ++ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), ++ sub_64))>; ++ ++ ++def : LSXPat<(vfseteq_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), ++ (VFCMP_CEQ_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; ++ ++def : LSXPat<(vfseteq_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), ++ (VFCMP_CEQ_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; ++ ++def : LSXPat<(vfsetle_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), ++ (VFCMP_CLE_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; ++ ++def : LSXPat<(vfsetle_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), ++ (VFCMP_CLE_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; ++ ++def : LSXPat<(vfsetlt_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), ++ (VFCMP_CLT_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; ++ ++def : LSXPat<(vfsetlt_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), ++ (VFCMP_CLT_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; ++ ++def : LSXPat<(vfsetne_v4f32 LSX128WOpnd:$a, LSX128WOpnd:$b), ++ (VFCMP_CNE_S LSX128WOpnd:$a, LSX128WOpnd:$b)>; ++ ++def : LSXPat<(vfsetne_v2f64 LSX128DOpnd:$a, LSX128DOpnd:$b), ++ (VFCMP_CNE_D LSX128DOpnd:$a, LSX128DOpnd:$b)>; ++ ++ ++class LSX_INSERT_PSEUDO_BASE : ++ LSXPseudo<(outs ROVD:$vd), (ins ROVD:$vd_in, ImmOp:$n, ROFS:$fs), ++ [(set ROVD:$vd, (OpNode (Ty ROVD:$vd_in), ROFS:$fs, Imm:$n))]> { ++ bit usesCustomInserter = 1; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++ ++class INSERT_FW_PSEUDO_DESC : LSX_INSERT_PSEUDO_BASE; ++class INSERT_FD_PSEUDO_DESC : LSX_INSERT_PSEUDO_BASE; ++ ++def INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC; ++def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC; ++ ++ ++class LSX_INSERT_VIDX_PSEUDO_BASE : ++ LSXPseudo<(outs ROVD:$vd), (ins ROVD:$vd_in, ROIdx:$n, ROFS:$fs), ++ [(set ROVD:$vd, (OpNode (Ty ROVD:$vd_in), ROFS:$fs, ++ ROIdx:$n))]> { ++ bit usesCustomInserter = 1; ++ string Constraints = "$vd = $vd_in"; ++} ++ ++class INSERT_H_VIDX64_PSEUDO_DESC : ++ LSX_INSERT_VIDX_PSEUDO_BASE; ++def INSERT_H_VIDX64_PSEUDO : INSERT_H_VIDX64_PSEUDO_DESC; ++ ++class INSERTPostRA : ++ LoongArchPseudo<(outs RC:$xd), (ins RC:$xd_in, RD:$n, RE:$fs), []> { ++ let mayLoad = 1; ++ let mayStore = 1; ++} ++ ++def INSERT_H_VIDX64_PSEUDO_POSTRA : INSERTPostRA; ++ ++class LSX_COPY_PSEUDO_BASE : ++ LSXPseudo<(outs RCD:$vd), (ins RCVS:$vj, ImmOp:$n), ++ [(set RCD:$vd, (OpNode (VecTy RCVS:$vj), Imm:$n))]> { ++ bit usesCustomInserter = 1; ++} ++ ++ ++class COPY_FW_PSEUDO_DESC : LSX_COPY_PSEUDO_BASE; ++class COPY_FD_PSEUDO_DESC : LSX_COPY_PSEUDO_BASE; ++def COPY_FW_PSEUDO : COPY_FW_PSEUDO_DESC; ++def COPY_FD_PSEUDO : COPY_FD_PSEUDO_DESC; ++ ++ ++let isCodeGenOnly = 1 in { ++ ++def VST_H : LSX_I12_S<0b0010110001>, ++ ST_DESC_BASE<"vst", store, v8i16, LSX128HOpnd, mem_simm12>; ++def VST_W : LSX_I12_S<0b0010110001>, ++ ST_DESC_BASE<"vst", store, v4i32, LSX128WOpnd, mem_simm12>; ++def VST_D : LSX_I12_S<0b0010110001>, ++ ST_DESC_BASE<"vst", store, v2i64, LSX128DOpnd, mem_simm12>; ++ ++ ++def VLD_H : LSX_I12_S<0b0010110000>, ++ LD_DESC_BASE<"vld", load, v8i16, LSX128HOpnd, mem_simm12>; ++def VLD_W : LSX_I12_S<0b0010110000>, ++ LD_DESC_BASE<"vld", load, v4i32, LSX128WOpnd, mem_simm12>; ++def VLD_D : LSX_I12_S<0b0010110000>, ++ LD_DESC_BASE<"vld", load, v2i64, LSX128DOpnd, mem_simm12>; ++ ++ ++ ++def VANDI_B_N : LSX_I8_U<0b01110011110100>, ++ LSX_BIT_U8_VREPLVE_DESC_BASE<"vandi.b", and, vsplati8_uimm8, LSX128BOpnd>; ++ ++ ++def VXORI_B_N : LSX_I8_U<0b01110011110110>, ++ LSX_BIT_U8_VREPLVE_DESC_BASE<"vxori.b", xor, vsplati8_uimm8, LSX128BOpnd>; ++ ++ ++def VSRAI_B_N : LSX_I3_U<0b0111001100110100001>, ++ LSX_BIT_U3_VREPLVE_DESC_BASE<"vsrai.b", sra, vsplati8_uimm3, LSX128BOpnd>; ++ ++def VSRAI_H_N : LSX_I4_U<0b011100110011010001>, ++ LSX_BIT_U4_VREPLVE_DESC_BASE<"vsrai.h", sra, vsplati16_uimm4, LSX128HOpnd>; ++ ++def VSRAI_W_N : LSX_I5_U<0b01110011001101001>, ++ LSX_BIT_U5_VREPLVE_DESC_BASE<"vsrai.w", sra, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSRAI_D_N : LSX_I6_U<0b0111001100110101>, ++ LSX_BIT_U6_VREPLVE_DESC_BASE<"vsrai.d", sra, vsplati64_uimm6, LSX128DOpnd>; ++ ++ ++def VMAXI_BU_N : LSX_I5_U<0b01110010100101000>, ++ LSX_I5_U_DESC_BASE<"vmaxi.bu", umax, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VMAXI_HU_N : LSX_I5_U<0b01110010100101001>, ++ LSX_I5_U_DESC_BASE<"vmaxi.hu", umax, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VMAXI_WU_N : LSX_I5_U<0b01110010100101010>, ++ LSX_I5_U_DESC_BASE<"vmaxi.wu", umax, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VMAXI_DU_N : LSX_I5_U<0b01110010100101011>, ++ LSX_I5_U_DESC_BASE<"vmaxi.du", umax, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VMINI_B_N : LSX_I5<0b01110010100100100>, ++ LSX_I5_DESC_BASE<"vmini.b", smin, vsplati8_simm5, LSX128BOpnd>; ++ ++def VMINI_H_N : LSX_I5<0b01110010100100101>, ++ LSX_I5_DESC_BASE<"vmini.h", smin, vsplati16_simm5, LSX128HOpnd>; ++ ++def VMINI_W_N : LSX_I5<0b01110010100100110>, ++ LSX_I5_DESC_BASE<"vmini.w", smin, vsplati32_simm5, LSX128WOpnd>; ++ ++def VMINI_D_N : LSX_I5<0b01110010100100111>, ++ LSX_I5_DESC_BASE<"vmini.d", smin, vsplati64_simm5, LSX128DOpnd>; ++ ++ ++def VMAXI_B_N : LSX_I5<0b01110010100100000>, ++ LSX_I5_DESC_BASE<"vmaxi.b", smax, vsplati8_simm5, LSX128BOpnd>; ++ ++def VMAXI_H_N : LSX_I5<0b01110010100100001>, ++ LSX_I5_DESC_BASE<"vmaxi.h", smax, vsplati16_simm5, LSX128HOpnd>; ++ ++def VMAXI_W_N : LSX_I5<0b01110010100100010>, ++ LSX_I5_DESC_BASE<"vmaxi.w", smax, vsplati32_simm5, LSX128WOpnd>; ++ ++def VMAXI_D_N : LSX_I5<0b01110010100100011>, ++ LSX_I5_DESC_BASE<"vmaxi.d", smax, vsplati64_simm5, LSX128DOpnd>; ++ ++ ++def VSEQI_B_N : LSX_I5<0b01110010100000000>, ++ LSX_I5_DESC_BASE<"vseqi.b", vseteq_v16i8, vsplati8_simm5, LSX128BOpnd>; ++ ++def VSEQI_H_N : LSX_I5<0b01110010100000001>, ++ LSX_I5_DESC_BASE<"vseqi.h", vseteq_v8i16, vsplati16_simm5, LSX128HOpnd>; ++ ++def VSEQI_W_N : LSX_I5<0b01110010100000010>, ++ LSX_I5_DESC_BASE<"vseqi.w", vseteq_v4i32, vsplati32_simm5, LSX128WOpnd>; ++ ++def VSEQI_D_N : LSX_I5<0b01110010100000011>, ++ LSX_I5_DESC_BASE<"vseqi.d", vseteq_v2i64, vsplati64_simm5, LSX128DOpnd>; ++ ++ ++def VSLEI_B_N : LSX_I5<0b01110010100000100>, ++ LSX_I5_DESC_BASE<"vslei.b", vsetle_v16i8, vsplati8_simm5, LSX128BOpnd>; ++ ++def VSLEI_H_N : LSX_I5<0b01110010100000101>, ++ LSX_I5_DESC_BASE<"vslei.h", vsetle_v8i16, vsplati16_simm5, LSX128HOpnd>; ++ ++def VSLEI_W_N : LSX_I5<0b01110010100000110>, ++ LSX_I5_DESC_BASE<"vslei.w", vsetle_v4i32, vsplati32_simm5, LSX128WOpnd>; ++ ++def VSLEI_D_N : LSX_I5<0b01110010100000111>, ++ LSX_I5_DESC_BASE<"vslei.d", vsetle_v2i64, vsplati64_simm5, LSX128DOpnd>; ++ ++def VSLEI_BU_N : LSX_I5_U<0b01110010100001000>, ++ LSX_I5_U_DESC_BASE<"vslei.bu", vsetule_v16i8, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VSLEI_HU_N : LSX_I5_U<0b01110010100001001>, ++ LSX_I5_U_DESC_BASE<"vslei.hu", vsetule_v8i16, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VSLEI_WU_N : LSX_I5_U<0b01110010100001010>, ++ LSX_I5_U_DESC_BASE<"vslei.wu", vsetule_v4i32, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSLEI_DU_N : LSX_I5_U<0b01110010100001011>, ++ LSX_I5_U_DESC_BASE<"vslei.du", vsetule_v2i64, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VSLTI_B_N : LSX_I5<0b01110010100001100>, ++ LSX_I5_DESC_BASE<"vslti.b", vsetlt_v16i8, vsplati8_simm5, LSX128BOpnd>; ++ ++def VSLTI_H_N : LSX_I5<0b01110010100001101>, ++ LSX_I5_DESC_BASE<"vslti.h", vsetlt_v8i16, vsplati16_simm5, LSX128HOpnd>; ++ ++def VSLTI_W_N : LSX_I5<0b01110010100001110>, ++ LSX_I5_DESC_BASE<"vslti.w", vsetlt_v4i32, vsplati32_simm5, LSX128WOpnd>; ++ ++def VSLTI_D_N : LSX_I5<0b01110010100001111>, ++ LSX_I5_DESC_BASE<"vslti.d", vsetlt_v2i64, vsplati64_simm5, LSX128DOpnd>; ++ ++ ++def VSLTI_BU_N : LSX_I5_U<0b01110010100010000>, ++ LSX_I5_U_DESC_BASE<"vslti.bu", vsetult_v16i8, vsplati8_uimm5, LSX128BOpnd>; ++ ++def VSLTI_HU_N : LSX_I5_U<0b01110010100010001>, ++ LSX_I5_U_DESC_BASE<"vslti.hu", vsetult_v8i16, vsplati16_uimm5, LSX128HOpnd>; ++ ++def VSLTI_WU_N : LSX_I5_U<0b01110010100010010>, ++ LSX_I5_U_DESC_BASE<"vslti.wu", vsetult_v4i32, vsplati32_uimm5, LSX128WOpnd>; ++ ++def VSLTI_DU_N : LSX_I5_U<0b01110010100010011>, ++ LSX_I5_U_DESC_BASE<"vslti.du", vsetult_v2i64, vsplati64_uimm5, LSX128DOpnd>; ++ ++ ++def VBITSELI_B_N : LSX_I8_U<0b01110011110001>, ++ LSX_2R_3R_SELECT<"vbitseli.b", vselect, LSX128BOpnd, LSX128BOpnd>; ++ ++} ++ ++ ++def : LSXPat<(v4f32 (load addrimm12:$addr)), (VLD_W addrimm12:$addr)>; ++def : LSXPat<(v2f64 (load addrimm12:$addr)), (VLD_D addrimm12:$addr)>; ++ ++def VST_FW : LSXPat<(store (v4f32 LSX128W:$vj), addrimm12:$addr), ++ (VST_W LSX128W:$vj, addrimm12:$addr)>; ++def VST_FD : LSXPat<(store (v2f64 LSX128D:$vj), addrimm12:$addr), ++ (VST_D LSX128D:$vj, addrimm12:$addr)>; ++ ++def VNEG_FW : LSXPat<(fneg (v4f32 LSX128W:$vj)), ++ (VBITREVI_W LSX128W:$vj, 31)>; ++def VNEG_FD : LSXPat<(fneg (v2f64 LSX128D:$vj)), ++ (VBITREVI_D LSX128D:$vj, 63)>; ++ ++ ++def : LSXPat<(v2i64 (LoongArchVABSD v2i64:$vj, v2i64:$vk, (i32 0))), ++ (v2i64 (VABSD_D $vj, $vk))>; ++ ++def : LSXPat<(v4i32 (LoongArchVABSD v4i32:$vj, v4i32:$vk, (i32 0))), ++ (v4i32 (VABSD_W $vj, $vk))>; ++ ++def : LSXPat<(v8i16 (LoongArchVABSD v8i16:$vj, v8i16:$vk, (i32 0))), ++ (v8i16 (VABSD_H $vj, $vk))>; ++ ++def : LSXPat<(v16i8 (LoongArchVABSD v16i8:$vj, v16i8:$vk, (i32 0))), ++ (v16i8 (VABSD_B $vj, $vk))>; ++ ++def : LSXPat<(v2i64 (LoongArchUVABSD v2i64:$vj, v2i64:$vk, (i32 0))), ++ (v2i64 (VABSD_DU $vj, $vk))>; ++ ++def : LSXPat<(v4i32 (LoongArchUVABSD v4i32:$vj, v4i32:$vk, (i32 0))), ++ (v4i32 (VABSD_WU $vj, $vk))>; ++ ++def : LSXPat<(v8i16 (LoongArchUVABSD v8i16:$vj, v8i16:$vk, (i32 0))), ++ (v8i16 (VABSD_HU $vj, $vk))>; ++ ++def : LSXPat<(v16i8 (LoongArchUVABSD v16i8:$vj, v16i8:$vk, (i32 0))), ++ (v16i8 (VABSD_BU $vj, $vk))>; ++ ++ ++def : LSXPat<(or v16i8:$vj, (shl vsplat_imm_eq_1, v16i8:$vk)), ++ (VBITSET_B v16i8:$vj, v16i8:$vk)>; ++def : LSXPat<(or v8i16:$vj, (shl vsplat_imm_eq_1, v8i16:$vk)), ++ (VBITSET_H v8i16:$vj, v8i16:$vk)>; ++def : LSXPat<(or v4i32:$vj, (shl vsplat_imm_eq_1, v4i32:$vk)), ++ (VBITSET_W v4i32:$vj, v4i32:$vk)>; ++def : LSXPat<(or v2i64:$vj, (shl vsplat_imm_eq_1, v2i64:$vk)), ++ (VBITSET_D v2i64:$vj, v2i64:$vk)>; ++ ++def : LSXPat<(xor v16i8:$vj, (shl vsplat_imm_eq_1, v16i8:$vk)), ++ (VBITREV_B v16i8:$vj, v16i8:$vk)>; ++def : LSXPat<(xor v8i16:$vj, (shl vsplat_imm_eq_1, v8i16:$vk)), ++ (VBITREV_H v8i16:$vj, v8i16:$vk)>; ++def : LSXPat<(xor v4i32:$vj, (shl vsplat_imm_eq_1, v4i32:$vk)), ++ (VBITREV_W v4i32:$vj, v4i32:$vk)>; ++def : LSXPat<(xor v2i64:$vj, (shl (v2i64 vsplati64_imm_eq_1), v2i64:$vk)), ++ (VBITREV_D v2i64:$vj, v2i64:$vk)>; ++ ++def : LSXPat<(and v16i8:$vj, (xor (shl vsplat_imm_eq_1, v16i8:$vk), immAllOnesV)), ++ (VBITCLR_B v16i8:$vj, v16i8:$vk)>; ++def : LSXPat<(and v8i16:$vj, (xor (shl vsplat_imm_eq_1, v8i16:$vk), immAllOnesV)), ++ (VBITCLR_H v8i16:$vj, v8i16:$vk)>; ++def : LSXPat<(and v4i32:$vj, (xor (shl vsplat_imm_eq_1, v4i32:$vk), immAllOnesV)), ++ (VBITCLR_W v4i32:$vj, v4i32:$vk)>; ++def : LSXPat<(and v2i64:$vj, (xor (shl (v2i64 vsplati64_imm_eq_1), v2i64:$vk), (bitconvert (v4i32 immAllOnesV)))), ++ (VBITCLR_D v2i64:$vj, v2i64:$vk)>; ++def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ ++ APInt Imm; ++ SDNode *BV = N->getOperand(0).getNode(); ++ EVT EltTy = N->getValueType(0).getVectorElementType(); ++ ++ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && ++ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63; ++}]>; ++ ++def immi32Cst7 : ImmLeaf(Imm) && Imm == 7;}]>; ++def immi32Cst15 : ImmLeaf(Imm) && Imm == 15;}]>; ++def immi32Cst31 : ImmLeaf(Imm) && Imm == 31;}]>; ++ ++def vsplati8imm7 : PatFrag<(ops node:$vt), ++ (and node:$vt, (vsplati8 immi32Cst7))>; ++def vsplati16imm15 : PatFrag<(ops node:$vt), ++ (and node:$vt, (vsplati16 immi32Cst15))>; ++def vsplati32imm31 : PatFrag<(ops node:$vt), ++ (and node:$vt, (vsplati32 immi32Cst31))>; ++def vsplati64imm63 : PatFrag<(ops node:$vt), ++ (and node:$vt, vsplati64_imm_eq_63)>; ++ ++class LSXShiftPat : ++ LSXPat<(VT (Node VT:$vs, (VT (and VT:$vt, Vec)))), ++ (VT (Insn VT:$vs, VT:$vt))>; ++ ++class LSXBitPat : ++ LSXPat<(VT (Node VT:$vs, (shl vsplat_imm_eq_1, (Frag VT:$vt)))), ++ (VT (Insn VT:$vs, VT:$vt))>; ++ ++multiclass LSXShiftPats { ++ def : LSXShiftPat(Insn#_B), ++ (vsplati8 immi32Cst7)>; ++ def : LSXShiftPat(Insn#_H), ++ (vsplati16 immi32Cst15)>; ++ def : LSXShiftPat(Insn#_W), ++ (vsplati32 immi32Cst31)>; ++ def : LSXPat<(v2i64 (Node v2i64:$vs, (v2i64 (and v2i64:$vt, ++ vsplati64_imm_eq_63)))), ++ (v2i64 (!cast(Insn#_D) v2i64:$vs, v2i64:$vt))>; ++} ++ ++multiclass LSXBitPats { ++ def : LSXBitPat(Insn#_B), vsplati8imm7>; ++ def : LSXBitPat(Insn#_H), vsplati16imm15>; ++ def : LSXBitPat(Insn#_W), vsplati32imm31>; ++ def : LSXPat<(Node v2i64:$vs, (shl (v2i64 vsplati64_imm_eq_1), ++ (vsplati64imm63 v2i64:$vt))), ++ (v2i64 (!cast(Insn#_D) v2i64:$vs, v2i64:$vt))>; ++} ++ ++defm : LSXShiftPats; ++defm : LSXShiftPats; ++defm : LSXShiftPats; ++defm : LSXBitPats; ++defm : LSXBitPats; ++ ++def : LSXPat<(and v16i8:$vs, (xor (shl vsplat_imm_eq_1, ++ (vsplati8imm7 v16i8:$vt)), ++ immAllOnesV)), ++ (v16i8 (VBITCLR_B v16i8:$vs, v16i8:$vt))>; ++def : LSXPat<(and v8i16:$vs, (xor (shl vsplat_imm_eq_1, ++ (vsplati16imm15 v8i16:$vt)), ++ immAllOnesV)), ++ (v8i16 (VBITCLR_H v8i16:$vs, v8i16:$vt))>; ++def : LSXPat<(and v4i32:$vs, (xor (shl vsplat_imm_eq_1, ++ (vsplati32imm31 v4i32:$vt)), ++ immAllOnesV)), ++ (v4i32 (VBITCLR_W v4i32:$vs, v4i32:$vt))>; ++def : LSXPat<(and v2i64:$vs, (xor (shl (v2i64 vsplati64_imm_eq_1), ++ (vsplati64imm63 v2i64:$vt)), ++ (bitconvert (v4i32 immAllOnesV)))), ++ (v2i64 (VBITCLR_D v2i64:$vs, v2i64:$vt))>; ++ ++ ++def : LSXPat<(fdiv (v4f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), v4f32:$v), ++ (VFRECIP_S v4f32:$v)>; ++ ++def : LSXPat<(fdiv (v2f64 (build_vector (f64 fpimm1), (f64 fpimm1))), v2f64:$v), ++ (VFRECIP_D v2f64:$v)>; ++ ++def : LSXPat<(fdiv (v4f32 fpimm1), v4f32:$v), ++ (VFRECIP_S v4f32:$v)>; ++ ++def : LSXPat<(fdiv (v2f64 fpimm1), v2f64:$v), ++ (VFRECIP_D v2f64:$v)>; ++ ++ ++def : LSXPat<(fdiv (v4f32 (build_vector (f32 fpimm1), (f32 fpimm1), (f32 fpimm1), (f32 fpimm1))), (fsqrt v4f32:$v)), ++ (VFRSQRT_S v4f32:$v)>; ++ ++def : LSXPat<(fdiv (v2f64 (build_vector (f64 fpimm1), (f64 fpimm1))), (fsqrt v2f64:$v)), ++ (VFRSQRT_D v2f64:$v)>; ++ ++def : LSXPat<(fdiv (v4f32 fpimm1), (fsqrt v4f32:$v)), ++ (VFRSQRT_S v4f32:$v)>; ++ ++def : LSXPat<(fdiv (v2f64 fpimm1), (fsqrt v2f64:$v)), ++ (VFRSQRT_D v2f64:$v)>; ++ ++ ++def : LSXPat<(abs v2i64:$v), ++ (VMAX_D v2i64:$v, (VNEG_D v2i64:$v))>; ++ ++def : LSXPat<(abs v4i32:$v), ++ (VMAX_W v4i32:$v, (VNEG_W v4i32:$v))>; ++ ++def : LSXPat<(abs v8i16:$v), ++ (VMAX_H v8i16:$v, (VNEG_H v8i16:$v))>; ++ ++def : LSXPat<(abs v16i8:$v), ++ (VMAX_B v16i8:$v, (VNEG_B v16i8:$v))>; ++ ++ ++def : LSXPat<(sub (v16i8 immAllZerosV), v16i8:$v), ++ (VNEG_B v16i8:$v)>; ++ ++def : LSXPat<(sub (v8i16 immAllZerosV), v8i16:$v), ++ (VNEG_H v8i16:$v)>; ++ ++def : LSXPat<(sub (v4i32 immAllZerosV), v4i32:$v), ++ (VNEG_W v4i32:$v)>; ++ ++def : LSXPat<(sub (v2i64 immAllZerosV), v2i64:$v), ++ (VNEG_D v2i64:$v)>; ++ ++ ++def : LSXPat<(sra ++ (v16i8 (add ++ (v16i8 (add LSX128B:$a, LSX128B:$b)), ++ (v16i8 (srl ++ (v16i8 (add LSX128B:$a, LSX128B:$b)), ++ (v16i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (VAVG_B (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; ++ ++def : LSXPat<(sra ++ (v8i16 (add ++ (v8i16 (add LSX128H:$a, LSX128H:$b)), ++ (v8i16 (srl ++ (v8i16 (add LSX128H:$a, LSX128H:$b)), ++ (v8i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (VAVG_H (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; ++ ++def : LSXPat<(sra ++ (v4i32 (add ++ (v4i32 (add LSX128W:$a, LSX128W:$b)), ++ (v4i32 (srl ++ (v4i32 (add LSX128W:$a, LSX128W:$b)), ++ (v4i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)))), ++ (VAVG_W (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; ++ ++def : LSXPat<(sra ++ (v2i64 (add ++ (v2i64 (add LSX128D:$a, LSX128D:$b)), ++ (v2i64 (srl ++ (v2i64 (add LSX128D:$a, LSX128D:$b)), ++ (v2i64 (build_vector (i64 63),(i64 63))) ++ ) ++ ) ++ ) ++ ), ++ (v2i64 (build_vector (i64 1),(i64 1)))), ++ (VAVG_D (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; ++ ++ ++ ++def : LSXPat<(srl ++ (v16i8 (add LSX128B:$a, LSX128B:$b)), ++ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVG_BU (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; ++ ++def : LSXPat<(srl ++ (v8i16 (add LSX128H:$a, LSX128H:$b)), ++ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVG_HU (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; ++ ++def : LSXPat<(srl ++ (v4i32 (add LSX128W:$a, LSX128W:$b)), ++ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVG_WU (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; ++ ++def : LSXPat<(srl ++ (v2i64 (add LSX128D:$a, LSX128D:$b)), ++ (v2i64 (build_vector (i64 1),(i64 1)) ++ ) ++ ), ++ (VAVG_DU (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; ++ ++ ++ ++ ++def : LSXPat<(sra ++ (v16i8 (add ++ (v16i8 (add (v16i8 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i8 (add LSX128B:$a, LSX128B:$b)) ++ )), ++ (v16i8 (srl ++ (v16i8 ( add (v16i8( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i8 (add LSX128B:$a, LSX128B:$b)) ++ )), ++ (v16i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7), ++ (i32 7),(i32 7),(i32 7),(i32 7)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (VAVGR_B (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; ++ ++def : LSXPat<(sra ++ (v8i16 (add ++ (v8i16 (add (v8i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i16 (add LSX128H:$a, LSX128H:$b)) ++ )), ++ (v8i16 (srl ++ (v8i16 (add (v8i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i16 (add LSX128H:$a, LSX128H:$b)) ++ )), ++ (v8i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15), ++ (i32 15),(i32 15),(i32 15),(i32 15)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ ))), ++ (VAVGR_H (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; ++ ++def : LSXPat<(sra ++ (v4i32 (add ++ (v4i32 (add (v4i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v4i32 (add LSX128W:$a, LSX128W:$b)) ++ )), ++ (v4i32 (srl ++ (v4i32 (add (v4i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v4i32 (add LSX128W:$a, LSX128W:$b)) ++ )), ++ (v4i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31)) ++ ) ++ ) ++ ) ++ ) ++ ), ++ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)))), ++ (VAVGR_W (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; ++ ++def : LSXPat<(sra ++ (v2i64 (add ++ (v2i64 (add (v2i64 ( ++ build_vector (i64 1),(i64 1) ++ )), ++ (v2i64 (add LSX128D:$a, LSX128D:$b)) ++ )), ++ (v2i64 (srl ++ (v2i64 (add (v2i64 ( ++ build_vector (i64 1),(i64 1) ++ )), ++ (v2i64 (add LSX128D:$a, LSX128D:$b)) ++ )), ++ (v2i64 (build_vector (i64 63),(i64 63))) ++ ) ++ ) ++ ) ++ ), ++ (v2i64 (build_vector (i64 1),(i64 1)))), ++ (VAVGR_D (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; ++ ++ ++ ++ ++def : LSXPat<(srl ++ (v16i8 (add (v16i8 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v16i8 (add LSX128B:$a, LSX128B:$b)) ++ )), ++ (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVGR_BU (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>; ++ ++def : LSXPat<(srl ++ (v8i16 (add (v8i16 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v8i16 (add LSX128H:$a, LSX128H:$b)) ++ )), ++ (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1), ++ (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVGR_HU (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>; ++ ++def : LSXPat<(srl ++ (v4i32 (add (v4i32 ( ++ build_vector (i32 1),(i32 1),(i32 1),(i32 1) ++ )), ++ (v4i32 (add LSX128W:$a, LSX128W:$b)) ++ )), ++ (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)) ++ ) ++ ), ++ (VAVGR_WU (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>; ++ ++def : LSXPat<(srl ++ (v2i64 (add (v2i64 ( ++ build_vector (i64 1),(i64 1) ++ )), ++ (v2i64 (add LSX128D:$a, LSX128D:$b)) ++ )), ++ (v2i64 (build_vector (i64 1),(i64 1)) ++ ) ++ ), ++ (VAVGR_DU (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>; ++ ++ ++def : LSXPat<(mulhs LSX128D:$a, LSX128D:$b), ++ (VMUH_D LSX128D:$a, LSX128D:$b)>; ++ ++def : LSXPat<(mulhs LSX128W:$a, LSX128W:$b), ++ (VMUH_W LSX128W:$a, LSX128W:$b)>; ++ ++def : LSXPat<(mulhs LSX128H:$a, LSX128H:$b), ++ (VMUH_H LSX128H:$a, LSX128H:$b)>; ++ ++def : LSXPat<(mulhs LSX128B:$a, LSX128B:$b), ++ (VMUH_B LSX128B:$a, LSX128B:$b)>; ++ ++ ++def : LSXPat<(mulhu LSX128D:$a, LSX128D:$b), ++ (VMUH_DU LSX128D:$a, LSX128D:$b)>; ++ ++def : LSXPat<(mulhu LSX128W:$a, LSX128W:$b), ++ (VMUH_WU LSX128W:$a, LSX128W:$b)>; ++ ++def : LSXPat<(mulhu LSX128H:$a, LSX128H:$b), ++ (VMUH_HU LSX128H:$a, LSX128H:$b)>; ++ ++def : LSXPat<(mulhu LSX128B:$a, LSX128B:$b), ++ (VMUH_BU LSX128B:$a, LSX128B:$b)>; ++ ++ ++ ++//===----------------------------------------------------------------------===// ++// Intrinsics ++//===----------------------------------------------------------------------===// ++ ++def : LSXPat<(int_loongarch_lsx_vseq_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSEQ_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vseq_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSEQ_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vseq_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSEQ_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vseq_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSEQ_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsle_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSLE_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSLE_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSLE_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSLE_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsle_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSLE_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSLE_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSLE_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsle_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSLE_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vslt_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSLT_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSLT_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSLT_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSLT_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vslt_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSLT_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSLT_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSLT_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vslt_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSLT_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vadd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VADD_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VADD_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VADD_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VADD_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsub_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSUB_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsub_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSUB_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsub_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSUB_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsub_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSUB_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsadd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSADD_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSADD_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSADD_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSADD_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssub_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSSUB_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSSUB_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSSUB_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSSUB_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsadd_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSADD_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSADD_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSADD_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsadd_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSADD_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssub_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSSUB_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSSUB_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSSUB_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vssub_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSSUB_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vhaddw_h_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VHADDW_H_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhaddw_w_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VHADDW_W_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhaddw_d_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VHADDW_D_W LSX128W:$vj, LSX128W:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vhsubw_h_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VHSUBW_H_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhsubw_w_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VHSUBW_W_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhsubw_d_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VHSUBW_D_W LSX128W:$vj, LSX128W:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vhaddw_hu_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VHADDW_HU_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhaddw_wu_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VHADDW_WU_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhaddw_du_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VHADDW_DU_WU LSX128W:$vj, LSX128W:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vhsubw_hu_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VHSUBW_HU_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhsubw_wu_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VHSUBW_WU_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vhsubw_du_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VHSUBW_DU_WU LSX128W:$vj, LSX128W:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vadda_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VADDA_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadda_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VADDA_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadda_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VADDA_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vadda_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VADDA_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vabsd_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VABSD_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VABSD_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VABSD_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VABSD_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vabsd_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VABSD_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VABSD_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VABSD_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vabsd_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VABSD_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vavg_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VAVG_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VAVG_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VAVG_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VAVG_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vavg_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VAVG_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VAVG_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VAVG_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavg_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VAVG_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vavgr_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VAVGR_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VAVGR_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VAVGR_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VAVGR_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vavgr_bu (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VAVGR_BU LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_hu (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VAVGR_HU LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_wu (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VAVGR_WU LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vavgr_du (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VAVGR_DU LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrlr_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSRLR_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrlr_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSRLR_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrlr_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSRLR_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrlr_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSRLR_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrar_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VSRAR_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrar_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VSRAR_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrar_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VSRAR_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vsrar_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VSRAR_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vbitset_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VBITSET_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitset_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VBITSET_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitset_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VBITSET_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitset_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VBITSET_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vbitrev_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk)), ++ (VBITREV_B LSX128B:$vj, LSX128B:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitrev_h (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk)), ++ (VBITREV_H LSX128H:$vj, LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitrev_w (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk)), ++ (VBITREV_W LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vbitrev_d (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk)), ++ (VBITREV_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfadd_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFADD_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfadd_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFADD_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfsub_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFSUB_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfsub_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFSUB_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfmax_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFMAX_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfmax_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFMAX_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfmin_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFMIN_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfmin_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFMIN_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfmaxa_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFMAXA_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfmaxa_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFMAXA_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfmina_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFMINA_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfmina_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFMINA_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vclo_b (v16i8 LSX128B:$vj)), ++ (VCLO_B LSX128B:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vclo_h (v8i16 LSX128H:$vj)), ++ (VCLO_H LSX128H:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vclo_w (v4i32 LSX128W:$vj)), ++ (VCLO_W LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vclo_d (v2i64 LSX128D:$vj)), ++ (VCLO_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vflogb_s (v4f32 LSX128W:$vj)), ++ (VFLOGB_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vflogb_d (v2f64 LSX128D:$vj)), ++ (VFLOGB_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfclass_s (v4f32 LSX128W:$vj)), ++ (VFCLASS_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vfclass_d (v2f64 LSX128D:$vj)), ++ (VFCLASS_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfrecip_s (v4f32 LSX128W:$vj)), ++ (VFRECIP_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vfrecip_d (v2f64 LSX128D:$vj)), ++ (VFRECIP_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfrsqrt_s (v4f32 LSX128W:$vj)), ++ (VFRSQRT_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vfrsqrt_d (v2f64 LSX128D:$vj)), ++ (VFRSQRT_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcvtl_s_h (v8i16 LSX128H:$vk)), ++ (VFCVTL_S_H LSX128H:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcvth_s_h (v8i16 LSX128H:$vk)), ++ (VFCVTH_S_H LSX128H:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcvtl_d_s (v4f32 LSX128W:$vj)), ++ (VFCVTL_D_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vfcvth_d_s (v4f32 LSX128W:$vj)), ++ (VFCVTH_D_S LSX128W:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vftint_w_s (v4f32 LSX128W:$vj)), ++ (VFTINT_W_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vftint_l_d (v2f64 LSX128D:$vj)), ++ (VFTINT_L_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vftint_wu_s (v4f32 LSX128W:$vj)), ++ (VFTINT_WU_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vftint_lu_d (v2f64 LSX128D:$vj)), ++ (VFTINT_LU_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vreplgr2vr_b GPR32Opnd:$rj), ++ (VREPLGR2VR_B GPR32Opnd:$rj)>; ++def : LSXPat<(int_loongarch_lsx_vreplgr2vr_h GPR32Opnd:$rj), ++ (VREPLGR2VR_H GPR32Opnd:$rj)>; ++def : LSXPat<(int_loongarch_lsx_vreplgr2vr_w GPR32Opnd:$rj), ++ (VREPLGR2VR_W GPR32Opnd:$rj)>; ++def : LSXPat<(int_loongarch_lsx_vreplgr2vr_d GPR64Opnd:$rj), ++ (VREPLGR2VR_D GPR64Opnd:$rj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrlri_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), ++ (VSRLRI_B LSX128B:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vsrlri_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), ++ (VSRLRI_H LSX128H:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsrlri_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), ++ (VSRLRI_W LSX128W:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsrlri_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), ++ (VSRLRI_D LSX128D:$vj, uimm6:$ui6)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrari_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), ++ (VSRARI_B LSX128B:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vsrari_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), ++ (VSRARI_H LSX128H:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsrari_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), ++ (VSRARI_W LSX128W:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsrari_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), ++ (VSRARI_D LSX128D:$vj, uimm6:$ui6)>; ++ ++def : LSXPat<(int_loongarch_lsx_vinsgr2vr_b (v16i8 LSX128B:$vj), GPR32Opnd:$rj, (immZExt4:$ui4)), ++ (VINSGR2VR_B LSX128B:$vj, GPR32Opnd:$rj, (uimm4i:$ui4))>; ++def : LSXPat<(int_loongarch_lsx_vinsgr2vr_h (v8i16 LSX128H:$vj), GPR32Opnd:$rj, (immZExt3:$ui3)), ++ (VINSGR2VR_H LSX128H:$vj, GPR32Opnd:$rj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vinsgr2vr_w (v4i32 LSX128W:$vj), GPR32Opnd:$rj, (immZExt2:$ui2)), ++ (VINSGR2VR_W LSX128W:$vj, GPR32Opnd:$rj, uimm2:$ui2)>; ++def : LSXPat<(int_loongarch_lsx_vinsgr2vr_d (v2i64 LSX128D:$vj), GPR64Opnd:$rj, (immZExt1:$ui1)), ++ (VINSGR2VR_D LSX128D:$vj, GPR64Opnd:$rj, uimm1i:$ui1)>; ++ ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_b (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VPICKVE2GR_B LSX128B:$vj, (uimm4i:$ui4))>; ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_h (v8i16 LSX128H:$vj), (immZExt3:$ui3)), ++ (VPICKVE2GR_H LSX128H:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_w (v4i32 LSX128W:$vj), (immZExt2:$ui2)), ++ (VPICKVE2GR_W LSX128W:$vj, uimm2:$ui2)>; ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_d (v2i64 LSX128D:$vj), (immZExt1:$ui1)), ++ (VPICKVE2GR_D LSX128D:$vj, uimm1i:$ui1)>; ++ ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_bu (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VPICKVE2GR_BU LSX128B:$vj, (uimm4i:$ui4))>; ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_hu (v8i16 LSX128H:$vj), (immZExt3:$ui3)), ++ (VPICKVE2GR_HU LSX128H:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vpickve2gr_wu (v4i32 LSX128W:$vj), (immZExt2:$ui2)), ++ (VPICKVE2GR_WU LSX128W:$vj, uimm2:$ui2)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsat_b (v16i8 LSX128B:$vj), (immZExt3:$ui3)), ++ (VSAT_B LSX128B:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vsat_h (v8i16 LSX128H:$vj), (immZExt4:$ui4)), ++ (VSAT_H LSX128H:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsat_w (v4i32 LSX128W:$vj), (immZExt5:$ui5)), ++ (VSAT_W LSX128W:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsat_d (v2i64 LSX128D:$vj), (immZExt6:$ui6)), ++ (VSAT_D LSX128D:$vj, uimm6:$ui6)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsat_bu (v16i8 LSX128B:$vj), (immZExt3:$ui3)), ++ (VSAT_BU LSX128B:$vj, uimm3:$ui3)>; ++def : LSXPat<(int_loongarch_lsx_vsat_hu (v8i16 LSX128H:$vj), (immZExt4:$ui4)), ++ (VSAT_HU LSX128H:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsat_wu (v4i32 LSX128W:$vj), (immZExt5:$ui5)), ++ (VSAT_WU LSX128W:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsat_du (v2i64 LSX128D:$vj), (immZExt6:$ui6)), ++ (VSAT_DU LSX128D:$vj, uimm6:$ui6)>; ++ ++def : LSXPat<(int_loongarch_lsx_vmskltz_b (v16i8 LSX128B:$vj)), ++ (VMSKLTZ_B LSX128B:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vmskltz_h (v8i16 LSX128H:$vj)), ++ (VMSKLTZ_H LSX128H:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vmskltz_w (v4i32 LSX128W:$vj)), ++ (VMSKLTZ_W LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vmskltz_d (v2i64 LSX128D:$vj)), ++ (VMSKLTZ_D LSX128D:$vj)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrlni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSRLNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsrlni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSRLNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsrlni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSRLNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vsrlni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSRLNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrlni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRLNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRLNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRLNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRLNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrlni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRLNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRLNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRLNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrlni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRLNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrlrni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRLRNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrlrni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRLRNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrlrni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRLRNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrlrni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRLRNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vsrarni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSRARNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vsrarni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSRARNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vsrarni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSRARNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vsrarni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSRARNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrani_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRANI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRANI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRANI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRANI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrani_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRANI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRANI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRANI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrani_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRANI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrarni_b_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRARNI_B_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_h_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRARNI_H_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_w_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRARNI_W_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_d_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRARNI_D_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(int_loongarch_lsx_vssrarni_bu_h (v16i8 LSX128B:$vd_in), (v16i8 LSX128B:$vj), (immZExt4:$ui4)), ++ (VSSRARNI_BU_H LSX128B:$vd_in, LSX128B:$vj, uimm4i:$ui4)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_hu_w (v8i16 LSX128H:$vd_in), (v8i16 LSX128H:$vj), (immZExt5:$ui5)), ++ (VSSRARNI_HU_W LSX128H:$vd_in, LSX128H:$vj, uimm5:$ui5)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_wu_d (v4i32 LSX128W:$vd_in), (v4i32 LSX128W:$vj), (immZExt6:$ui6)), ++ (VSSRARNI_WU_D LSX128W:$vd_in, LSX128W:$vj, uimm6:$ui6)>; ++def : LSXPat<(int_loongarch_lsx_vssrarni_du_q (v2i64 LSX128D:$vd_in), (v2i64 LSX128D:$vj), (immZExt7:$ui7)), ++ (VSSRARNI_DU_Q LSX128D:$vd_in, LSX128D:$vj, uimm7i:$ui7)>; ++ ++def : LSXPat<(load (add iPTR:$vj, GPR64Opnd:$vk)), ++ (VLDX PtrRC:$vj, GPR64Opnd:$vk)>; ++ ++def : LSXPat<(store (v16i8 LSX128B:$vd), (add iPTR:$vj, GPR64Opnd:$vk)), ++ (VSTX LSX128B:$vd, PtrRC:$vj, GPR64Opnd:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vshuf_b (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk), (v16i8 LSX128B:$va)), ++ (VSHUF_B LSX128B:$vj, LSX128B:$vk, LSX128B:$va)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_ceq_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CEQ_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_ceq_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CEQ_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cor_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_COR_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cor_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_COR_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cun_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CUN_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cun_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CUN_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cune_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CUNE_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cune_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CUNE_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cueq_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CUEQ_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cueq_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CUEQ_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cne_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CNE_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cne_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CNE_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_clt_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CLT_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_clt_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CLT_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cult_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CULT_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cult_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CULT_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cle_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CLE_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cle_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CLE_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vfcmp_cule_s (v4f32 LSX128W:$vj), (v4f32 LSX128W:$vk)), ++ (VFCMP_CULE_S LSX128W:$vj, LSX128W:$vk)>; ++def : LSXPat<(int_loongarch_lsx_vfcmp_cule_d (v2f64 LSX128D:$vj), (v2f64 LSX128D:$vk)), ++ (VFCMP_CULE_D LSX128D:$vj, LSX128D:$vk)>; ++ ++def : LSXPat<(int_loongarch_lsx_vftintrz_w_s (v4f32 LSX128W:$vj)), ++ (VFTINTRZ_W_S LSX128W:$vj)>; ++def : LSXPat<(int_loongarch_lsx_vftintrz_l_d (v2f64 LSX128D:$vj)), ++ (VFTINTRZ_L_D LSX128D:$vj)>; ++ ++ ++def imm_mask : ImmLeaf(Imm) && Imm == -1;}]>; ++def imm_mask_64 : ImmLeaf(Imm) && Imm == -1;}]>; ++ ++ ++def : LSXPat<(xor (v8i16 LSX128H:$vj), (vsplati16 imm_mask)), ++ (NOR_V_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vj))>; ++ ++def : LSXPat<(xor (v4i32 LSX128W:$vj), (vsplati32 imm_mask)), ++ (NOR_V_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vj))>; ++ ++def : LSXPat<(xor (v2i64 LSX128D:$vj), (vsplati64 imm_mask_64)), ++ (NOR_V_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vj))>; ++ ++ ++def : LSXPat<(and ++ (v16i8 (xor (v16i8 LSX128B:$vj),(vsplati8 imm_mask))), ++ (v16i8 LSX128B:$vk) ++ ), ++ (VANDN_V (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk))>; ++ ++def : LSXPat<(and ++ (v8i16 (xor (v8i16 LSX128H:$vj), (vsplati16 imm_mask))), ++ (v8i16 LSX128H:$vk) ++ ), ++ (VANDN_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk))>; ++ ++def : LSXPat<(and ++ (v4i32 (xor (v4i32 LSX128W:$vj), (vsplati32 imm_mask))), ++ (v4i32 LSX128W:$vk) ++ ), ++ (VANDN_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk))>; ++ ++def : LSXPat<(and ++ (v2i64 (xor (v2i64 LSX128D:$vj), (vsplati64 imm_mask_64))), ++ (v2i64 LSX128D:$vk) ++ ), ++ (VANDN_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk))>; ++ ++ ++def : LSXPat<(or ++ (v16i8 LSX128B:$vj), ++ (v16i8 (xor (v16i8 LSX128B:$vk), (vsplati8 imm_mask))) ++ ), ++ (VORN_V (v16i8 LSX128B:$vj), (v16i8 LSX128B:$vk))>; ++ ++def : LSXPat<(or ++ (v8i16 LSX128H:$vj), ++ (v8i16 (xor (v8i16 LSX128H:$vk), (vsplati16 imm_mask))) ++ ), ++ (VORN_H_PSEUDO (v8i16 LSX128H:$vj), (v8i16 LSX128H:$vk))>; ++ ++def : LSXPat<(or ++ (v4i32 LSX128W:$vj), ++ (v4i32 (xor (v4i32 LSX128W:$vk), (vsplati32 imm_mask))) ++ ), ++ (VORN_W_PSEUDO (v4i32 LSX128W:$vj), (v4i32 LSX128W:$vk))>; ++ ++def : LSXPat<(or ++ (v2i64 LSX128D:$vj), ++ (v2i64 (xor (v2i64 LSX128D:$vk), (vsplati64 imm_mask_64))) ++ ), ++ (VORN_D_PSEUDO (v2i64 LSX128D:$vj), (v2i64 LSX128D:$vk))>; ++ ++ ++def : LSXPat<(add (v2i64 (abs LSX128D:$a)), (v2i64 (abs LSX128D:$b))), ++ (VADDA_D (v2i64 LSX128D:$a),(v2i64 LSX128D:$b))>; ++ ++def : LSXPat<(add (v4i32 (abs LSX128W:$a)), (v4i32 (abs LSX128W:$b))), ++ (VADDA_W (v4i32 LSX128W:$a),(v4i32 LSX128W:$b))>; ++ ++def : LSXPat<(add (v8i16 (abs LSX128H:$a)), (v8i16 (abs LSX128H:$b))), ++ (VADDA_H (v8i16 LSX128H:$a),(v8i16 LSX128H:$b))>; ++ ++def : LSXPat<(add (v16i8 (abs LSX128B:$a)), (v16i8 (abs LSX128B:$b))), ++ (VADDA_B (v16i8 LSX128B:$a),(v16i8 LSX128B:$b))>; ++ ++ ++def : LSXPat<(and v16i8:$vj, (xor (shl vsplat_imm_eq_1, v16i8:$vk), ++ (vsplati8 imm_mask))), ++ (VBITCLR_B v16i8:$vj, v16i8:$vk)>; ++ ++def : LSXPat<(and v8i16:$vj, (xor (shl vsplat_imm_eq_1, v8i16:$vk), ++ (vsplati16 imm_mask))), ++ (VBITCLR_H v8i16:$vj, v8i16:$vk)>; ++ ++def : LSXPat<(and v4i32:$vj, (xor (shl vsplat_imm_eq_1, v4i32:$vk), ++ (vsplati32 imm_mask))), ++ (VBITCLR_W v4i32:$vj, v4i32:$vk)>; ++ ++def : LSXPat<(and v2i64:$vj, (xor (shl vsplat_imm_eq_1, v2i64:$vk), ++ (vsplati64 imm_mask_64))), ++ (VBITCLR_D v2i64:$vj, v2i64:$vk)>; +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +index 488c66f47..bf70b09d4 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +@@ -1,4 +1,4 @@ +-//=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=// ++//===- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to MCInst ----------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,86 +6,337 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file contains code to lower LoongArch MachineInstrs to their +-// corresponding MCInst records. ++// This file contains code to lower LoongArch MachineInstrs to their corresponding ++// MCInst records. + // + //===----------------------------------------------------------------------===// + +-#include "LoongArch.h" +-#include "LoongArchSubtarget.h" +-#include "llvm/CodeGen/AsmPrinter.h" ++#include "LoongArchMCInstLower.h" ++#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" ++#include "LoongArchAsmPrinter.h" + #include "llvm/CodeGen/MachineBasicBlock.h" + #include "llvm/CodeGen/MachineInstr.h" +-#include "llvm/MC/MCAsmInfo.h" +-#include "llvm/MC/MCContext.h" +-#include "llvm/Support/raw_ostream.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/Support/ErrorHandling.h" ++#include + + using namespace llvm; + +-static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, +- const AsmPrinter &AP) { +- MCContext &Ctx = AP.OutContext; ++LoongArchMCInstLower::LoongArchMCInstLower(LoongArchAsmPrinter &asmprinter) ++ : AsmPrinter(asmprinter) {} + +- // TODO: Processing target flags. ++void LoongArchMCInstLower::Initialize(MCContext *C) { ++ Ctx = C; ++} + +- const MCExpr *ME = +- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); ++MCOperand LoongArchMCInstLower::LowerSymbolOperand(const MachineOperand &MO, ++ MachineOperandType MOTy, ++ unsigned Offset) const { ++ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; ++ LoongArchMCExpr::LoongArchExprKind TargetKind = LoongArchMCExpr::MEK_None; ++ const MCSymbol *Symbol; + +- if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) +- ME = MCBinaryExpr::createAdd( +- ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); ++ switch(MO.getTargetFlags()) { ++ default: ++ llvm_unreachable("Invalid target flag!"); ++ case LoongArchII::MO_NO_FLAG: ++ break; ++ case LoongArchII::MO_GOT_HI: ++ TargetKind = LoongArchMCExpr::MEK_GOT_HI; ++ break; ++ case LoongArchII::MO_GOT_LO: ++ TargetKind = LoongArchMCExpr::MEK_GOT_LO; ++ break; ++ case LoongArchII::MO_GOT_RRHI: ++ TargetKind = LoongArchMCExpr::MEK_GOT_RRHI; ++ break; ++ case LoongArchII::MO_GOT_RRHIGHER: ++ TargetKind = LoongArchMCExpr::MEK_GOT_RRHIGHER; ++ break; ++ case LoongArchII::MO_GOT_RRHIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_GOT_RRHIGHEST; ++ break; ++ case LoongArchII::MO_GOT_RRLO: ++ TargetKind = LoongArchMCExpr::MEK_GOT_RRLO; ++ break; ++ case LoongArchII::MO_PCREL_HI: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_HI; ++ break; ++ case LoongArchII::MO_PCREL_LO: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_LO; ++ break; ++ case LoongArchII::MO_PCREL_RRHI: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHI; ++ break; ++ case LoongArchII::MO_PCREL_RRHIGHER: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHIGHER; ++ break; ++ case LoongArchII::MO_PCREL_RRHIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_RRHIGHEST; ++ break; ++ case LoongArchII::MO_PCREL_RRLO: ++ TargetKind = LoongArchMCExpr::MEK_PCREL_RRLO; ++ break; ++ case LoongArchII::MO_TLSIE_HI: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_HI; ++ break; ++ case LoongArchII::MO_TLSIE_LO: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_LO; ++ break; ++ case LoongArchII::MO_TLSIE_RRHI: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHI; ++ break; ++ case LoongArchII::MO_TLSIE_RRHIGHER: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHIGHER; ++ break; ++ case LoongArchII::MO_TLSIE_RRHIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRHIGHEST; ++ break; ++ case LoongArchII::MO_TLSIE_RRLO: ++ TargetKind = LoongArchMCExpr::MEK_TLSIE_RRLO; ++ break; ++ case LoongArchII::MO_TLSLE_HI: ++ TargetKind = LoongArchMCExpr::MEK_TLSLE_HI; ++ break; ++ case LoongArchII::MO_TLSLE_HIGHER: ++ TargetKind = LoongArchMCExpr::MEK_TLSLE_HIGHER; ++ break; ++ case LoongArchII::MO_TLSLE_HIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_TLSLE_HIGHEST; ++ break; ++ case LoongArchII::MO_TLSLE_LO: ++ TargetKind = LoongArchMCExpr::MEK_TLSLE_LO; ++ break; ++ case LoongArchII::MO_TLSGD_HI: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_HI; ++ break; ++ case LoongArchII::MO_TLSGD_LO: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_LO; ++ break; ++ case LoongArchII::MO_TLSGD_RRHI: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHI; ++ break; ++ case LoongArchII::MO_TLSGD_RRHIGHER: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHIGHER; ++ break; ++ case LoongArchII::MO_TLSGD_RRHIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRHIGHEST; ++ break; ++ case LoongArchII::MO_TLSGD_RRLO: ++ TargetKind = LoongArchMCExpr::MEK_TLSGD_RRLO; ++ break; ++ case LoongArchII::MO_ABS_HI: ++ TargetKind = LoongArchMCExpr::MEK_ABS_HI; ++ break; ++ case LoongArchII::MO_ABS_HIGHER: ++ TargetKind = LoongArchMCExpr::MEK_ABS_HIGHER; ++ break; ++ case LoongArchII::MO_ABS_HIGHEST: ++ TargetKind = LoongArchMCExpr::MEK_ABS_HIGHEST; ++ break; ++ case LoongArchII::MO_ABS_LO: ++ TargetKind = LoongArchMCExpr::MEK_ABS_LO; ++ break; ++ case LoongArchII::MO_CALL_HI: ++ TargetKind = LoongArchMCExpr::MEK_CALL_HI; ++ break; ++ case LoongArchII::MO_CALL_LO: ++ TargetKind = LoongArchMCExpr::MEK_CALL_LO; ++ break; ++ } + +- return MCOperand::createExpr(ME); +-} ++ switch (MOTy) { ++ case MachineOperand::MO_MachineBasicBlock: ++ Symbol = MO.getMBB()->getSymbol(); ++ break; ++ ++ case MachineOperand::MO_GlobalAddress: ++ Symbol = AsmPrinter.getSymbol(MO.getGlobal()); ++ Offset += MO.getOffset(); ++ break; ++ ++ case MachineOperand::MO_BlockAddress: ++ Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); ++ Offset += MO.getOffset(); ++ break; ++ ++ case MachineOperand::MO_ExternalSymbol: ++ Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); ++ Offset += MO.getOffset(); ++ break; ++ ++ case MachineOperand::MO_MCSymbol: ++ Symbol = MO.getMCSymbol(); ++ Offset += MO.getOffset(); ++ break; ++ ++ case MachineOperand::MO_JumpTableIndex: ++ Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); ++ break; ++ ++ case MachineOperand::MO_ConstantPoolIndex: ++ Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); ++ Offset += MO.getOffset(); ++ break; + +-bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, +- MCOperand &MCOp, +- const AsmPrinter &AP) { +- switch (MO.getType()) { + default: +- report_fatal_error( +- "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); ++ llvm_unreachable(""); ++ } ++ ++ const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); ++ ++ if (Offset) { ++ // Assume offset is never negative. ++ assert(Offset > 0); ++ ++ Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), ++ *Ctx); ++ } ++ ++ if (TargetKind != LoongArchMCExpr::MEK_None) ++ Expr = LoongArchMCExpr::create(TargetKind, Expr, *Ctx); ++ ++ return MCOperand::createExpr(Expr); ++} ++ ++MCOperand LoongArchMCInstLower::LowerOperand(const MachineOperand &MO, ++ unsigned offset) const { ++ MachineOperandType MOTy = MO.getType(); ++ ++ switch (MOTy) { ++ default: llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. +- if (MO.isImplicit()) +- return false; +- MCOp = MCOperand::createReg(MO.getReg()); +- break; +- case MachineOperand::MO_RegisterMask: +- // Regmasks are like implicit defs. +- return false; ++ if (MO.isImplicit()) break; ++ return MCOperand::createReg(MO.getReg()); + case MachineOperand::MO_Immediate: +- MCOp = MCOperand::createImm(MO.getImm()); +- break; ++ return MCOperand::createImm(MO.getImm() + offset); ++ case MachineOperand::MO_MachineBasicBlock: ++ case MachineOperand::MO_GlobalAddress: ++ case MachineOperand::MO_ExternalSymbol: ++ case MachineOperand::MO_MCSymbol: ++ case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ConstantPoolIndex: +- MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); ++ case MachineOperand::MO_BlockAddress: ++ return LowerSymbolOperand(MO, MOTy, offset); ++ case MachineOperand::MO_RegisterMask: + break; +- case MachineOperand::MO_GlobalAddress: +- MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); ++ } ++ ++ return MCOperand(); ++} ++ ++MCOperand LoongArchMCInstLower::createSub(MachineBasicBlock *BB1, ++ MachineBasicBlock *BB2, ++ LoongArchMCExpr::LoongArchExprKind Kind) const { ++ const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); ++ const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); ++ const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); ++ ++ return MCOperand::createExpr(LoongArchMCExpr::create(Kind, Sub, *Ctx)); ++} ++ ++void LoongArchMCInstLower::lowerLongBranchADDI(const MachineInstr *MI, ++ MCInst &OutMI, int Opcode) const { ++ OutMI.setOpcode(Opcode); ++ ++ LoongArchMCExpr::LoongArchExprKind Kind; ++ unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); ++ switch (TargetFlags) { ++ case LoongArchII::MO_ABS_HIGHEST: ++ Kind = LoongArchMCExpr::MEK_ABS_HIGHEST; + break; +- case MachineOperand::MO_MachineBasicBlock: +- MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); ++ case LoongArchII::MO_ABS_HIGHER: ++ Kind = LoongArchMCExpr::MEK_ABS_HIGHER; + break; +- case MachineOperand::MO_ExternalSymbol: +- MCOp = lowerSymbolOperand( +- MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); ++ case LoongArchII::MO_ABS_HI: ++ Kind = LoongArchMCExpr::MEK_ABS_HI; + break; +- // TODO: lower special operands +- case MachineOperand::MO_BlockAddress: +- case MachineOperand::MO_JumpTableIndex: ++ case LoongArchII::MO_ABS_LO: ++ Kind = LoongArchMCExpr::MEK_ABS_LO; + break; ++ default: ++ report_fatal_error("Unexpected flags for lowerLongBranchADDI"); ++ } ++ ++ // Lower two register operands. ++ for (unsigned I = 0, E = 2; I != E; ++I) { ++ const MachineOperand &MO = MI->getOperand(I); ++ OutMI.addOperand(LowerOperand(MO)); ++ } ++ ++ if (MI->getNumOperands() == 3) { ++ // Lower register operand. ++ const MCExpr *Expr = ++ MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); ++ const LoongArchMCExpr *LoongArchExpr = LoongArchMCExpr::create(Kind, Expr, *Ctx); ++ OutMI.addOperand(MCOperand::createExpr(LoongArchExpr)); ++ } else if (MI->getNumOperands() == 4) { ++ // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). ++ OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), ++ MI->getOperand(3).getMBB(), Kind)); + } +- return true; + } + +-bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, +- MCInst &OutMI, AsmPrinter &AP) { ++void LoongArchMCInstLower::lowerLongBranchPCADDU12I(const MachineInstr *MI, ++ MCInst &OutMI, int Opcode) const { ++ OutMI.setOpcode(Opcode); ++ ++ LoongArchMCExpr::LoongArchExprKind Kind; ++ unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); ++ switch (TargetFlags) { ++ case LoongArchII::MO_PCREL_HI: ++ Kind = LoongArchMCExpr::MEK_PCREL_HI; ++ break; ++ case LoongArchII::MO_PCREL_LO: ++ Kind = LoongArchMCExpr::MEK_PCREL_LO; ++ break; ++ default: ++ report_fatal_error("Unexpected flags for lowerLongBranchADDI"); ++ } ++ ++ // Lower one register operands. ++ const MachineOperand &MO = MI->getOperand(0); ++ OutMI.addOperand(LowerOperand(MO)); ++ ++ const MCExpr *Expr = ++ MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); ++ const LoongArchMCExpr *LoongArchExpr = LoongArchMCExpr::create(Kind, Expr, *Ctx); ++ OutMI.addOperand(MCOperand::createExpr(LoongArchExpr)); ++} ++bool LoongArchMCInstLower::lowerLongBranch(const MachineInstr *MI, ++ MCInst &OutMI) const { ++ switch (MI->getOpcode()) { ++ default: ++ return false; ++ case LoongArch::LONG_BRANCH_ADDIW: ++ case LoongArch::LONG_BRANCH_ADDIW2Op: ++ lowerLongBranchADDI(MI, OutMI, LoongArch::ADDI_W); ++ return true; ++ case LoongArch::LONG_BRANCH_ADDID: ++ case LoongArch::LONG_BRANCH_ADDID2Op: ++ lowerLongBranchADDI(MI, OutMI, LoongArch::ADDI_D); ++ return true; ++ case LoongArch::LONG_BRANCH_PCADDU12I: ++ lowerLongBranchPCADDU12I(MI, OutMI, LoongArch::PCADDU12I); ++ return true; ++ } ++} ++ ++void LoongArchMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { ++ if (lowerLongBranch(MI, OutMI)) ++ return; ++ + OutMI.setOpcode(MI->getOpcode()); + +- for (const MachineOperand &MO : MI->operands()) { +- MCOperand MCOp; +- if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) ++ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { ++ const MachineOperand &MO = MI->getOperand(i); ++ MCOperand MCOp = LowerOperand(MO); ++ ++ if (MCOp.isValid()) + OutMI.addOperand(MCOp); + } +- return false; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h +new file mode 100644 +index 000000000..6463a7b64 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.h +@@ -0,0 +1,55 @@ ++//===- LoongArchMCInstLower.h - Lower MachineInstr to MCInst --------*- C++ -*--===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H ++#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H ++ ++#include "MCTargetDesc/LoongArchMCExpr.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/Support/Compiler.h" ++ ++namespace llvm { ++ ++class MachineBasicBlock; ++class MachineInstr; ++class MCContext; ++class MCInst; ++class MCOperand; ++class LoongArchAsmPrinter; ++ ++/// LoongArchMCInstLower - This class is used to lower an MachineInstr into an ++/// MCInst. ++class LLVM_LIBRARY_VISIBILITY LoongArchMCInstLower { ++ using MachineOperandType = MachineOperand::MachineOperandType; ++ ++ MCContext *Ctx; ++ LoongArchAsmPrinter &AsmPrinter; ++ ++public: ++ LoongArchMCInstLower(LoongArchAsmPrinter &asmprinter); ++ ++ void Initialize(MCContext *C); ++ void Lower(const MachineInstr *MI, MCInst &OutMI) const; ++ MCOperand LowerOperand(const MachineOperand& MO, unsigned offset = 0) const; ++ ++private: ++ MCOperand LowerSymbolOperand(const MachineOperand &MO, ++ MachineOperandType MOTy, unsigned Offset) const; ++ MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, ++ LoongArchMCExpr::LoongArchExprKind Kind) const; ++ void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; ++ void lowerLongBranchADDI(const MachineInstr *MI, MCInst &OutMI, ++ int Opcode) const; ++ void lowerLongBranchPCADDU12I(const MachineInstr *MI, MCInst &OutMI, ++ int Opcode) const; ++ bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const; ++}; ++ ++} // end namespace llvm ++ ++#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMCINSTLOWER_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp +new file mode 100644 +index 000000000..a9c52cbb1 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.cpp +@@ -0,0 +1,58 @@ ++//===-- LoongArchMachineFunctionInfo.cpp - Private data used for LoongArch ----------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchMachineFunction.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "LoongArchSubtarget.h" ++#include "LoongArchTargetMachine.h" ++#include "llvm/CodeGen/MachineFrameInfo.h" ++#include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/PseudoSourceValue.h" ++#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "llvm/Support/CommandLine.h" ++ ++using namespace llvm; ++ ++LoongArchFunctionInfo::~LoongArchFunctionInfo() = default; ++ ++void LoongArchFunctionInfo::createEhDataRegsFI() { ++ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); ++ for (int I = 0; I < 4; ++I) { ++ const TargetRegisterClass &RC = ++ static_cast(MF.getTarget()).getABI().IsLP64() ++ ? LoongArch::GPR64RegClass ++ : LoongArch::GPR32RegClass; ++ ++ EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC), ++ TRI.getSpillAlign(RC), false); ++ } ++} ++ ++bool LoongArchFunctionInfo::isEhDataRegFI(int FI) const { ++ return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1] ++ || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]); ++} ++ ++MachinePointerInfo LoongArchFunctionInfo::callPtrInfo(const char *ES) { ++ return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)); ++} ++ ++MachinePointerInfo LoongArchFunctionInfo::callPtrInfo(const GlobalValue *GV) { ++ return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV)); ++} ++ ++int LoongArchFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { ++ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); ++ if (MoveF64ViaSpillFI == -1) { ++ MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject( ++ TRI.getSpillSize(*RC), TRI.getSpillAlign(*RC), false); ++ } ++ return MoveF64ViaSpillFI; ++} ++ ++void LoongArchFunctionInfo::anchor() {} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h +new file mode 100644 +index 000000000..1765013ea +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunction.h +@@ -0,0 +1,103 @@ ++//===- LoongArchMachineFunctionInfo.h - Private data used for LoongArch ---*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file declares the LoongArch specific subclass of MachineFunctionInfo. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H ++#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H ++ ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineMemOperand.h" ++#include ++ ++namespace llvm { ++ ++/// LoongArchFunctionInfo - This class is derived from MachineFunction private ++/// LoongArch target-specific information for each MachineFunction. ++class LoongArchFunctionInfo : public MachineFunctionInfo { ++public: ++ LoongArchFunctionInfo(MachineFunction &MF) : MF(MF) {} ++ ++ ~LoongArchFunctionInfo() override; ++ ++ unsigned getSRetReturnReg() const { return SRetReturnReg; } ++ void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } ++ ++ int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } ++ void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } ++ ++ unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; } ++ void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; } ++ ++ bool hasByvalArg() const { return HasByvalArg; } ++ void setFormalArgInfo(unsigned Size, bool HasByval) { ++ IncomingArgSize = Size; ++ HasByvalArg = HasByval; ++ } ++ ++ unsigned getIncomingArgSize() const { return IncomingArgSize; } ++ ++ bool callsEhReturn() const { return CallsEhReturn; } ++ void setCallsEhReturn() { CallsEhReturn = true; } ++ ++ void createEhDataRegsFI(); ++ int getEhDataRegFI(unsigned Reg) const { return EhDataRegFI[Reg]; } ++ bool isEhDataRegFI(int FI) const; ++ ++ /// Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue ++ /// object representing a GOT entry for an external function. ++ MachinePointerInfo callPtrInfo(const char *ES); ++ ++ /// Create a MachinePointerInfo that has a GlobalValuePseudoSourceValue object ++ /// representing a GOT entry for a global function. ++ MachinePointerInfo callPtrInfo(const GlobalValue *GV); ++ ++ void setSaveS2() { SaveS2 = true; } ++ bool hasSaveS2() const { return SaveS2; } ++ ++ int getMoveF64ViaSpillFI(const TargetRegisterClass *RC); ++ ++private: ++ virtual void anchor(); ++ ++ MachineFunction& MF; ++ ++ /// SRetReturnReg - Some subtargets require that sret lowering includes ++ /// returning the value of the returned struct in a register. This field ++ /// holds the virtual register into which the sret argument is passed. ++ unsigned SRetReturnReg = 0; ++ ++ /// VarArgsFrameIndex - FrameIndex for start of varargs area. ++ int VarArgsFrameIndex = 0; ++ int VarArgsSaveSize = 0; ++ ++ /// True if function has a byval argument. ++ bool HasByvalArg; ++ ++ /// Size of incoming argument area. ++ unsigned IncomingArgSize; ++ ++ /// CallsEhReturn - Whether the function calls llvm.eh.return. ++ bool CallsEhReturn = false; ++ ++ /// Frame objects for spilling eh data registers. ++ int EhDataRegFI[4]; ++ ++ // saveS2 ++ bool SaveS2 = false; ++ ++ /// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the ++ /// LP32 FPXX ABI is enabled. -1 is used to denote invalid index. ++ int MoveF64ViaSpillFI = -1; ++}; ++ ++} // end namespace llvm ++ ++#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTION_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h +deleted file mode 100644 +index d4a6c884b..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h ++++ /dev/null +@@ -1,57 +0,0 @@ +-//=- LoongArchMachineFunctionInfo.h - LoongArch machine function info -----===// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +-// +-// This file declares LoongArch-specific per-machine-function information. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H +-#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H +- +-#include "LoongArchSubtarget.h" +-#include "llvm/CodeGen/MachineFrameInfo.h" +-#include "llvm/CodeGen/MachineFunction.h" +- +-namespace llvm { +- +-/// LoongArchMachineFunctionInfo - This class is derived from +-/// MachineFunctionInfo and contains private LoongArch-specific information for +-/// each MachineFunction. +-class LoongArchMachineFunctionInfo : public MachineFunctionInfo { +-private: +- /// FrameIndex for start of varargs area +- int VarArgsFrameIndex = 0; +- /// Size of the save area used for varargs +- int VarArgsSaveSize = 0; +- +- /// Size of stack frame to save callee saved registers +- unsigned CalleeSavedStackSize = 0; +- +-public: +- LoongArchMachineFunctionInfo(const MachineFunction &MF) {} +- +- MachineFunctionInfo * +- clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, +- const DenseMap &Src2DstMBB) +- const override { +- return DestMF.cloneInfo(*this); +- } +- +- int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } +- void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } +- +- unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; } +- void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; } +- +- unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; } +- void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; } +-}; +- +-} // end namespace llvm +- +-#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp +new file mode 100644 +index 000000000..8dbf30f21 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp +@@ -0,0 +1,53 @@ ++//===----------------------------------------------------------------------===// ++// Instruction Selector Subtarget Control ++//===----------------------------------------------------------------------===// ++ ++//===----------------------------------------------------------------------===// ++// This file defines a pass used to change the subtarget for the ++// LoongArch Instruction selector. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArch.h" ++#include "LoongArchTargetMachine.h" ++#include "llvm/CodeGen/TargetPassConfig.h" ++#include "llvm/CodeGen/StackProtector.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/raw_ostream.h" ++ ++using namespace llvm; ++ ++#define DEBUG_TYPE "loongarch-isel" ++ ++namespace { ++ class LoongArchModuleDAGToDAGISel : public MachineFunctionPass { ++ public: ++ static char ID; ++ ++ LoongArchModuleDAGToDAGISel() : MachineFunctionPass(ID) {} ++ ++ // Pass Name ++ StringRef getPassName() const override { ++ return "LoongArch DAG->DAG Pattern Instruction Selection"; ++ } ++ ++ void getAnalysisUsage(AnalysisUsage &AU) const override { ++ AU.addRequired(); ++ AU.addPreserved(); ++ MachineFunctionPass::getAnalysisUsage(AU); ++ } ++ ++ bool runOnMachineFunction(MachineFunction &MF) override; ++ }; ++ ++ char LoongArchModuleDAGToDAGISel::ID = 0; ++} ++ ++bool LoongArchModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { ++ LLVM_DEBUG(errs() << "In LoongArchModuleDAGToDAGISel::runMachineFunction\n"); ++ return false; ++} ++ ++llvm::FunctionPass *llvm::createLoongArchModuleISelDagPass() { ++ return new LoongArchModuleDAGToDAGISel(); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp +index 05902ebb7..4d1a3cf22 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp +@@ -1,4 +1,4 @@ +-//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=// ++//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,132 +6,352 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file contains the LoongArch implementation of the TargetRegisterInfo +-// class. ++// This file contains the LoongArch implementation of the TargetRegisterInfo class. + // + //===----------------------------------------------------------------------===// + + #include "LoongArchRegisterInfo.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" + #include "LoongArch.h" ++#include "LoongArchMachineFunction.h" + #include "LoongArchSubtarget.h" ++#include "LoongArchTargetMachine.h" ++#include "llvm/ADT/BitVector.h" ++#include "llvm/ADT/STLExtras.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineFunction.h" +-#include "llvm/CodeGen/MachineInstrBuilder.h" +-#include "llvm/CodeGen/RegisterScavenging.h" ++#include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineRegisterInfo.h" + #include "llvm/CodeGen/TargetFrameLowering.h" +-#include "llvm/CodeGen/TargetInstrInfo.h" ++#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "llvm/CodeGen/TargetSubtargetInfo.h" ++#include "llvm/IR/Function.h" ++#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/Support/Debug.h" + #include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/raw_ostream.h" ++#include + + using namespace llvm; + ++#define DEBUG_TYPE "loongarch-reg-info" ++ + #define GET_REGINFO_TARGET_DESC + #include "LoongArchGenRegisterInfo.inc" + +-LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode) +- : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0, +- /*EHFlavor*/ 0, +- /*PC*/ 0, HwMode) {} ++LoongArchRegisterInfo::LoongArchRegisterInfo() : LoongArchGenRegisterInfo(LoongArch::RA) {} + +-const MCPhysReg * +-LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { +- auto &Subtarget = MF->getSubtarget(); ++unsigned LoongArchRegisterInfo::getPICCallReg() { return LoongArch::T8; } ++ ++const TargetRegisterClass * ++LoongArchRegisterInfo::getPointerRegClass(const MachineFunction &MF, ++ unsigned Kind) const { ++ LoongArchABIInfo ABI = MF.getSubtarget().getABI(); ++ LoongArchPtrClass PtrClassKind = static_cast(Kind); ++ ++ switch (PtrClassKind) { ++ case LoongArchPtrClass::Default: ++ return ABI.ArePtrs64bit() ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ case LoongArchPtrClass::StackPointer: ++ return ABI.ArePtrs64bit() ? &LoongArch::SP64RegClass : &LoongArch::SP32RegClass; ++ } ++ ++ llvm_unreachable("Unknown pointer kind"); ++} + +- switch (Subtarget.getTargetABI()) { ++unsigned ++LoongArchRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, ++ MachineFunction &MF) const { ++ switch (RC->getID()) { + default: +- llvm_unreachable("Unrecognized ABI"); +- case LoongArchABI::ABI_ILP32S: +- case LoongArchABI::ABI_LP64S: +- return CSR_ILP32S_LP64S_SaveList; +- case LoongArchABI::ABI_ILP32F: +- case LoongArchABI::ABI_LP64F: +- return CSR_ILP32F_LP64F_SaveList; +- case LoongArchABI::ABI_ILP32D: +- case LoongArchABI::ABI_LP64D: +- return CSR_ILP32D_LP64D_SaveList; ++ return 0; ++ case LoongArch::GPR32RegClassID: ++ case LoongArch::GPR64RegClassID: ++ { ++ const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); ++ return 28 - TFI->hasFP(MF); + } ++ case LoongArch::FGR32RegClassID: ++ return 32; ++ case LoongArch::FGR64RegClassID: ++ return 32; ++ } ++} ++ ++//===----------------------------------------------------------------------===// ++// Callee Saved Registers methods ++//===----------------------------------------------------------------------===// ++ ++/// LoongArch Callee Saved Registers ++const MCPhysReg * ++LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { ++ const LoongArchSubtarget &Subtarget = MF->getSubtarget(); ++ ++ if (Subtarget.isSingleFloat()) ++ return CSR_SingleFloatOnly_SaveList; ++ ++ if (Subtarget.isABI_LP64()) ++ return CSR_LP64_SaveList; ++ ++ if (Subtarget.isABI_LPX32()) ++ return CSR_LPX32_SaveList; ++ ++ return CSR_LP32_SaveList; + } + + const uint32_t * + LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF, +- CallingConv::ID CC) const { +- auto &Subtarget = MF.getSubtarget(); ++ CallingConv::ID) const { ++ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); + +- switch (Subtarget.getTargetABI()) { +- default: +- llvm_unreachable("Unrecognized ABI"); +- case LoongArchABI::ABI_ILP32S: +- case LoongArchABI::ABI_LP64S: +- return CSR_ILP32S_LP64S_RegMask; +- case LoongArchABI::ABI_ILP32F: +- case LoongArchABI::ABI_LP64F: +- return CSR_ILP32F_LP64F_RegMask; +- case LoongArchABI::ABI_ILP32D: +- case LoongArchABI::ABI_LP64D: +- return CSR_ILP32D_LP64D_RegMask; +- } +-} ++ if (Subtarget.isSingleFloat()) ++ return CSR_SingleFloatOnly_RegMask; ++ ++ if (Subtarget.isABI_LP64()) ++ return CSR_LP64_RegMask; + +-const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const { +- return CSR_NoRegs_RegMask; ++ return CSR_LP32_RegMask; + } + +-BitVector +-LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const { +- const LoongArchFrameLowering *TFI = getFrameLowering(MF); ++BitVector LoongArchRegisterInfo:: ++getReservedRegs(const MachineFunction &MF) const { ++ static const MCPhysReg ReservedGPR32[] = { ++ LoongArch::ZERO, LoongArch::SP, LoongArch::TP, LoongArch::T9 ++ }; ++ ++ static const MCPhysReg ReservedGPR64[] = { ++ LoongArch::ZERO_64, LoongArch::SP_64, LoongArch::TP_64, LoongArch::T9_64 ++ }; ++ + BitVector Reserved(getNumRegs()); ++ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); ++ ++ for (unsigned I = 0; I < array_lengthof(ReservedGPR32); ++I) ++ Reserved.set(ReservedGPR32[I]); ++ ++ for (unsigned I = 0; I < array_lengthof(ReservedGPR64); ++I) ++ Reserved.set(ReservedGPR64[I]); ++ ++ // Reserve FP if this function should have a dedicated frame pointer register. ++ if (Subtarget.getFrameLowering()->hasFP(MF)) { ++ Reserved.set(LoongArch::FP); ++ Reserved.set(LoongArch::FP_64); ++ ++ // Reserve the base register if we need to both realign the stack and ++ // allocate variable-sized objects at runtime. This should test the ++ // same conditions as LoongArchFrameLowering::hasBP(). ++ if (hasStackRealignment(MF) && MF.getFrameInfo().hasVarSizedObjects()) { ++ Reserved.set(LoongArch::S7); ++ Reserved.set(LoongArch::S7_64); ++ } ++ } + +- // Use markSuperRegs to ensure any register aliases are also reserved +- markSuperRegs(Reserved, LoongArch::R0); // zero +- markSuperRegs(Reserved, LoongArch::R2); // tp +- markSuperRegs(Reserved, LoongArch::R3); // sp +- markSuperRegs(Reserved, LoongArch::R21); // non-allocatable +- if (TFI->hasFP(MF)) +- markSuperRegs(Reserved, LoongArch::R22); // fp +- // Reserve the base register if we need to realign the stack and allocate +- // variable-sized objects at runtime. +- if (TFI->hasBP(MF)) +- markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp +- +- assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; + } + +-bool LoongArchRegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { +- return PhysReg == LoongArch::R0; ++bool ++LoongArchRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { ++ return true; + } + +-Register +-LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const { +- const TargetFrameLowering *TFI = getFrameLowering(MF); +- return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3; ++bool LoongArchRegisterInfo:: ++requiresFrameIndexScavenging(const MachineFunction &MF) const { ++ return true; + } + +-void LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, +- int SPAdj, +- unsigned FIOperandNum, +- RegScavenger *RS) const { +- // TODO: this implementation is a temporary placeholder which does just +- // enough to allow other aspects of code generation to be tested. ++bool ++LoongArchRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { ++ return true; ++} ++ ++/// Get the size of the offset supported by the given load/store/inline asm. ++/// The result includes the effects of any scale factors applied to the ++/// instruction immediate. ++static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, ++ MachineOperand MO) { ++ switch (Opcode) { ++ case LoongArch::LDPTR_W: ++ case LoongArch::LDPTR_W32: ++ case LoongArch::LDPTR_D: ++ case LoongArch::STPTR_W: ++ case LoongArch::STPTR_W32: ++ case LoongArch::STPTR_D: ++ case LoongArch::LL_W: ++ case LoongArch::LL_D: ++ case LoongArch::SC_W: ++ case LoongArch::SC_D: ++ return 14 + 2 /* scale factor */; ++ case LoongArch::INLINEASM: { ++ unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); ++ switch (ConstraintID) { ++ case InlineAsm::Constraint_ZC: { ++ return 14 + 2 /* scale factor */; ++ } ++ default: ++ return 12; ++ } ++ } ++ default: ++ return 12; ++ } ++} + +- assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); ++/// Get the scale factor applied to the immediate in the given load/store. ++static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) { ++ switch (Opcode) { ++ case LoongArch::LDPTR_W: ++ case LoongArch::LDPTR_W32: ++ case LoongArch::LDPTR_D: ++ case LoongArch::STPTR_W: ++ case LoongArch::STPTR_W32: ++ case LoongArch::STPTR_D: ++ case LoongArch::LL_W: ++ case LoongArch::LL_D: ++ case LoongArch::SC_W: ++ case LoongArch::SC_D: ++ return 4; ++ default: ++ return 1; ++ } ++} + ++// FrameIndex represent objects inside a abstract stack. ++// We must replace FrameIndex with an stack/frame pointer ++// direct reference. ++void LoongArchRegisterInfo:: ++eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, ++ unsigned FIOperandNum, RegScavenger *RS) const { + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); +- const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); +- DebugLoc DL = MI.getDebugLoc(); ++ const LoongArchFrameLowering *TFI = getFrameLowering(MF); ++ ++ LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; ++ errs() << "<--------->\n" ++ << MI); + + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); ++ uint64_t stackSize = MF.getFrameInfo().getStackSize(); ++ int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); ++ ++ LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" ++ << "spOffset : " << spOffset << "\n" ++ << "stackSize : " << stackSize << "\n" ++ << "SPAdj : " << SPAdj << "\n" ++ << "alignment : " ++ << DebugStr(MF.getFrameInfo().getObjectAlign(FrameIndex)) ++ << "\n"); ++ ++ LoongArchABIInfo ABI = ++ static_cast(MF.getTarget()).getABI(); ++ ++ // Everything else is referenced relative to whatever register ++ // getFrameIndexReference() returns. + Register FrameReg; + StackOffset Offset = + TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) + + StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm()); + +- // Offsets must be encodable with a 12-bit immediate field. +- if (!isInt<12>(Offset.getFixed())) { +- report_fatal_error("Frame offsets outside of the signed 12-bit range is " +- "not supported currently"); ++ LLVM_DEBUG(errs() << "Location : " ++ << "FrameReg<" << FrameReg << "> + " << Offset.getFixed() ++ << "\n<--------->\n"); ++ ++ MachineBasicBlock &MBB = *MI.getParent(); ++ DebugLoc DL = II->getDebugLoc(); ++ bool IsKill = false; ++ ++ if (!MI.isDebugValue()) { ++ // Make sure Offset fits within the field available. ++ // For ldptr/stptr/ll/sc instructions, this is a 14-bit signed immediate ++ // (scaled by 2), otherwise it is a 12-bit signed immediate. ++ unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits( ++ MI.getOpcode(), MI.getOperand(FIOperandNum - 1)); ++ const Align OffsetAlign(getLoadStoreOffsetAlign(MI.getOpcode())); ++ ++ if (OffsetBitSize == 16 && isInt<12>(Offset.getFixed()) && ++ !isAligned(OffsetAlign, Offset.getFixed())) { ++ // If we have an offset that needs to fit into a signed n-bit immediate ++ // (where n == 16) and doesn't aligned and does fit into 12-bits ++ // then use an ADDI ++ const TargetRegisterClass *PtrRC = ABI.ArePtrs64bit() ++ ? &LoongArch::GPR64RegClass ++ : &LoongArch::GPR32RegClass; ++ MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); ++ unsigned Reg = RegInfo.createVirtualRegister(PtrRC); ++ const LoongArchInstrInfo &TII = *static_cast( ++ MBB.getParent()->getSubtarget().getInstrInfo()); ++ BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiOp()), Reg) ++ .addReg(FrameReg) ++ .addImm(Offset.getFixed()); ++ ++ FrameReg = Reg; ++ Offset = StackOffset::getFixed(0); ++ IsKill = true; ++ } else if (!isInt<12>(Offset.getFixed())) { ++ // Otherwise split the offset into several pieces and add it in multiple ++ // instructions. ++ const LoongArchInstrInfo &TII = *static_cast( ++ MBB.getParent()->getSubtarget().getInstrInfo()); ++ unsigned Reg = TII.loadImmediate(Offset.getFixed(), MBB, II, DL); ++ BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddOp()), Reg) ++ .addReg(FrameReg) ++ .addReg(Reg, RegState::Kill); ++ ++ FrameReg = Reg; ++ Offset = StackOffset::getFixed(0); ++ IsKill = true; ++ } + } + +- MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); ++ MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed()); + } ++ ++Register LoongArchRegisterInfo:: ++getFrameRegister(const MachineFunction &MF) const { ++ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); ++ const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); ++ bool IsLP64 = ++ static_cast(MF.getTarget()).getABI().IsLP64(); ++ ++ return TFI->hasFP(MF) ? (IsLP64 ? LoongArch::FP_64 : LoongArch::FP) : ++ (IsLP64 ? LoongArch::SP_64 : LoongArch::SP); ++} ++ ++const TargetRegisterClass * ++LoongArchRegisterInfo::intRegClass(unsigned Size) const { ++ if (Size == 4) ++ return &LoongArch::GPR32RegClass; ++ ++ assert(Size == 8); ++ return &LoongArch::GPR64RegClass; ++} ++ ++bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const { ++ // Avoid realigning functions that explicitly do not want to be realigned. ++ // Normally, we should report an error when a function should be dynamically ++ // realigned but also has the attribute no-realign-stack. Unfortunately, ++ // with this attribute, MachineFrameInfo clamps each new object's alignment ++ // to that of the stack's alignment as specified by the ABI. As a result, ++ // the information of whether we have objects with larger alignment ++ // requirement than the stack's alignment is already lost at this point. ++ if (!TargetRegisterInfo::canRealignStack(MF)) ++ return false; ++ ++ const LoongArchSubtarget &Subtarget = MF.getSubtarget(); ++ unsigned FP = Subtarget.is64Bit() ? LoongArch::FP_64 : LoongArch::FP; ++ unsigned BP = Subtarget.is64Bit() ? LoongArch::S7_64 : LoongArch::S7; ++ ++ // We can't perform dynamic stack realignment if we can't reserve the ++ // frame pointer register. ++ if (!MF.getRegInfo().canReserveReg(FP)) ++ return false; ++ ++ // We can realign the stack if we know the maximum call frame size and we ++ // don't have variable sized objects. ++ if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF)) ++ return true; ++ ++ // We have to reserve the base pointer register in the presence of variable ++ // sized objects. ++ return MF.getRegInfo().canReserveReg(BP); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h +index cca130c3b..dd3be916a 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h +@@ -1,4 +1,4 @@ +-//= LoongArchRegisterInfo.h - LoongArch Register Information Impl -*- C++ -*-=// ++//===- LoongArchRegisterInfo.h - LoongArch Register Information Impl ------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,45 +6,75 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file contains the LoongArch implementation of the TargetRegisterInfo +-// class. ++// This file contains the LoongArch implementation of the TargetRegisterInfo class. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H + +-#include "llvm/CodeGen/TargetRegisterInfo.h" ++#include "LoongArch.h" ++#include "llvm/CodeGen/MachineBasicBlock.h" ++#include + + #define GET_REGINFO_HEADER + #include "LoongArchGenRegisterInfo.inc" + + namespace llvm { + +-struct LoongArchRegisterInfo : public LoongArchGenRegisterInfo { ++class TargetRegisterClass; + +- LoongArchRegisterInfo(unsigned HwMode); ++class LoongArchRegisterInfo : public LoongArchGenRegisterInfo { ++public: ++ enum class LoongArchPtrClass { ++ /// The default register class for integer values. ++ Default = 0, ++ /// The stack pointer only. ++ StackPointer = 1, ++ }; + ++ LoongArchRegisterInfo(); ++ ++ /// Get PIC indirect call register ++ static unsigned getPICCallReg(); ++ ++ /// Code Generation virtual methods... ++ const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, ++ unsigned Kind) const override; ++ ++ unsigned getRegPressureLimit(const TargetRegisterClass *RC, ++ MachineFunction &MF) const override; + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; +- const uint32_t *getNoPreservedMask() const override; +- + BitVector getReservedRegs(const MachineFunction &MF) const override; +- bool isConstantPhysReg(MCRegister PhysReg) const override; + +- const TargetRegisterClass * +- getPointerRegClass(const MachineFunction &MF, +- unsigned Kind = 0) const override { +- return &LoongArch::GPRRegClass; +- } ++ bool requiresRegisterScavenging(const MachineFunction &MF) const override; ++ ++ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; + +- void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, +- unsigned FIOperandNum, ++ bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override; ++ ++ /// Stack Frame Processing Methods ++ void eliminateFrameIndex(MachineBasicBlock::iterator II, ++ int SPAdj, unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + ++ // Stack realignment queries. ++ bool canRealignStack(const MachineFunction &MF) const override; ++ ++ /// Debug information queries. + Register getFrameRegister(const MachineFunction &MF) const override; ++ ++ /// Return GPR register class. ++ const TargetRegisterClass *intRegClass(unsigned Size) const; ++ ++private: ++ void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, ++ int FrameIndex, uint64_t StackSize, ++ int SPAdj, int64_t SPOffset) const; + }; ++ + } // end namespace llvm + + #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td +index 2d5ad99f6..96569e075 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td +@@ -1,4 +1,4 @@ +-//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===// ++//===-- LoongArchRegisterInfo.td - LoongArch Register defs -----------*- tablegen -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -7,155 +7,367 @@ + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// +-// Declarations that describe the LoongArch register files ++// Declarations that describe the LoongArch register file + //===----------------------------------------------------------------------===// +- + let Namespace = "LoongArch" in { +-class LoongArchReg Enc, string n, list alt = []> +- : Register { ++def sub_32 : SubRegIndex<32>; ++def sub_64 : SubRegIndex<64>; ++def sub_128 : SubRegIndex<128>; ++def sub_fcsr1 : SubRegIndex<5>; ++def sub_fcsr2 : SubRegIndex<13, 16>; ++def sub_fcsr3 : SubRegIndex<2, 8>; ++def sub_lo : SubRegIndex<32>; ++def sub_hi : SubRegIndex<32, 32>; ++def PC : Register<"pc">; ++} ++ ++class Unallocatable { ++ bit isAllocatable = 0; ++} ++ ++/// We have banks of registers each. ++class LoongArchReg Enc, string n> : Register { + let HWEncoding = Enc; +- let AltNames = alt; ++ let Namespace = "LoongArch"; + } + +-class LoongArchReg32 Enc, string n, list alt = []> +- : Register { ++class LoongArchRegWithSubRegs Enc, string n, list subregs> ++ : RegisterWithSubRegs { + let HWEncoding = Enc; +- let AltNames = alt; ++ let Namespace = "LoongArch"; + } + +-def sub_32 : SubRegIndex<32>; +-class LoongArchReg64 +- : Register<""> { +- let HWEncoding = subreg.HWEncoding; +- let SubRegs = [subreg]; ++/// LoongArch 32-bit CPU Registers. ++class LoongArch32GPR Enc, string n> : LoongArchReg; ++ ++/// LoongArch 64-bit CPU Registers. ++class LoongArch64GPR Enc, string n, list subregs> ++ : LoongArchRegWithSubRegs { + let SubRegIndices = [sub_32]; +- let AsmName = subreg.AsmName; +- let AltNames = subreg.AltNames; +-} +- +-let FallbackRegAltNameIndex = NoRegAltName in +-def RegAliasName : RegAltNameIndex; +-} // Namespace = "LoongArch" +- +-// Integer registers +- +-let RegAltNameIndices = [RegAliasName] in { +- def R0 : LoongArchReg<0, "r0", ["zero"]>, DwarfRegNum<[0]>; +- def R1 : LoongArchReg<1, "r1", ["ra"]>, DwarfRegNum<[1]>; +- def R2 : LoongArchReg<2, "r2", ["tp"]>, DwarfRegNum<[2]>; +- def R3 : LoongArchReg<3, "r3", ["sp"]>, DwarfRegNum<[3]>; +- def R4 : LoongArchReg<4, "r4", ["a0"]>, DwarfRegNum<[4]>; +- def R5 : LoongArchReg<5, "r5", ["a1"]>, DwarfRegNum<[5]>; +- def R6 : LoongArchReg<6, "r6", ["a2"]>, DwarfRegNum<[6]>; +- def R7 : LoongArchReg<7, "r7", ["a3"]>, DwarfRegNum<[7]>; +- def R8 : LoongArchReg<8, "r8", ["a4"]>, DwarfRegNum<[8]>; +- def R9 : LoongArchReg<9, "r9", ["a5"]>, DwarfRegNum<[9]>; +- def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>; +- def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>; +- def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>; +- def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>; +- def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>; +- def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>; +- def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>; +- def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>; +- def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>; +- def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>; +- def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>; +- def R21 : LoongArchReg<21, "r21", [""]>, DwarfRegNum<[21]>; +- def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, DwarfRegNum<[22]>; +- def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>; +- def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>; +- def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>; +- def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>; +- def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>; +- def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>; +- def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>; +- def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>; +- def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>; +-} // RegAltNameIndices = [RegAliasName] +- +-def GRLenVT : ValueTypeByHwMode<[LA32, LA64], +- [i32, i64]>; +-def GRLenRI : RegInfoByHwMode< +- [LA32, LA64], +- [RegInfo<32,32,32>, RegInfo<64,64,64>]>; +- +-// The order of registers represents the preferred allocation sequence. +-// Registers are listed in the order caller-save, callee-save, specials. +-def GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add +- // Argument registers (a0...a7) +- (sequence "R%u", 4, 11), +- // Temporary registers (t0...t8) +- (sequence "R%u", 12, 20), +- // Static register (s9/fp, s0...s8) +- (sequence "R%u", 22, 31), +- // Specials (r0, ra, tp, sp) +- (sequence "R%u", 0, 3), +- // Reserved (Non-allocatable) +- R21 +- )> { +- let RegInfos = GRLenRI; +-} +- +-// Floating point registers +- +-let RegAltNameIndices = [RegAliasName] in { +- def F0 : LoongArchReg32<0, "f0", ["fa0"]>, DwarfRegNum<[32]>; +- def F1 : LoongArchReg32<1, "f1", ["fa1"]>, DwarfRegNum<[33]>; +- def F2 : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>; +- def F3 : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>; +- def F4 : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>; +- def F5 : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>; +- def F6 : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>; +- def F7 : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>; +- def F8 : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>; +- def F9 : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>; +- def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>; +- def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>; +- def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>; +- def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>; +- def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>; +- def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>; +- def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>; +- def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>; +- def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>; +- def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>; +- def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>; +- def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>; +- def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>; +- def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>; +- def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>; +- def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>; +- def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>; +- def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>; +- def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>; +- def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>; +- def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>; +- def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>; +- +- foreach I = 0-31 in { +- def F#I#_64 : LoongArchReg64("F"#I)>, +- DwarfRegNum<[!add(I, 32)]>; +- } +-} +- +-// The order of registers represents the preferred allocation sequence. +-def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>; +-def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>; +- +-// Condition flag registers ++} ++ ++/// LoongArch 64-bit Floating-point Registers ++class FGR32 Enc, string n> : LoongArchReg; ++class FGR64 Enc, string n, list subregs> ++ : LoongArchRegWithSubRegs { ++ let SubRegIndices = [sub_lo]; ++} ++ ++// LoongArch 128-bit (aliased) LSX Registers ++class LSX128 Enc, string n, list subregs> ++ : LoongArchRegWithSubRegs { ++ let SubRegIndices = [sub_64]; ++} ++ ++// LoongArch 256-bit (aliased) LASX Registers ++class LASX256 Enc, string n, list subregs> ++ : LoongArchRegWithSubRegs { ++ let SubRegIndices = [sub_128]; ++} ++ ++//===----------------------------------------------------------------------===// ++// Registers ++//===----------------------------------------------------------------------===// ++ ++/// General Purpose 32-bit Registers ++def ZERO : LoongArch32GPR<0, "zero">, ++ DwarfRegNum<[0]>; ++def RA : LoongArch32GPR<1, "ra">, DwarfRegNum<[1]>; ++def TP : LoongArch32GPR<2, "tp">, DwarfRegNum<[2]>; ++def SP : LoongArch32GPR<3, "sp">, DwarfRegNum<[3]>; ++def A0 : LoongArch32GPR<4, "r4">, DwarfRegNum<[4]>; ++def A1 : LoongArch32GPR<5, "r5">, DwarfRegNum<[5]>; ++def A2 : LoongArch32GPR<6, "r6">, DwarfRegNum<[6]>; ++def A3 : LoongArch32GPR<7, "r7">, DwarfRegNum<[7]>; ++def A4 : LoongArch32GPR<8, "r8">, DwarfRegNum<[8]>; ++def A5 : LoongArch32GPR<9, "r9">, DwarfRegNum<[9]>; ++def A6 : LoongArch32GPR<10, "r10">, DwarfRegNum<[10]>; ++def A7 : LoongArch32GPR<11, "r11">, DwarfRegNum<[11]>; ++def T0 : LoongArch32GPR<12, "r12">, DwarfRegNum<[12]>; ++def T1 : LoongArch32GPR<13, "r13">, DwarfRegNum<[13]>; ++def T2 : LoongArch32GPR<14, "r14">, DwarfRegNum<[14]>; ++def T3 : LoongArch32GPR<15, "r15">, DwarfRegNum<[15]>; ++def T4 : LoongArch32GPR<16, "r16">, DwarfRegNum<[16]>; ++def T5 : LoongArch32GPR<17, "r17">, DwarfRegNum<[17]>; ++def T6 : LoongArch32GPR<18, "r18">, DwarfRegNum<[18]>; ++def T7 : LoongArch32GPR<19, "r19">, DwarfRegNum<[19]>; ++def T8 : LoongArch32GPR<20, "r20">, DwarfRegNum<[20]>; ++def T9 : LoongArch32GPR<21, "r21">, DwarfRegNum<[21]>; ++def FP : LoongArch32GPR<22, "r22">, DwarfRegNum<[22]>; ++def S0 : LoongArch32GPR<23, "r23">, DwarfRegNum<[23]>; ++def S1 : LoongArch32GPR<24, "r24">, DwarfRegNum<[24]>; ++def S2 : LoongArch32GPR<25, "r25">, DwarfRegNum<[25]>; ++def S3 : LoongArch32GPR<26, "r26">, DwarfRegNum<[26]>; ++def S4 : LoongArch32GPR<27, "r27">, DwarfRegNum<[27]>; ++def S5 : LoongArch32GPR<28, "r28">, DwarfRegNum<[28]>; ++def S6 : LoongArch32GPR<29, "r29">, DwarfRegNum<[29]>; ++def S7 : LoongArch32GPR<30, "r30">, DwarfRegNum<[30]>; ++def S8 : LoongArch32GPR<31, "r31">, DwarfRegNum<[31]>; ++ ++let SubRegIndices = [sub_32] in { ++def V0 : LoongArchRegWithSubRegs<4, "r4", [A0]>, DwarfRegNum<[4]>; ++def V1 : LoongArchRegWithSubRegs<5, "r5", [A1]>, DwarfRegNum<[5]>; ++} ++ ++/// General Purpose 64-bit Registers ++def ZERO_64 : LoongArch64GPR<0, "zero", [ZERO]>, DwarfRegNum<[0]>; ++def RA_64 : LoongArch64GPR<1, "ra", [RA]>, DwarfRegNum<[1]>; ++def TP_64 : LoongArch64GPR<2, "tp", [TP]>, DwarfRegNum<[2]>; ++def SP_64 : LoongArch64GPR<3, "sp", [SP]>, DwarfRegNum<[3]>; ++def A0_64 : LoongArch64GPR<4, "r4", [A0]>, DwarfRegNum<[4]>; ++def A1_64 : LoongArch64GPR<5, "r5", [A1]>, DwarfRegNum<[5]>; ++def A2_64 : LoongArch64GPR<6, "r6", [A2]>, DwarfRegNum<[6]>; ++def A3_64 : LoongArch64GPR<7, "r7", [A3]>, DwarfRegNum<[7]>; ++def A4_64 : LoongArch64GPR<8, "r8", [A4]>, DwarfRegNum<[8]>; ++def A5_64 : LoongArch64GPR<9, "r9", [A5]>, DwarfRegNum<[9]>; ++def A6_64 : LoongArch64GPR<10, "r10", [A6]>, DwarfRegNum<[10]>; ++def A7_64 : LoongArch64GPR<11, "r11", [A7]>, DwarfRegNum<[11]>; ++def T0_64 : LoongArch64GPR<12, "r12", [T0]>, DwarfRegNum<[12]>; ++def T1_64 : LoongArch64GPR<13, "r13", [T1]>, DwarfRegNum<[13]>; ++def T2_64 : LoongArch64GPR<14, "r14", [T2]>, DwarfRegNum<[14]>; ++def T3_64 : LoongArch64GPR<15, "r15", [T3]>, DwarfRegNum<[15]>; ++def T4_64 : LoongArch64GPR<16, "r16", [T4]>, DwarfRegNum<[16]>; ++def T5_64 : LoongArch64GPR<17, "r17", [T5]>, DwarfRegNum<[17]>; ++def T6_64 : LoongArch64GPR<18, "r18", [T6]>, DwarfRegNum<[18]>; ++def T7_64 : LoongArch64GPR<19, "r19", [T7]>, DwarfRegNum<[19]>; ++def T8_64 : LoongArch64GPR<20, "r20", [T8]>, DwarfRegNum<[20]>; ++def T9_64 : LoongArch64GPR<21, "r21", [T9]>, DwarfRegNum<[21]>; ++def FP_64 : LoongArch64GPR<22, "r22", [FP]>, DwarfRegNum<[22]>; ++def S0_64 : LoongArch64GPR<23, "r23", [S0]>, DwarfRegNum<[23]>; ++def S1_64 : LoongArch64GPR<24, "r24", [S1]>, DwarfRegNum<[24]>; ++def S2_64 : LoongArch64GPR<25, "r25", [S2]>, DwarfRegNum<[25]>; ++def S3_64 : LoongArch64GPR<26, "r26", [S3]>, DwarfRegNum<[26]>; ++def S4_64 : LoongArch64GPR<27, "r27", [S4]>, DwarfRegNum<[27]>; ++def S5_64 : LoongArch64GPR<28, "r28", [S5]>, DwarfRegNum<[28]>; ++def S6_64 : LoongArch64GPR<29, "r29", [S6]>, DwarfRegNum<[29]>; ++def S7_64 : LoongArch64GPR<30, "r30", [S7]>, DwarfRegNum<[30]>; ++def S8_64 : LoongArch64GPR<31, "r31", [S8]>, DwarfRegNum<[31]>; ++ ++let SubRegIndices = [sub_64] in { ++def V0_64 : LoongArch64GPR<4, "r4", [A0_64]>, DwarfRegNum<[4]>; ++def V1_64 : LoongArch64GPR<5, "r5", [A1_64]>, DwarfRegNum<[5]>; ++} ++ ++/// FP registers ++foreach I = 0-31 in ++def F#I : FGR32, DwarfRegNum<[!add(I, 32)]>; ++ ++foreach I = 0-31 in ++def F#I#_64 : FGR64("F"#I)]>, DwarfRegNum<[!add(I, 32)]>; + ++/// FP Condition Flag 0~7 + foreach I = 0-7 in + def FCC#I : LoongArchReg; + +-def CFR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "FCC%u", 0, 7)> { +- let RegInfos = GRLenRI; ++/// FP Control and Status Registers, FCSR 1~3 ++foreach I = 1-3 in ++def FCSR#I : LoongArchReg; ++ ++class FCSRReg Enc, string n, list subregs> : ++ RegisterWithSubRegs { ++// field bits<2> chan_encoding = 0; ++ let Namespace = "LoongArch"; ++ let SubRegIndices = [sub_fcsr1, sub_fcsr2, sub_fcsr3]; ++// let HWEncoding{8-0} = encoding{8-0}; ++// let HWEncoding{10-9} = chan_encoding; + } + +-// Control and status registers ++def FCSR0 : FCSRReg<0, "fcsr0", [FCSR1, FCSR2, FCSR3]>; + +-foreach I = 0-3 in +-def FCSR#I : LoongArchReg; ++/// PC register ++//let NameSpace = "LoongArch" in ++//def PC : Register<"pc">; ++ ++//===----------------------------------------------------------------------===// ++// Register Classes ++//===----------------------------------------------------------------------===// ++ ++def GPR32 : RegisterClass<"LoongArch", [i32], 32, (add ++ // Reserved ++ ZERO, ++ // Return Values and Arguments ++ A0, A1, A2, A3, A4, A5, A6, A7, ++ // Not preserved across procedure calls ++ T0, T1, T2, T3, T4, T5, T6, T7, T8, ++ // Callee save ++ S0, S1, S2, S3, S4, S5, S6, S7, S8, ++ // Reserved ++ RA, TP, SP, ++ // Reserved ++ T9, FP)>; ++ ++def GPR64 : RegisterClass<"LoongArch", [i64], 64, (add ++ // Reserved ++ ZERO_64, ++ // Return Values and Arguments ++ A0_64, A1_64, A2_64, A3_64, A4_64, A5_64, A6_64, A7_64, ++ // Not preserved across procedure calls ++ T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64, ++ // Callee save ++ S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64, S8_64, ++ // Reserved ++ RA_64, TP_64, SP_64, ++ // Reserved ++ T9_64, FP_64)>; ++ ++def GPRTC64 : RegisterClass<"LoongArch", [i64], 64, (add ++ // Return Values and Arguments ++ A0_64, A1_64, A2_64, A3_64, A4_64, A5_64, A6_64, A7_64, ++ // Not preserved across procedure calls ++ T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64)>; ++ ++/// FP Registers. ++def FGR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>; ++def FGR32 : RegisterClass<"LoongArch", [f32], 64, (sequence "F%u", 0, 31)>; ++ ++/// FP condition Flag registers. ++def FCFR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCC%u", 0, 7)>, ++ Unallocatable; ++ ++def SP32 : RegisterClass<"LoongArch", [i32], 32, (add SP)>, Unallocatable; ++def SP64 : RegisterClass<"LoongArch", [i64], 64, (add SP_64)>, Unallocatable; ++def TP32 : RegisterClass<"LoongArch", [i32], 32, (add TP)>, Unallocatable; ++def TP64 : RegisterClass<"LoongArch", [i64], 64, (add TP_64)>, Unallocatable; ++ ++/// FP control and Status registers. ++def FCSR : RegisterClass<"LoongArch", [i32], 4, (sequence "FCSR%u", 0, 3)>, ++ Unallocatable; ++ ++//LSX ++foreach I = 0-31 in ++def VR#I : LSX128("F"#I#"_64")]>, ++ DwarfRegNum<[!add(I, 32)]>; ++ ++//LASX ++foreach I = 0-31 in ++def XR#I : LASX256("VR"#I)]>, ++ DwarfRegNum<[!add(I, 32)]>; ++ ++def LSX128B: RegisterClass<"LoongArch", [v16i8], 128, ++ (sequence "VR%u", 0, 31)>; ++ ++def LSX128H: RegisterClass<"LoongArch", [v8i16], 128, ++ (sequence "VR%u", 0, 31)>; ++ ++def LSX128W: RegisterClass<"LoongArch", [v4i32, v4f32], 128, ++ (sequence "VR%u", 0, 31)>; ++ ++def LSX128D: RegisterClass<"LoongArch", [v2i64, v2f64], 128, ++ (sequence "VR%u", 0, 31)>; ++ ++def LASX256B: RegisterClass<"LoongArch", [v32i8], 256, ++ (sequence "XR%u", 0, 31)>; ++def LASX256H: RegisterClass<"LoongArch", [v16i16], 256, ++ (sequence "XR%u", 0, 31)>; ++def LASX256W: RegisterClass<"LoongArch", [v8i32, v8f32], 256, ++ (sequence "XR%u", 0, 31)>; ++def LASX256D: RegisterClass<"LoongArch", [v4i64, v4f64], 256, ++ (sequence "XR%u", 0, 31)>; ++ ++//===----------------------------------------------------------------------===// ++// Register Operands. ++//===----------------------------------------------------------------------===// + +-let isAllocatable = false in +-def FCSR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCSR%u", 0, 3)>; ++class LoongArchAsmRegOperand : AsmOperandClass { ++ let ParserMethod = "parseAnyRegister"; ++} ++ ++def GPR32AsmOperand : LoongArchAsmRegOperand { ++ let Name = "GPR32AsmReg"; ++ let PredicateMethod = "isGPRAsmReg"; ++} ++ ++def GPR64AsmOperand : LoongArchAsmRegOperand { ++ let Name = "GPR64AsmReg"; ++ let PredicateMethod = "isGPRAsmReg"; ++} ++ ++def FGR32AsmOperand : LoongArchAsmRegOperand { ++ let Name = "FGR32AsmReg"; ++ let PredicateMethod = "isFGRAsmReg"; ++} ++ ++def FGR64AsmOperand : LoongArchAsmRegOperand { ++ let Name = "FGR64AsmReg"; ++ let PredicateMethod = "isFGRAsmReg"; ++} ++ ++def FCSRAsmOperand : LoongArchAsmRegOperand { ++ let Name = "FCSRAsmReg"; ++} ++ ++def FCFRAsmOperand : LoongArchAsmRegOperand { ++ let Name = "FCFRAsmReg"; ++} ++ ++//LSX ++def LSX128AsmOperand : LoongArchAsmRegOperand { ++ let Name = "LSX128AsmReg"; ++} ++ ++//LASX ++def LASX256AsmOperand : LoongArchAsmRegOperand { ++ let Name = "LASX256AsmReg"; ++} ++ ++def GPR32Opnd : RegisterOperand { ++ let ParserMatchClass = GPR32AsmOperand; ++} ++ ++def GPR64Opnd : RegisterOperand { ++ let ParserMatchClass = GPR64AsmOperand; ++} ++ ++def GPRTC64Opnd : RegisterOperand { ++ let ParserMatchClass = GPR64AsmOperand; ++} ++ ++def FGR32Opnd : RegisterOperand { ++ let ParserMatchClass = FGR32AsmOperand; ++} ++ ++def FGR64Opnd : RegisterOperand { ++ let ParserMatchClass = FGR64AsmOperand; ++} ++ ++def FCSROpnd : RegisterOperand { ++ let ParserMatchClass = FCSRAsmOperand; ++} ++ ++def FCFROpnd : RegisterOperand { ++ let ParserMatchClass = FCFRAsmOperand; ++} ++ ++//LSX ++def LSX128BOpnd : RegisterOperand { ++ let ParserMatchClass = LSX128AsmOperand; ++} ++ ++def LSX128HOpnd : RegisterOperand { ++ let ParserMatchClass = LSX128AsmOperand; ++} ++ ++def LSX128WOpnd : RegisterOperand { ++ let ParserMatchClass = LSX128AsmOperand; ++} ++ ++def LSX128DOpnd : RegisterOperand { ++ let ParserMatchClass = LSX128AsmOperand; ++} ++ ++//LASX ++def LASX256BOpnd : RegisterOperand { ++ let ParserMatchClass = LASX256AsmOperand; ++} ++ ++def LASX256HOpnd : RegisterOperand { ++ let ParserMatchClass = LASX256AsmOperand; ++} ++ ++def LASX256WOpnd : RegisterOperand { ++ let ParserMatchClass = LASX256AsmOperand; ++} ++ ++def LASX256DOpnd : RegisterOperand { ++ let ParserMatchClass = LASX256AsmOperand; ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp +index ff84e7c8c..ef990ae09 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information -*- C++ -*--=// ++//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information --------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,7 +11,16 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchSubtarget.h" +-#include "LoongArchFrameLowering.h" ++#include "LoongArch.h" ++#include "LoongArchMachineFunction.h" ++#include "LoongArchRegisterInfo.h" ++#include "LoongArchTargetMachine.h" ++#include "llvm/IR/Attributes.h" ++#include "llvm/IR/Function.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/MC/TargetRegistry.h" ++#include "llvm/Support/raw_ostream.h" + + using namespace llvm; + +@@ -23,32 +32,74 @@ using namespace llvm; + + void LoongArchSubtarget::anchor() {} + +-LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies( +- const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, +- StringRef ABIName) { +- bool Is64Bit = TT.isArch64Bit(); +- if (CPU.empty()) +- CPU = Is64Bit ? "generic-la64" : "generic-la32"; ++LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, ++ StringRef FS, ++ const LoongArchTargetMachine &TM, ++ MaybeAlign StackAlignOverride) ++ : LoongArchGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), HasLA64(false), ++ IsSoftFloat(false), IsSingleFloat(false), IsFP64bit(false), HasLSX(false), ++ HasLASX(false), UnalignedAccess(false), ++ StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), ++ TSInfo(), InstrInfo(initializeSubtargetDependencies(CPU, FS, TM)), ++ FrameLowering(*this), TLInfo(TM, *this) { ++ ++ // Check if Architecture and ABI are compatible. ++ assert(((!is64Bit() && isABI_LP32()) || ++ (is64Bit() && (isABI_LPX32() || isABI_LP64()))) && ++ "Invalid Arch & ABI pair."); ++ ++ if (hasLSX() && !isFP64bit()) ++ report_fatal_error("LSX requires 64-bit floating point register." ++ "See -mattr=+fp64.", ++ false); ++ ++ assert(isFP64bit()); ++} ++ ++bool LoongArchSubtarget::isPositionIndependent() const { ++ return TM.isPositionIndependent(); ++} ++ ++/// This overrides the PostRAScheduler bit in the SchedModel for any CPU. ++bool LoongArchSubtarget::enablePostRAScheduler() const { return true; } + +- if (TuneCPU.empty()) +- TuneCPU = CPU; ++void LoongArchSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { ++ CriticalPathRCs.clear(); ++ CriticalPathRCs.push_back(is64Bit() ? &LoongArch::GPR64RegClass ++ : &LoongArch::GPR32RegClass); ++} ++ ++CodeGenOpt::Level LoongArchSubtarget::getOptLevelToEnablePostRAScheduler() const { ++ return CodeGenOpt::Aggressive; ++} ++ ++LoongArchSubtarget & ++LoongArchSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, ++ const TargetMachine &TM) { ++ StringRef CPUName = LoongArch_MC::selectLoongArchCPU(TM.getTargetTriple(), CPU); + +- ParseSubtargetFeatures(CPU, TuneCPU, FS); +- if (Is64Bit) { +- GRLenVT = MVT::i64; +- GRLen = 64; ++ // Parse features string. ++ ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS); ++ // Initialize scheduling itinerary for the specified CPU. ++ InstrItins = getInstrItineraryForCPU(CPUName); ++ ++ if (StackAlignOverride) ++ stackAlignment = *StackAlignOverride; ++ else if (isABI_LPX32() || isABI_LP64()) ++ stackAlignment = Align(16); ++ else { ++ assert(isABI_LP32() && "Unknown ABI for stack alignment!"); ++ stackAlignment = Align(8); + } + +- // TODO: ILP32{S,F} LP64{S,F} +- TargetABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D; + return *this; + } + +-LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, +- StringRef TuneCPU, StringRef FS, +- StringRef ABIName, +- const TargetMachine &TM) +- : LoongArchGenSubtargetInfo(TT, CPU, TuneCPU, FS), +- FrameLowering( +- initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), +- InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {} ++Reloc::Model LoongArchSubtarget::getRelocationModel() const { ++ return TM.getRelocationModel(); ++} ++ ++bool LoongArchSubtarget::isABI_LP64() const { return getABI().IsLP64(); } ++bool LoongArchSubtarget::isABI_LPX32() const { return getABI().IsLPX32(); } ++bool LoongArchSubtarget::isABI_LP32() const { return getABI().IsLP32(); } ++const LoongArchABIInfo &LoongArchSubtarget::getABI() const { return TM.getABI(); } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +index fbe7a176b..588d9f46b 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +@@ -1,4 +1,4 @@ +-//===- LoongArchSubtarget.h - Define Subtarget for the LoongArch -*- C++ -*-==// ++//===-- LoongArchSubtarget.h - Define Subtarget for the LoongArch ---------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -13,15 +13,16 @@ + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H + ++#include "MCTargetDesc/LoongArchABIInfo.h" + #include "LoongArchFrameLowering.h" + #include "LoongArchISelLowering.h" + #include "LoongArchInstrInfo.h" +-#include "LoongArchRegisterInfo.h" +-#include "MCTargetDesc/LoongArchBaseInfo.h" + #include "llvm/CodeGen/SelectionDAGTargetInfo.h" + #include "llvm/CodeGen/TargetSubtargetInfo.h" + #include "llvm/IR/DataLayout.h" +-#include "llvm/Target/TargetMachine.h" ++#include "llvm/MC/MCInstrItineraries.h" ++#include "llvm/Support/ErrorHandling.h" ++#include + + #define GET_SUBTARGETINFO_HEADER + #include "LoongArchGenSubtargetInfo.inc" +@@ -29,61 +30,114 @@ + namespace llvm { + class StringRef; + ++class LoongArchTargetMachine; ++ + class LoongArchSubtarget : public LoongArchGenSubtargetInfo { + virtual void anchor(); +- bool HasLA64 = false; +- bool HasBasicF = false; +- bool HasBasicD = false; +- bool HasExtLSX = false; +- bool HasExtLASX = false; +- bool HasExtLVZ = false; +- bool HasExtLBT = false; +- unsigned GRLen = 32; +- MVT GRLenVT = MVT::i32; +- LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown; +- LoongArchFrameLowering FrameLowering; +- LoongArchInstrInfo InstrInfo; +- LoongArchRegisterInfo RegInfo; +- LoongArchTargetLowering TLInfo; +- +- /// Initializes using the passed in CPU and feature strings so that we can +- /// use initializer lists for subtarget initialization. +- LoongArchSubtarget &initializeSubtargetDependencies(const Triple &TT, +- StringRef CPU, +- StringRef TuneCPU, +- StringRef FS, +- StringRef ABIName); ++ ++ // HasLA64 - The target processor has LA64 ISA support. ++ bool HasLA64; ++ ++ // IsSoftFloat - The target does not support any floating point instructions. ++ bool IsSoftFloat; ++ ++ // IsSingleFloat - The target only supports single precision float ++ // point operations. This enable the target to use all 32 32-bit ++ // floating point registers instead of only using even ones. ++ bool IsSingleFloat; ++ ++ // IsFP64bit - The target processor has 64-bit floating point registers. ++ bool IsFP64bit; ++ ++ /// Features related to the presence of specific instructions. ++ ++ // HasLSX - Supports LSX. ++ bool HasLSX; ++ ++ // HasLASX - Supports LASX. ++ bool HasLASX; ++ ++ /// The minimum alignment known to hold of the stack frame on ++ /// entry to the function and which must be maintained by every function. ++ Align stackAlignment; ++ ++ // Allow unaligned memory accesses. ++ bool UnalignedAccess; ++ ++ /// The overridden stack alignment. ++ MaybeAlign StackAlignOverride; ++ ++ InstrItineraryData InstrItins; ++ ++ const LoongArchTargetMachine &TM; ++ ++ Triple TargetTriple; ++ ++ const SelectionDAGTargetInfo TSInfo; ++ const LoongArchInstrInfo InstrInfo; ++ const LoongArchFrameLowering FrameLowering; ++ const LoongArchTargetLowering TLInfo; + + public: +- // Initializes the data members to match that of the specified triple. +- LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, +- StringRef FS, StringRef ABIName, const TargetMachine &TM); ++ bool isPositionIndependent() const; ++ /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. ++ bool enablePostRAScheduler() const override; ++ void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; ++ CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; ++ ++ bool isABI_LP64() const; ++ bool isABI_LPX32() const; ++ bool isABI_LP32() const; ++ const LoongArchABIInfo &getABI() const; + +- // Parses features string setting specified subtarget options. The +- // definition of this function is auto-generated by tblgen. ++ /// This constructor initializes the data members to match that ++ /// of the specified triple. ++ LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef FS, ++ const LoongArchTargetMachine &TM, MaybeAlign StackAlignOverride); ++ ++ /// ParseSubtargetFeatures - Parses features string setting specified ++ /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); + +- const LoongArchFrameLowering *getFrameLowering() const override { ++ bool is64Bit() const { return HasLA64; } ++ bool isFP64bit() const { return IsFP64bit; } ++ unsigned getGPRSizeInBytes() const { return is64Bit() ? 8 : 4; } ++ bool isSingleFloat() const { return IsSingleFloat; } ++ bool hasLSX() const { return HasLSX; } ++ bool hasLASX() const { return HasLASX; } ++ bool useSoftFloat() const { return IsSoftFloat; } ++ ++ bool allowUnalignedAccess() const { return UnalignedAccess; } ++ ++ bool isXRaySupported() const override { return true; } ++ ++ Align getStackAlignment() const { return stackAlignment; } ++ ++ // Grab relocation model ++ Reloc::Model getRelocationModel() const; ++ ++ LoongArchSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, ++ const TargetMachine &TM); ++ ++ const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { ++ return &TSInfo; ++ } ++ const LoongArchInstrInfo *getInstrInfo() const override { ++ return &InstrInfo; ++ } ++ const TargetFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } +- const LoongArchInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const LoongArchRegisterInfo *getRegisterInfo() const override { +- return &RegInfo; ++ return &InstrInfo.getRegisterInfo(); + } + const LoongArchTargetLowering *getTargetLowering() const override { + return &TLInfo; + } +- bool is64Bit() const { return HasLA64; } +- bool hasBasicF() const { return HasBasicF; } +- bool hasBasicD() const { return HasBasicD; } +- bool hasExtLSX() const { return HasExtLSX; } +- bool hasExtLASX() const { return HasExtLASX; } +- bool hasExtLVZ() const { return HasExtLVZ; } +- bool hasExtLBT() const { return HasExtLBT; } +- MVT getGRLenVT() const { return GRLenVT; } +- unsigned getGRLen() const { return GRLen; } +- LoongArchABI::ABI getTargetABI() const { return TargetABI; } ++ const InstrItineraryData *getInstrItineraryData() const override { ++ return &InstrItins; ++ } + }; +-} // end namespace llvm ++} // End llvm namespace + +-#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp +index 7ba5848e0..f8a1dc5fa 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// ++//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch -------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -12,12 +12,29 @@ + + #include "LoongArchTargetMachine.h" + #include "LoongArch.h" +-#include "MCTargetDesc/LoongArchBaseInfo.h" +-#include "TargetInfo/LoongArchTargetInfo.h" ++#include "LoongArchISelDAGToDAG.h" ++#include "LoongArchSubtarget.h" ++#include "LoongArchTargetObjectFile.h" ++#include "LoongArchTargetTransformInfo.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/ADT/Optional.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/Analysis/TargetTransformInfo.h" ++#include "llvm/CodeGen/BasicTTIImpl.h" ++#include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/Passes.h" +-#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" + #include "llvm/CodeGen/TargetPassConfig.h" ++#include "llvm/IR/Attributes.h" ++#include "llvm/IR/Function.h" + #include "llvm/MC/TargetRegistry.h" ++#include "llvm/Support/CodeGen.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/raw_ostream.h" ++#include "llvm/Target/TargetOptions.h" ++#include ++#include + + using namespace llvm; + +@@ -26,29 +43,63 @@ using namespace llvm; + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { + // Register the target. + RegisterTargetMachine X(getTheLoongArch32Target()); +- RegisterTargetMachine Y(getTheLoongArch64Target()); ++ RegisterTargetMachine A(getTheLoongArch64Target()); + } + +-static std::string computeDataLayout(const Triple &TT) { +- if (TT.isArch64Bit()) +- return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; +- assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); +- return "e-m:e-p:32:32-i64:64-n32-S128"; ++static std::string computeDataLayout(const Triple &TT, StringRef CPU, ++ const TargetOptions &Options) { ++ std::string Ret; ++ LoongArchABIInfo ABI = LoongArchABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); ++ ++ Ret += "e"; ++ ++ if (ABI.IsLP32()) ++ Ret += "-m:m"; ++ else ++ Ret += "-m:e"; ++ ++ // Pointers are 32 bit on some ABIs. ++ if (!ABI.IsLP64()) ++ Ret += "-p:32:32"; ++ ++ // 8 and 16 bit integers only need to have natural alignment, but try to ++ // align them to 32 bits. 64 bit integers have natural alignment. ++ Ret += "-i8:8:32-i16:16:32-i64:64"; ++ ++ // 32 bit registers are always available and the stack is at least 64 bit ++ // aligned. On LP64 64 bit registers are also available and the stack is ++ // 128 bit aligned. ++ if (ABI.IsLP64() || ABI.IsLPX32()) ++ Ret += "-n32:64-S128"; ++ else ++ Ret += "-n32-S64"; ++ ++ return Ret; + } + +-static Reloc::Model getEffectiveRelocModel(const Triple &TT, ++static Reloc::Model getEffectiveRelocModel(bool JIT, + Optional RM) { +- return RM.value_or(Reloc::Static); ++ if (!RM.hasValue() || JIT) ++ return Reloc::Static; ++ return *RM; + } + +-LoongArchTargetMachine::LoongArchTargetMachine( +- const Target &T, const Triple &TT, StringRef CPU, StringRef FS, +- const TargetOptions &Options, Optional RM, +- Optional CM, CodeGenOpt::Level OL, bool JIT) +- : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, +- getEffectiveRelocModel(TT, RM), ++// On function prologue, the stack is created by decrementing ++// its pointer. Once decremented, all references are done with positive ++// offset from the stack/frame pointer, using StackGrowsUp enables ++// an easier handling. ++// Using CodeModel::Large enables different CALL behavior. ++LoongArchTargetMachine::LoongArchTargetMachine(const Target &T, const Triple &TT, ++ StringRef CPU, StringRef FS, ++ const TargetOptions &Options, ++ Optional RM, ++ Optional CM, ++ CodeGenOpt::Level OL, bool JIT) ++ : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, ++ CPU, FS, Options, getEffectiveRelocModel(JIT, RM), + getEffectiveCodeModel(CM, CodeModel::Small), OL), +- TLOF(std::make_unique()) { ++ TLOF(std::make_unique()), ++ ABI(LoongArchABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)) { + initAsmInfo(); + } + +@@ -57,44 +108,45 @@ LoongArchTargetMachine::~LoongArchTargetMachine() = default; + const LoongArchSubtarget * + LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { + Attribute CPUAttr = F.getFnAttribute("target-cpu"); +- Attribute TuneAttr = F.getFnAttribute("tune-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); + +- std::string CPU = +- CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; +- std::string TuneCPU = +- TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; +- std::string FS = +- FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; ++ std::string CPU = !CPUAttr.hasAttribute(Attribute::None) ++ ? CPUAttr.getValueAsString().str() ++ : TargetCPU; ++ std::string FS = !FSAttr.hasAttribute(Attribute::None) ++ ? FSAttr.getValueAsString().str() ++ : TargetFS; ++ ++ // FIXME: This is related to the code below to reset the target options, ++ // we need to know whether or not the soft float flag is set on the ++ // function, so we can enable it as a subtarget feature. ++ bool softFloat = ++ F.hasFnAttribute("use-soft-float") && ++ F.getFnAttribute("use-soft-float").getValueAsString() == "true"; ++ ++ if (softFloat) ++ FS += FS.empty() ? "+soft-float" : ",+soft-float"; + +- std::string Key = CPU + TuneCPU + FS; +- auto &I = SubtargetMap[Key]; ++ auto &I = SubtargetMap[CPU + FS]; + if (!I) { + // This needs to be done before we create a new subtarget since any + // creation will depend on the TM and the code generation flags on the + // function that reside in TargetOptions. + resetTargetOptions(F); +- auto ABIName = Options.MCOptions.getABIName(); +- if (const MDString *ModuleTargetABI = dyn_cast_or_null( +- F.getParent()->getModuleFlag("target-abi"))) { +- auto TargetABI = LoongArchABI::getTargetABI(ABIName); +- if (TargetABI != LoongArchABI::ABI_Unknown && +- ModuleTargetABI->getString() != ABIName) { +- report_fatal_error("-target-abi option != target-abi module flag"); +- } +- ABIName = ModuleTargetABI->getString(); +- } +- I = std::make_unique(TargetTriple, CPU, TuneCPU, FS, +- ABIName, *this); ++ I = std::make_unique(TargetTriple, CPU, FS, *this, ++ MaybeAlign(F.getParent()->getOverrideStackAlignment())); + } + return I.get(); + } + + namespace { ++ ++/// LoongArch Code Generator Pass Configuration Options. + class LoongArchPassConfig : public TargetPassConfig { + public: + LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) +- : TargetPassConfig(TM, PM) {} ++ : TargetPassConfig(TM, PM) { ++ } + + LoongArchTargetMachine &getLoongArchTargetMachine() const { + return getTM(); +@@ -102,22 +154,42 @@ public: + + void addIRPasses() override; + bool addInstSelector() override; ++ void addPreEmitPass() override; + }; +-} // end namespace + +-TargetPassConfig * +-LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { ++} // end anonymous namespace ++ ++TargetPassConfig *LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { + return new LoongArchPassConfig(*this, PM); + } + + void LoongArchPassConfig::addIRPasses() { +- addPass(createAtomicExpandPass()); +- + TargetPassConfig::addIRPasses(); ++ addPass(createAtomicExpandPass()); + } +- ++// Install an instruction selector pass using ++// the ISelDag to gen LoongArch code. + bool LoongArchPassConfig::addInstSelector() { +- addPass(createLoongArchISelDag(getLoongArchTargetMachine())); +- ++ addPass(createLoongArchModuleISelDagPass()); ++ addPass(createLoongArchISelDag(getLoongArchTargetMachine(), getOptLevel())); + return false; + } ++ ++TargetTransformInfo ++LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const { ++ LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); ++ return TargetTransformInfo(BasicTTIImpl(this, F)); ++} ++ ++// Implemented by targets that want to run passes immediately before ++// machine code is emitted. return true if -print-machineinstrs should ++// print out the code after the passes. ++void LoongArchPassConfig::addPreEmitPass() { ++ // Expand pseudo instructions that are sensitive to register allocation. ++ addPass(createLoongArchExpandPseudoPass()); ++ ++ // Relax conditional branch instructions if they're otherwise out of ++ // range of their destination. ++ // This pass must be run after any pseudo instruction expansion ++ addPass(&BranchRelaxationPassID); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h +index cbd872031..8e395d183 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h +@@ -1,4 +1,4 @@ +-//=- LoongArchTargetMachine.h - Define TargetMachine for LoongArch -*- C++ -*-// ++//===- LoongArchTargetMachine.h - Define TargetMachine for LoongArch ------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -13,25 +13,33 @@ + #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H + #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H + ++#include "MCTargetDesc/LoongArchABIInfo.h" + #include "LoongArchSubtarget.h" ++#include "llvm/ADT/Optional.h" ++#include "llvm/ADT/StringMap.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/Support/CodeGen.h" + #include "llvm/Target/TargetMachine.h" ++#include + + namespace llvm { + + class LoongArchTargetMachine : public LLVMTargetMachine { + std::unique_ptr TLOF; ++ // Selected ABI ++ LoongArchABIInfo ABI; ++ + mutable StringMap> SubtargetMap; + + public: + LoongArchTargetMachine(const Target &T, const Triple &TT, StringRef CPU, +- StringRef FS, const TargetOptions &Options, +- Optional RM, +- Optional CM, CodeGenOpt::Level OL, +- bool JIT); ++ StringRef FS, const TargetOptions &Options, ++ Optional RM, Optional CM, ++ CodeGenOpt::Level OL, bool JIT); + ~LoongArchTargetMachine() override; + ++ TargetTransformInfo getTargetTransformInfo(const Function &F) const override; + const LoongArchSubtarget *getSubtargetImpl(const Function &F) const override; +- const LoongArchSubtarget *getSubtargetImpl() const = delete; + + // Pass Pipeline Configuration + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; +@@ -39,6 +47,20 @@ public: + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } ++ ++ /// Returns true if a cast between SrcAS and DestAS is a noop. ++ bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override { ++ // Mips doesn't have any special address spaces so we just reserve ++ // the first 256 for software use (e.g. OpenCL) and treat casts ++ // between them as noops. ++ return SrcAS < 256 && DestAS < 256; ++ } ++ ++ const LoongArchABIInfo &getABI() const { return ABI; } ++ ++ bool isMachineVerifierClean() const override { ++ return false; ++ } + }; + + } // end namespace llvm +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp +new file mode 100644 +index 000000000..9c6250d28 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.cpp +@@ -0,0 +1,26 @@ ++//===-- LoongArchTargetObjectFile.cpp - LoongArch Object Files ----------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchTargetObjectFile.h" ++#include "LoongArchSubtarget.h" ++#include "LoongArchTargetMachine.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" ++#include "llvm/BinaryFormat/ELF.h" ++#include "llvm/IR/DataLayout.h" ++#include "llvm/IR/DerivedTypes.h" ++#include "llvm/IR/GlobalVariable.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCSectionELF.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Target/TargetMachine.h" ++using namespace llvm; ++ ++void LoongArchTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ ++ TargetLoweringObjectFileELF::Initialize(Ctx, TM); ++ InitializeELF(TM.Options.UseInitArray); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h +new file mode 100644 +index 000000000..a50c57171 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetObjectFile.h +@@ -0,0 +1,24 @@ ++//===-- llvm/Target/LoongArchTargetObjectFile.h - LoongArch Object Info ---*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETOBJECTFILE_H ++#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETOBJECTFILE_H ++ ++#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" ++ ++namespace llvm { ++class LoongArchTargetMachine; ++ class LoongArchTargetObjectFile : public TargetLoweringObjectFileELF { ++ ++ public: ++ ++ void Initialize(MCContext &Ctx, const TargetMachine &TM) override; ++ }; ++} // end namespace llvm ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h +new file mode 100644 +index 000000000..a9adc32d0 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetStreamer.h +@@ -0,0 +1,130 @@ ++//===-- LoongArchTargetStreamer.h - LoongArch Target Streamer ------------*- C++ -*--===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETSTREAMER_H ++#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETSTREAMER_H ++ ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "llvm/ADT/Optional.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/MC/MCELFStreamer.h" ++#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/MC/MCStreamer.h" ++ ++namespace llvm { ++ ++class formatted_raw_ostream; ++ ++struct LoongArchFPABIInfo; ++ ++class LoongArchTargetStreamer : public MCTargetStreamer { ++public: ++ LoongArchTargetStreamer(MCStreamer &S); ++ ++ virtual void setPic(bool Value) {} ++ ++ virtual void emitDirectiveOptionPic0(); ++ virtual void emitDirectiveOptionPic2(); ++ ++ virtual void emitDirectiveSetArch(StringRef Arch); ++ virtual void emitDirectiveSetLoongArch32(); ++ virtual void emitDirectiveSetloongarch64(); ++ ++ void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitRXX(unsigned Opcode, unsigned Reg0, MCOperand Op1, MCOperand Op2, ++ SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, ++ SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, ++ SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int32_t Imm, ++ SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitRRXX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, ++ MCOperand Op3, SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0, ++ int16_t Imm1, int16_t Imm2, SMLoc IDLoc, ++ const MCSubtargetInfo *STI); ++ void emitAdd(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit, ++ const MCSubtargetInfo *STI); ++ void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, ++ SMLoc IDLoc, const MCSubtargetInfo *STI); ++ void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI); ++ ++ void forbidModuleDirective() { ModuleDirectiveAllowed = false; } ++ void reallowModuleDirective() { ModuleDirectiveAllowed = true; } ++ bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } ++ ++ template ++ void updateABIInfo(const PredicateLibrary &P) { ++ ABI = P.getABI(); ++ } ++ ++ const LoongArchABIInfo &getABI() const { ++ assert(ABI.hasValue() && "ABI hasn't been set!"); ++ return *ABI; ++ } ++ ++protected: ++ llvm::Optional ABI; ++ ++ bool GPRInfoSet; ++ ++ bool FPRInfoSet; ++ ++ bool FrameInfoSet; ++ int FrameOffset; ++ unsigned FrameReg; ++ unsigned ReturnReg; ++ ++private: ++ bool ModuleDirectiveAllowed; ++}; ++ ++// This part is for ascii assembly output ++class LoongArchTargetAsmStreamer : public LoongArchTargetStreamer { ++ formatted_raw_ostream &OS; ++ ++public: ++ LoongArchTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); ++ ++ void emitDirectiveOptionPic0() override; ++ void emitDirectiveOptionPic2() override; ++ ++ void emitDirectiveSetArch(StringRef Arch) override; ++ void emitDirectiveSetLoongArch32() override; ++ void emitDirectiveSetloongarch64() override; ++}; ++ ++// This part is for ELF object output ++class LoongArchTargetELFStreamer : public LoongArchTargetStreamer { ++ const MCSubtargetInfo &STI; ++ bool Pic; ++ ++public: ++ MCELFStreamer &getStreamer(); ++ LoongArchTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); ++ ++ void setPic(bool Value) override { Pic = Value; } ++ ++ void emitLabel(MCSymbol *Symbol) override; ++ void finish() override; ++ ++ void emitDirectiveOptionPic0() override; ++ void emitDirectiveOptionPic2() override; ++}; ++} ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp +new file mode 100644 +index 000000000..9510dc027 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp +@@ -0,0 +1,325 @@ ++//===-- LoongArchTargetTransformInfo.cpp - LoongArch specific TTI pass ++//----------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++/// \file ++/// This file implements a TargetTransformInfo analysis pass specific to the ++/// LoongArch target machine. It uses the target's detailed information to ++/// provide more precise answers to certain TTI queries, while letting the ++/// target independent and default TTI implementations handle the rest. ++/// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchTargetTransformInfo.h" ++#include "llvm/Analysis/TargetTransformInfo.h" ++#include "llvm/CodeGen/BasicTTIImpl.h" ++#include "llvm/CodeGen/CostTable.h" ++#include "llvm/CodeGen/TargetLowering.h" ++#include "llvm/IR/IntrinsicInst.h" ++#include "llvm/Support/Debug.h" ++ ++using namespace llvm; ++ ++#define DEBUG_TYPE "LoongArchtti" ++ ++//===----------------------------------------------------------------------===// ++// ++// LoongArch cost model. ++// ++//===----------------------------------------------------------------------===// ++ ++bool LoongArchTTIImpl::areInlineCompatible(const Function *Caller, ++ const Function *Callee) const { ++ const TargetMachine &TM = getTLI()->getTargetMachine(); ++ ++ const FeatureBitset &CallerBits = ++ TM.getSubtargetImpl(*Caller)->getFeatureBits(); ++ const FeatureBitset &CalleeBits = ++ TM.getSubtargetImpl(*Callee)->getFeatureBits(); ++ ++ // Inline a callee if its target-features are a subset of the callers ++ // target-features. ++ return (CallerBits & CalleeBits) == CalleeBits; ++} ++ ++TargetTransformInfo::PopcntSupportKind ++LoongArchTTIImpl::getPopcntSupport(unsigned TyWidth) { ++ assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); ++ if (TyWidth == 32 || TyWidth == 64) ++ return TTI::PSK_FastHardware; ++ return TTI::PSK_Software; ++} ++ ++unsigned LoongArchTTIImpl::getNumberOfRegisters(bool Vector) { ++ if (Vector && !ST->hasLSX()) ++ return 0; ++ ++ return 32; ++} ++ ++unsigned LoongArchTTIImpl::getRegisterBitWidth(bool Vector) const { ++ if (Vector) { ++ if (ST->hasLASX()) ++ return 256; ++ ++ if (ST->hasLSX()) ++ return 128; ++ ++ return 0; ++ } ++ return 64; ++} ++ ++unsigned LoongArchTTIImpl::getMaxInterleaveFactor(unsigned VF) { ++ if (VF == 1) ++ return 1; ++ return 2; ++} ++ ++InstructionCost LoongArchTTIImpl::getArithmeticInstrCost( ++ unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, ++ TTI::OperandValueKind Op1Info, TTI::OperandValueKind Op2Info, ++ TTI::OperandValueProperties Opd1PropInfo, ++ TTI::OperandValueProperties Opd2PropInfo, ArrayRef Args, ++ const Instruction *CxtI) { ++ ++ std::pair LT = TLI->getTypeLegalizationCost(DL, Ty); ++ ++ int ISD = TLI->InstructionOpcodeToISD(Opcode); ++ assert(ISD && "Invalid opcode"); ++ ++ static const CostTblEntry LASXCostTable[] = { ++ ++ {ISD::SHL, MVT::v32i8, 1}, ++ {ISD::SHL, MVT::v16i16, 1}, ++ {ISD::SHL, MVT::v8i32, 1}, ++ {ISD::SHL, MVT::v4i64, 1}, ++ ++ {ISD::SRL, MVT::v32i8, 1}, ++ {ISD::SRL, MVT::v16i16, 1}, ++ {ISD::SRL, MVT::v8i32, 1}, ++ {ISD::SRL, MVT::v4i64, 1}, ++ ++ {ISD::SRA, MVT::v32i8, 1}, ++ {ISD::SRA, MVT::v16i16, 1}, ++ {ISD::SRA, MVT::v8i32, 1}, ++ {ISD::SRA, MVT::v4i64, 1}, ++ ++ {ISD::SUB, MVT::v32i8, 1}, ++ {ISD::SUB, MVT::v16i16, 1}, ++ {ISD::SUB, MVT::v8i32, 1}, ++ {ISD::SUB, MVT::v4i64, 1}, ++ ++ {ISD::ADD, MVT::v32i8, 1}, ++ {ISD::ADD, MVT::v16i16, 1}, ++ {ISD::ADD, MVT::v8i32, 1}, ++ {ISD::ADD, MVT::v4i64, 1}, ++ ++ {ISD::MUL, MVT::v32i8, 1}, ++ {ISD::MUL, MVT::v16i16, 1}, ++ {ISD::MUL, MVT::v8i32, 1}, ++ {ISD::MUL, MVT::v4i64, 1}, ++ ++ {ISD::SDIV, MVT::v32i8, 29}, ++ {ISD::SDIV, MVT::v16i16, 19}, ++ {ISD::SDIV, MVT::v8i32, 14}, ++ {ISD::SDIV, MVT::v4i64, 13}, ++ ++ {ISD::UDIV, MVT::v32i8, 29}, ++ {ISD::UDIV, MVT::v16i16, 19}, ++ {ISD::UDIV, MVT::v8i32, 14}, ++ {ISD::UDIV, MVT::v4i64, 13}, ++ ++ {ISD::SREM, MVT::v32i8, 33}, ++ {ISD::SREM, MVT::v16i16, 21}, ++ {ISD::SREM, MVT::v8i32, 15}, ++ {ISD::SREM, MVT::v4i64, 13}, ++ ++ {ISD::UREM, MVT::v32i8, 29}, ++ {ISD::UREM, MVT::v16i16, 19}, ++ {ISD::UREM, MVT::v8i32, 14}, ++ {ISD::UREM, MVT::v4i64, 13}, ++ ++ {ISD::FADD, MVT::f64, 1}, ++ {ISD::FADD, MVT::f32, 1}, ++ {ISD::FADD, MVT::v4f64, 1}, ++ {ISD::FADD, MVT::v8f32, 1}, ++ ++ {ISD::FSUB, MVT::f64, 1}, ++ {ISD::FSUB, MVT::f32, 1}, ++ {ISD::FSUB, MVT::v4f64, 1}, ++ {ISD::FSUB, MVT::v8f32, 1}, ++ ++ {ISD::FMUL, MVT::f64, 1}, ++ {ISD::FMUL, MVT::f32, 1}, ++ {ISD::FMUL, MVT::v4f64, 1}, ++ {ISD::FMUL, MVT::v8f32, 1}, ++ ++ {ISD::FDIV, MVT::f32, 12}, ++ {ISD::FDIV, MVT::f64, 10}, ++ {ISD::FDIV, MVT::v8f32, 12}, ++ {ISD::FDIV, MVT::v4f64, 10} ++ ++ }; ++ ++ if (ST->hasLASX()) ++ if (const auto *Entry = CostTableLookup(LASXCostTable, ISD, LT.second)) ++ return LT.first * Entry->Cost; ++ ++ static const CostTblEntry LSXCostTable[] = { ++ ++ {ISD::SHL, MVT::v16i8, 1}, ++ {ISD::SHL, MVT::v8i16, 1}, ++ {ISD::SHL, MVT::v4i32, 1}, ++ {ISD::SHL, MVT::v2i64, 1}, ++ ++ {ISD::SRL, MVT::v16i8, 1}, ++ {ISD::SRL, MVT::v8i16, 1}, ++ {ISD::SRL, MVT::v4i32, 1}, ++ {ISD::SRL, MVT::v2i64, 1}, ++ ++ {ISD::SRA, MVT::v16i8, 1}, ++ {ISD::SRA, MVT::v8i16, 1}, ++ {ISD::SRA, MVT::v4i32, 1}, ++ {ISD::SRA, MVT::v2i64, 1}, ++ ++ {ISD::SUB, MVT::v16i8, 1}, ++ {ISD::SUB, MVT::v8i16, 1}, ++ {ISD::SUB, MVT::v4i32, 1}, ++ {ISD::SUB, MVT::v2i64, 1}, ++ ++ {ISD::ADD, MVT::v16i8, 1}, ++ {ISD::ADD, MVT::v8i16, 1}, ++ {ISD::ADD, MVT::v4i32, 1}, ++ {ISD::ADD, MVT::v2i64, 1}, ++ ++ {ISD::MUL, MVT::v16i8, 1}, ++ {ISD::MUL, MVT::v8i16, 1}, ++ {ISD::MUL, MVT::v4i32, 1}, ++ {ISD::MUL, MVT::v2i64, 1}, ++ ++ {ISD::SDIV, MVT::v16i8, 29}, ++ {ISD::SDIV, MVT::v8i16, 19}, ++ {ISD::SDIV, MVT::v4i32, 14}, ++ {ISD::SDIV, MVT::v2i64, 13}, ++ ++ {ISD::UDIV, MVT::v16i8, 29}, ++ {ISD::UDIV, MVT::v8i16, 19}, ++ {ISD::UDIV, MVT::v4i32, 14}, ++ {ISD::UDIV, MVT::v2i64, 13}, ++ ++ {ISD::SREM, MVT::v16i8, 33}, ++ {ISD::SREM, MVT::v8i16, 21}, ++ {ISD::SREM, MVT::v4i32, 15}, ++ {ISD::SREM, MVT::v2i64, 13}, ++ ++ {ISD::UREM, MVT::v16i8, 29}, ++ {ISD::UREM, MVT::v8i16, 19}, ++ {ISD::UREM, MVT::v4i32, 14}, ++ {ISD::UREM, MVT::v2i64, 13}, ++ ++ {ISD::FADD, MVT::f64, 1}, ++ {ISD::FADD, MVT::f32, 1}, ++ {ISD::FADD, MVT::v2f64, 1}, ++ {ISD::FADD, MVT::v4f32, 1}, ++ ++ {ISD::FSUB, MVT::f64, 1}, ++ {ISD::FSUB, MVT::f32, 1}, ++ {ISD::FSUB, MVT::v2f64, 1}, ++ {ISD::FSUB, MVT::v4f32, 1}, ++ ++ {ISD::FMUL, MVT::f64, 1}, ++ {ISD::FMUL, MVT::f32, 1}, ++ {ISD::FMUL, MVT::v2f64, 1}, ++ {ISD::FMUL, MVT::v4f32, 1}, ++ ++ {ISD::FDIV, MVT::f32, 12}, ++ {ISD::FDIV, MVT::f64, 10}, ++ {ISD::FDIV, MVT::v4f32, 12}, ++ {ISD::FDIV, MVT::v2f64, 10} ++ ++ }; ++ ++ if (ST->hasLSX()) ++ if (const auto *Entry = CostTableLookup(LSXCostTable, ISD, LT.second)) ++ return LT.first * Entry->Cost; ++ ++ // Fallback to the default implementation. ++ return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info); ++} ++ ++InstructionCost LoongArchTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, ++ unsigned Index) { ++ assert(Val->isVectorTy() && "This must be a vector type"); ++ ++ Type *ScalarType = Val->getScalarType(); ++ ++ if (Index != -1U) { ++ // Legalize the type. ++ std::pair LT = TLI->getTypeLegalizationCost(DL, Val); ++ ++ // This type is legalized to a scalar type. ++ if (!LT.second.isVector()) ++ return 0; ++ ++ // The type may be split. Normalize the index to the new type. ++ unsigned Width = LT.second.getVectorNumElements(); ++ Index = Index % Width; ++ ++ // The element at index zero is already inside the vector. ++ if (Index == 0) // if (ScalarType->isFloatingPointTy() && Index == 0) ++ return 0; ++ } ++ ++ // Add to the base cost if we know that the extracted element of a vector is ++ // destined to be moved to and used in the integer register file. ++ int RegisterFileMoveCost = 0; ++ if (Opcode == Instruction::ExtractElement && ScalarType->isPointerTy()) ++ RegisterFileMoveCost = 1; ++ ++ return BaseT::getVectorInstrCost(Opcode, Val, Index) + RegisterFileMoveCost; ++} ++ ++unsigned LoongArchTTIImpl::getLoadStoreVecRegBitWidth(unsigned) const { ++ return getRegisterBitWidth(true); ++} ++ ++InstructionCost LoongArchTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, ++ Type *Src, ++ TTI::CastContextHint CCH, ++ TTI::TargetCostKind CostKind, ++ const Instruction *I) { ++ int ISD = TLI->InstructionOpcodeToISD(Opcode); ++ assert(ISD && "Invalid opcode"); ++ ++ static const TypeConversionCostTblEntry LASXConversionTbl[] = { ++ ++ // TODO:The cost requires more granular testing ++ {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 3}, ++ {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 3}, ++ {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 3}, ++ {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 3}, ++ {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 3}, ++ {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 3}, ++ ++ }; ++ ++ EVT SrcTy = TLI->getValueType(DL, Src); ++ EVT DstTy = TLI->getValueType(DL, Dst); ++ ++ if (!SrcTy.isSimple() || !DstTy.isSimple()) ++ return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); ++ ++ if (ST->hasLASX()) { ++ if (const auto *Entry = ConvertCostTableLookup( ++ LASXConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT())) ++ return Entry->Cost; ++ } ++ ++ return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h +new file mode 100644 +index 000000000..3a93fc8ec +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h +@@ -0,0 +1,91 @@ ++//===-- LoongArchTargetTransformInfo.h - LoongArch specific TTI -------------*- ++// C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// \file ++// This file a TargetTransformInfo::Concept conforming object specific to the ++// LoongArch target machine. It uses the target's detailed information to ++// provide more precise answers to certain TTI queries, while letting the ++// target independent and default TTI implementations handle the rest. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LoongArch_LoongArchTARGETTRANSFORMINFO_H ++#define LLVM_LIB_TARGET_LoongArch_LoongArchTARGETTRANSFORMINFO_H ++ ++#include "LoongArch.h" ++#include "LoongArchSubtarget.h" ++#include "LoongArchTargetMachine.h" ++#include "llvm/Analysis/TargetTransformInfo.h" ++#include "llvm/CodeGen/BasicTTIImpl.h" ++#include "llvm/CodeGen/TargetLowering.h" ++ ++namespace llvm { ++ ++class LoongArchTTIImpl : public BasicTTIImplBase { ++ typedef BasicTTIImplBase BaseT; ++ typedef TargetTransformInfo TTI; ++ friend BaseT; ++ ++ const LoongArchSubtarget *ST; ++ const LoongArchTargetLowering *TLI; ++ ++ const LoongArchSubtarget *getST() const { return ST; } ++ const LoongArchTargetLowering *getTLI() const { return TLI; } ++ ++public: ++ explicit LoongArchTTIImpl(const LoongArchTargetMachine *TM, const Function &F) ++ : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), ++ TLI(ST->getTargetLowering()) {} ++ ++ bool areInlineCompatible(const Function *Caller, ++ const Function *Callee) const; ++ ++ /// \name Scalar TTI Implementations ++ // /// @{ ++ ++ TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth); ++ ++ /// @} ++ ++ /// \name Vector TTI Implementations ++ /// @{ ++ ++ bool enableInterleavedAccessVectorization() { return true; } ++ ++ unsigned getNumberOfRegisters(bool Vector); ++ ++ unsigned getRegisterBitWidth(bool Vector) const; ++ ++ unsigned getMaxInterleaveFactor(unsigned VF); ++ ++ InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, ++ unsigned Index); ++ ++ InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, ++ TTI::CastContextHint CCH, ++ TTI::TargetCostKind CostKind, ++ const Instruction *I = nullptr); ++ ++ unsigned getLoadStoreVecRegBitWidth(unsigned AS) const; ++ ++ InstructionCost getArithmeticInstrCost( ++ unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, ++ TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, ++ TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, ++ TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, ++ TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, ++ ArrayRef Args = ArrayRef(), ++ const Instruction *CxtI = nullptr); ++ ++ /// @} ++}; ++ ++} // end namespace llvm ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt +index 2e1ca69a3..927fa7d5b 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt +@@ -1,12 +1,15 @@ +-add_llvm_component_library(LLVMLoongArchDesc ++ add_llvm_component_library(LLVMLoongArchDesc ++ LoongArchABIInfo.cpp ++ LoongArchAnalyzeImmediate.cpp + LoongArchAsmBackend.cpp +- LoongArchBaseInfo.cpp + LoongArchELFObjectWriter.cpp ++ LoongArchELFStreamer.cpp + LoongArchInstPrinter.cpp + LoongArchMCAsmInfo.cpp +- LoongArchMCTargetDesc.cpp + LoongArchMCCodeEmitter.cpp +- LoongArchMatInt.cpp ++ LoongArchMCExpr.cpp ++ LoongArchMCTargetDesc.cpp ++ LoongArchTargetStreamer.cpp + + LINK_COMPONENTS + MC +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp +new file mode 100644 +index 000000000..18b67961a +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.cpp +@@ -0,0 +1,106 @@ ++//===---- LoongArchABIInfo.cpp - Information about LoongArch ABI's ------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchABIInfo.h" ++#include "LoongArchRegisterInfo.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/MC/MCTargetOptions.h" ++ ++using namespace llvm; ++ ++namespace { ++static const MCPhysReg LP32IntRegs[4] = {LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3}; ++ ++static const MCPhysReg LoongArch64IntRegs[8] = { ++ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64, ++ LoongArch::A4_64, LoongArch::A5_64, LoongArch::A6_64, LoongArch::A7_64}; ++} ++ ++ArrayRef LoongArchABIInfo::GetByValArgRegs() const { ++ if (IsLP32()) ++ return makeArrayRef(LP32IntRegs); ++ if (IsLPX32() || IsLP64()) ++ return makeArrayRef(LoongArch64IntRegs); ++ llvm_unreachable("Unhandled ABI"); ++} ++ ++ArrayRef LoongArchABIInfo::GetVarArgRegs() const { ++ if (IsLP32()) ++ return makeArrayRef(LP32IntRegs); ++ if (IsLPX32() || IsLP64()) ++ return makeArrayRef(LoongArch64IntRegs); ++ llvm_unreachable("Unhandled ABI"); ++} ++ ++LoongArchABIInfo LoongArchABIInfo::computeTargetABI(const Triple &TT, StringRef CPU, ++ const MCTargetOptions &Options) { ++ if (Options.getABIName().startswith("lp32")) ++ return LoongArchABIInfo::LP32(); ++ if (Options.getABIName().startswith("lpx32")) ++ return LoongArchABIInfo::LPX32(); ++ if (Options.getABIName().startswith("lp64")) ++ return LoongArchABIInfo::LP64(); ++ assert(Options.getABIName().empty() && "Unknown ABI option for LoongArch"); ++ ++ if (TT.isLoongArch64()) ++ return LoongArchABIInfo::LP64(); ++ return LoongArchABIInfo::LP32(); ++} ++ ++unsigned LoongArchABIInfo::GetStackPtr() const { ++ return ArePtrs64bit() ? LoongArch::SP_64 : LoongArch::SP; ++} ++ ++unsigned LoongArchABIInfo::GetFramePtr() const { ++ return ArePtrs64bit() ? LoongArch::FP_64 : LoongArch::FP; ++} ++ ++unsigned LoongArchABIInfo::GetBasePtr() const { ++ return ArePtrs64bit() ? LoongArch::S7_64 : LoongArch::S7; ++} ++ ++unsigned LoongArchABIInfo::GetNullPtr() const { ++ return ArePtrs64bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; ++} ++ ++unsigned LoongArchABIInfo::GetZeroReg() const { ++ return AreGprs64bit() ? LoongArch::ZERO_64 : LoongArch::ZERO; ++} ++ ++unsigned LoongArchABIInfo::GetPtrAddOp() const { ++ return ArePtrs64bit() ? LoongArch::ADD_D : LoongArch::ADD_W; ++} ++ ++unsigned LoongArchABIInfo::GetPtrAddiOp() const { ++ return ArePtrs64bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++} ++ ++unsigned LoongArchABIInfo::GetPtrSubOp() const { ++ return ArePtrs64bit() ? LoongArch::SUB_D : LoongArch::SUB_W; ++} ++ ++unsigned LoongArchABIInfo::GetPtrAndOp() const { ++ return ArePtrs64bit() ? LoongArch::AND : LoongArch::AND32; ++} ++ ++unsigned LoongArchABIInfo::GetGPRMoveOp() const { ++ return ArePtrs64bit() ? LoongArch::OR : LoongArch::OR32; ++} ++ ++unsigned LoongArchABIInfo::GetEhDataReg(unsigned I) const { ++ static const unsigned EhDataReg[] = { ++ LoongArch::A0, LoongArch::A1, LoongArch::A2, LoongArch::A3 ++ }; ++ static const unsigned EhDataReg64[] = { ++ LoongArch::A0_64, LoongArch::A1_64, LoongArch::A2_64, LoongArch::A3_64 ++ }; ++ ++ return IsLP64() ? EhDataReg64[I] : EhDataReg[I]; ++} ++ +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h +new file mode 100644 +index 000000000..334ee80ea +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchABIInfo.h +@@ -0,0 +1,76 @@ ++//===---- LoongArchABIInfo.h - Information about LoongArch ABI's --------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHABIINFO_H ++#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHABIINFO_H ++ ++#include "llvm/ADT/Triple.h" ++#include "llvm/IR/CallingConv.h" ++#include "llvm/MC/MCRegisterInfo.h" ++ ++namespace llvm { ++ ++template class ArrayRef; ++class MCTargetOptions; ++class StringRef; ++class TargetRegisterClass; ++ ++class LoongArchABIInfo { ++public: ++ enum class ABI { Unknown, LP32, LPX32, LP64 }; ++ ++protected: ++ ABI ThisABI; ++ ++public: ++ LoongArchABIInfo(ABI ThisABI) : ThisABI(ThisABI) {} ++ ++ static LoongArchABIInfo Unknown() { return LoongArchABIInfo(ABI::Unknown); } ++ static LoongArchABIInfo LP32() { return LoongArchABIInfo(ABI::LP32); } ++ static LoongArchABIInfo LPX32() { return LoongArchABIInfo(ABI::LPX32); } ++ static LoongArchABIInfo LP64() { return LoongArchABIInfo(ABI::LP64); } ++ static LoongArchABIInfo computeTargetABI(const Triple &TT, StringRef CPU, ++ const MCTargetOptions &Options); ++ ++ bool IsKnown() const { return ThisABI != ABI::Unknown; } ++ bool IsLP32() const { return ThisABI == ABI::LP32; } ++ bool IsLPX32() const { return ThisABI == ABI::LPX32; } ++ bool IsLP64() const { return ThisABI == ABI::LP64; } ++ ABI GetEnumValue() const { return ThisABI; } ++ ++ /// The registers to use for byval arguments. ++ ArrayRef GetByValArgRegs() const; ++ ++ /// The registers to use for the variable argument list. ++ ArrayRef GetVarArgRegs() const; ++ ++ /// Ordering of ABI's ++ /// LoongArchGenSubtargetInfo.inc will use this to resolve conflicts when given ++ /// multiple ABI options. ++ bool operator<(const LoongArchABIInfo Other) const { ++ return ThisABI < Other.GetEnumValue(); ++ } ++ ++ unsigned GetStackPtr() const; ++ unsigned GetFramePtr() const; ++ unsigned GetBasePtr() const; ++ unsigned GetNullPtr() const; ++ unsigned GetZeroReg() const; ++ unsigned GetPtrAddOp() const; ++ unsigned GetPtrAddiOp() const; ++ unsigned GetPtrSubOp() const; ++ unsigned GetPtrAndOp() const; ++ unsigned GetGPRMoveOp() const; ++ inline bool ArePtrs64bit() const { return IsLP64(); } ++ inline bool AreGprs64bit() const { return IsLPX32() || IsLP64(); } ++ ++ unsigned GetEhDataReg(unsigned I) const; ++}; ++} ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp +new file mode 100644 +index 000000000..96e43b2d3 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.cpp +@@ -0,0 +1,64 @@ ++//===- LoongArchAnalyzeImmediate.cpp - Analyze Immediates -----------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchAnalyzeImmediate.h" ++#include "LoongArch.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/Support/MathExtras.h" ++ ++using namespace llvm; ++ ++LoongArchAnalyzeImmediate::InstSeq ++LoongArchAnalyzeImmediate::generateInstSeq(int64_t Val, bool Is64Bit) { ++ // Val: ++ // | hi32 | lo32 | ++ // +------------+------------------+------------------+-----------+ ++ // | Bits_52_63 | Bits_32_51 | Bits_12_31 | Bits_0_11 | ++ // +------------+------------------+------------------+-----------+ ++ // 63 52 51 32 31 12 11 0 ++ unsigned ORIOp = Is64Bit ? LoongArch::ORI : LoongArch::ORI32; ++ unsigned LU12IOp = Is64Bit ? LoongArch::LU12I_W : LoongArch::LU12I_W32; ++ unsigned ADDIOp = Is64Bit ? LoongArch::ADDI_W64 : LoongArch::ADDI_W; ++ unsigned LU32IOp = LoongArch::LU32I_D_R2; ++ unsigned LU52IOp = LoongArch::LU52I_D; ++ ++ int64_t Bits_52_63 = Val >> 52 & 0xFFF; ++ int64_t Bits_32_51 = Val >> 32 & 0xFFFFF; ++ int64_t Bits_12_31 = Val >> 12 & 0xFFFFF; ++ int64_t Bits_0_11 = Val & 0xFFF; ++ ++ InstSeq Insts; ++ ++ if (isInt<12>(Val) && Is64Bit) { ++ Insts.push_back(Inst(LoongArch::ADDI_D, SignExtend64<12>(Bits_0_11))); ++ return Insts; ++ } ++ ++ if (Bits_52_63 != 0 && SignExtend64<52>(Val) == 0) { ++ Insts.push_back(Inst(LU52IOp, SignExtend64<12>(Bits_52_63))); ++ return Insts; ++ } ++ ++ if (Bits_12_31 == 0) ++ Insts.push_back(Inst(ORIOp, Bits_0_11)); ++ else if (SignExtend32<1>(Bits_0_11 >> 11) == SignExtend32<20>(Bits_12_31)) ++ Insts.push_back(Inst(ADDIOp, SignExtend64<12>(Bits_0_11))); ++ else { ++ Insts.push_back(Inst(LU12IOp, SignExtend64<20>(Bits_12_31))); ++ if (Bits_0_11 != 0) ++ Insts.push_back(Inst(ORIOp, Bits_0_11)); ++ } ++ ++ if (SignExtend32<1>(Bits_12_31 >> 19) != SignExtend32<20>(Bits_32_51)) ++ Insts.push_back(Inst(LU32IOp, SignExtend64<20>(Bits_32_51))); ++ ++ if (SignExtend32<1>(Bits_32_51 >> 19) != SignExtend32<12>(Bits_52_63)) ++ Insts.push_back(Inst(LU52IOp, SignExtend64<12>(Bits_52_63))); ++ ++ return Insts; ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h +similarity index 62% +rename from src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h +rename to src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h +index be1b42589..3ff00f254 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAnalyzeImmediate.h +@@ -1,4 +1,4 @@ +-//===- LoongArchMatInt.h - Immediate materialisation - --------*- C++ -*--===// ++//===- LoongArchAnalyzeImmediate.h - Analyze Immediates --------*- C++ -*--===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,14 +6,13 @@ + // + //===----------------------------------------------------------------------===// + +-#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_MATINT_H +-#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_MATINT_H ++#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H ++#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H + + #include "llvm/ADT/SmallVector.h" +-#include + + namespace llvm { +-namespace LoongArchMatInt { ++namespace LoongArchAnalyzeImmediate { + struct Inst { + unsigned Opc; + int64_t Imm; +@@ -23,8 +22,8 @@ using InstSeq = SmallVector; + + // Helper to generate an instruction sequence that will materialise the given + // immediate value into a register. +-InstSeq generateInstSeq(int64_t Val); +-} // end namespace LoongArchMatInt ++InstSeq generateInstSeq(int64_t Val, bool Is64Bit); ++} // end namespace LoongArchAnalyzeImmediate + } // end namespace llvm + +-#endif ++#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHANALYZEIMMEDIATE_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index 94a068897..b9ba9e536 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchAsmBackend.cpp - LoongArch Assembler Backend -*- C++ -*---===// ++//===-- LoongArchAsmBackend.cpp - LoongArch Asm Backend ----------------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -9,41 +9,158 @@ + // This file implements the LoongArchAsmBackend class. + // + //===----------------------------------------------------------------------===// ++// + +-#include "LoongArchAsmBackend.h" +-#include "llvm/MC/MCAsmLayout.h" ++#include "MCTargetDesc/LoongArchAsmBackend.h" ++#include "MCTargetDesc/LoongArchABIInfo.h" ++#include "MCTargetDesc/LoongArchFixupKinds.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/MC/MCAsmBackend.h" + #include "llvm/MC/MCAssembler.h" + #include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCDirectives.h" + #include "llvm/MC/MCELFObjectWriter.h" +-#include "llvm/Support/Endian.h" ++#include "llvm/MC/MCFixupKindInfo.h" ++#include "llvm/MC/MCObjectWriter.h" ++#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCTargetOptions.h" ++#include "llvm/MC/MCValue.h" + #include "llvm/Support/EndianStream.h" +- +-#define DEBUG_TYPE "loongarch-asmbackend" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/Format.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Support/raw_ostream.h" + + using namespace llvm; + +-void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, +- const MCFixup &Fixup, +- const MCValue &Target, +- MutableArrayRef Data, uint64_t Value, +- bool IsResolved, +- const MCSubtargetInfo *STI) const { +- // TODO: Apply the Value for given Fixup into the provided data fragment. +- return; ++std::unique_ptr ++LoongArchAsmBackend::createObjectTargetWriter() const { ++ return createLoongArchELFObjectWriter(TheTriple, IsLPX32); + } + +-bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, +- const MCFixup &Fixup, +- const MCValue &Target) { +- // TODO: Determine which relocation require special processing at linking +- // time. +- return false; ++/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided ++/// data fragment, at the offset specified by the fixup and following the ++/// fixup kind as appropriate. ++void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, ++ const MCValue &Target, ++ MutableArrayRef Data, uint64_t Value, ++ bool IsResolved, ++ const MCSubtargetInfo *STI) const { ++ MCFixupKind Kind = Fixup.getKind(); ++ if (Kind > FirstTargetFixupKind) ++ return; ++ ++ if (!Value) ++ return; // Doesn't change encoding. ++ ++ // Where do we start in the object ++ unsigned Offset = Fixup.getOffset(); ++ // Number of bytes we need to fixup ++ unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; ++ ++ ++ // Grab current value, if any, from bits. ++ uint64_t CurVal = 0; ++ ++ for (unsigned i = 0; i != NumBytes; ++i) ++ CurVal |= (uint64_t)((uint8_t)Data[Offset + i]) << (i*8); ++ ++ uint64_t Mask = ((uint64_t)(-1) >> ++ (64 - getFixupKindInfo(Kind).TargetSize)); ++ CurVal |= Value & Mask; ++ ++ // Write out the fixed up bytes back to the code/data bits. ++ for (unsigned i = 0; i != NumBytes; ++i) ++ Data[Offset + i] = (uint8_t)((CurVal >> (i*8)) & 0xff); + } + ++Optional LoongArchAsmBackend::getFixupKind(StringRef Name) const { ++ return StringSwitch>(Name) ++ .Case("R_LARCH_NONE", (MCFixupKind)LoongArch::fixup_LARCH_NONE) ++ .Case("R_LARCH_32", FK_Data_4) ++ .Case("R_LARCH_64", FK_Data_8) ++ .Default(MCAsmBackend::getFixupKind(Name)); ++} ++ ++const MCFixupKindInfo &LoongArchAsmBackend:: ++getFixupKindInfo(MCFixupKind Kind) const { ++ const static MCFixupKindInfo Infos[] = { ++ // This table *must* be in same the order of fixup_* kinds in ++ // LoongArchFixupKinds.h. ++ // ++ // name offset bits flags ++ { "fixup_LARCH_NONE", 0, 0, 0 }, ++ { "fixup_LARCH_SOP_PUSH_ABSOLUTE", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_PCREL", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_GPREL", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_TLS_TPREL", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_TLS_GOT", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_TLS_GD", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_PLT_PCREL", 0, 0, 0}, ++ { "fixup_LARCH_32", 0, 0, 0}, ++ { "fixup_LARCH_64", 0, 0, 0}, ++ { "fixup_LARCH_RELATIVE", 0, 0, 0}, ++ { "fixup_LARCH_COPY", 0, 0, 0}, ++ { "fixup_LARCH_JUMP_SLOT", 0, 0, 0}, ++ { "fixup_LARCH_TLS_DTPMOD32", 0, 0, 0}, ++ { "fixup_LARCH_TLS_DTPMOD64", 0, 0, 0}, ++ { "fixup_LARCH_TLS_DTPREL32", 0, 0, 0}, ++ { "fixup_LARCH_TLS_DTPREL64", 0, 0, 0}, ++ { "fixup_LARCH_TLS_TPREL32", 0, 0, 0}, ++ { "fixup_LARCH_TLS_TPREL64", 0, 0, 0}, ++ { "fixup_LARCH_IRELATIVE", 0, 0, 0}, ++ { "fixup_LARCH_MARK_LA", 0, 0, 0}, ++ { "fixup_LARCH_MARK_PCREL", 0, 0, 0}, ++ { "fixup_LARCH_SOP_PUSH_DUP", 0, 0, 0}, ++ { "fixup_LARCH_SOP_ASSERT", 0, 0, 0}, ++ { "fixup_LARCH_SOP_NOT", 0, 0, 0}, ++ { "fixup_LARCH_SOP_SUB", 0, 0, 0}, ++ { "fixup_LARCH_SOP_SL", 0, 0, 0}, ++ { "fixup_LARCH_SOP_SR", 0, 0, 0}, ++ { "fixup_LARCH_SOP_ADD", 0, 0, 0}, ++ { "fixup_LARCH_SOP_AND", 0, 0, 0}, ++ { "fixup_LARCH_SOP_IF_ELSE", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_10_5", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_U_10_12", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_10_12", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_10_16", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_10_16_S2", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_5_20", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2", 0, 0, 0}, ++ { "fixup_LARCH_SOP_POP_32_U", 0, 0, 0}, ++ { "fixup_LARCH_ADD8", 0, 0, 0}, ++ { "fixup_LARCH_ADD16", 0, 0, 0}, ++ { "fixup_LARCH_ADD24", 0, 0, 0}, ++ { "fixup_LARCH_ADD32", 0, 0, 0}, ++ { "fixup_LARCH_ADD64", 0, 0, 0}, ++ { "fixup_LARCH_SUB8", 0, 0, 0}, ++ { "fixup_LARCH_SUB16", 0, 0, 0}, ++ { "fixup_LARCH_SUB24", 0, 0, 0}, ++ { "fixup_LARCH_SUB32", 0, 0, 0}, ++ { "fixup_LARCH_SUB64", 0, 0, 0}, ++ }; ++ ++ if (Kind < FirstTargetFixupKind) ++ return MCAsmBackend::getFixupKindInfo(Kind); ++ ++ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && ++ "Invalid kind!"); ++ ++ return Infos[Kind - FirstTargetFixupKind]; ++} ++ ++/// WriteNopData - Write an (optimal) nop sequence of Count bytes ++/// to the given output. If the target cannot generate such a sequence, ++/// it should return an error. ++/// ++/// \return - True on success. + bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { +- // Check for byte count not multiple of instruction word size +- if (Count % 4 != 0) ++ // Check for a less than instruction size number of bytes ++ if ((Count % 4) != 0) + return false; + + // The nop on LoongArch is andi r0, r0, 0. +@@ -53,16 +170,45 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + return true; + } + +-std::unique_ptr +-LoongArchAsmBackend::createObjectTargetWriter() const { +- return createLoongArchELFObjectWriter(OSABI, Is64Bit); ++bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, ++ const MCFixup &Fixup, ++ const MCValue &Target) { ++ const unsigned FixupKind = Fixup.getKind(); ++ switch (FixupKind) { ++ default: ++ return false; ++ // All these relocations require special processing ++ // at linking time. Delegate this work to a linker. ++ case LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL: ++ case LoongArch::fixup_LARCH_SOP_PUSH_PCREL: ++ case LoongArch::fixup_LARCH_SOP_PUSH_GPREL: ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD: ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT: ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL: ++ case LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE: ++ case LoongArch::fixup_LARCH_SOP_IF_ELSE: ++ case LoongArch::fixup_LARCH_SOP_ADD: ++ case LoongArch::fixup_LARCH_SOP_SUB: ++ case LoongArch::fixup_LARCH_SOP_AND: ++ case LoongArch::fixup_LARCH_SOP_SL: ++ case LoongArch::fixup_LARCH_SOP_SR: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_5: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_5_20: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_12: ++ case LoongArch::fixup_LARCH_SOP_POP_32_U_10_12: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ return true; ++ } + } + + MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { +- const Triple &TT = STI.getTargetTriple(); +- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); +- return new LoongArchAsmBackend(STI, OSABI, TT.isArch64Bit()); ++ LoongArchABIInfo ABI = LoongArchABIInfo::computeTargetABI( ++ STI.getTargetTriple(), STI.getCPU(), Options); ++ return new LoongArchAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), ++ ABI.IsLPX32()); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +index a5f0b816c..45ae6af44 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +@@ -1,4 +1,4 @@ +-//===-- LoongArchAsmBackend.h - LoongArch Assembler Backend ---*- C++ -*---===// ++//===-- LoongArchAsmBackend.h - LoongArch Asm Backend ------------------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -9,55 +9,83 @@ + // This file defines the LoongArchAsmBackend class. + // + //===----------------------------------------------------------------------===// ++// + + #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H + #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H + +-#include "MCTargetDesc/LoongArchBaseInfo.h" +-#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "MCTargetDesc/LoongArchFixupKinds.h" ++#include "llvm/ADT/Triple.h" + #include "llvm/MC/MCAsmBackend.h" +-#include "llvm/MC/MCFixupKindInfo.h" +-#include "llvm/MC/MCSubtargetInfo.h" + + namespace llvm { + ++class MCAssembler; ++struct MCFixupKindInfo; ++class MCObjectWriter; ++class MCRegisterInfo; ++class MCSymbolELF; ++class Target; ++ + class LoongArchAsmBackend : public MCAsmBackend { +- uint8_t OSABI; +- bool Is64Bit; ++ Triple TheTriple; ++ bool IsLPX32; + + public: +- LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit) +- : MCAsmBackend(support::little), OSABI(OSABI), Is64Bit(Is64Bit) {} +- ~LoongArchAsmBackend() override {} ++ LoongArchAsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TT, ++ StringRef CPU, bool LPX32) ++ : MCAsmBackend(support::little), ++ TheTriple(TT), IsLPX32(LPX32) { ++ assert(TT.isLittleEndian()); ++ } ++ ++ std::unique_ptr ++ createObjectTargetWriter() const override; + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + +- bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, +- const MCValue &Target) override; ++ Optional getFixupKind(StringRef Name) const override; ++ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; ++ ++ unsigned getNumFixupKinds() const override { ++ return LoongArch::NumTargetFixupKinds; ++ } ++ ++ /// @name Target Relaxation Interfaces ++ /// @{ + +- bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, +- const MCRelaxableFragment *DF, +- const MCAsmLayout &Layout) const override { ++ /// MayNeedRelaxation - Check whether the given instruction may need ++ /// relaxation. ++ /// ++ /// \param Inst - The instruction to test. ++ bool mayNeedRelaxation(const MCInst &Inst, ++ const MCSubtargetInfo &STI) const override { + return false; + } + +- unsigned getNumFixupKinds() const override { +- // FIXME: Implement this when we define fixup kind +- return 0; ++ /// fixupNeedsRelaxation - Target specific predicate for whether a given ++ /// fixup requires the associated instruction to be relaxed. ++ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, ++ const MCRelaxableFragment *DF, ++ const MCAsmLayout &Layout) const override { ++ // FIXME. ++ llvm_unreachable("RelaxInstruction() unimplemented"); ++ return false; + } + +- void relaxInstruction(MCInst &Inst, +- const MCSubtargetInfo &STI) const override {} ++ /// @} + + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; + +- std::unique_ptr +- createObjectTargetWriter() const override; +-}; +-} // end namespace llvm ++ bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, ++ const MCValue &Target) override; ++ ++}; // class LoongArchAsmBackend ++ ++} // namespace + +-#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp +deleted file mode 100644 +index de2ba2833..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp ++++ /dev/null +@@ -1,40 +0,0 @@ +-//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- C++ -*-// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +-// +-// This file implements helper functions for the LoongArch target useful for the +-// compiler back-end and the MC libraries. +-// +-//===----------------------------------------------------------------------===// +- +-#include "LoongArchBaseInfo.h" +-#include "llvm/ADT/ArrayRef.h" +-#include "llvm/ADT/Triple.h" +-#include "llvm/MC/MCSubtargetInfo.h" +- +-namespace llvm { +- +-namespace LoongArchABI { +- +-ABI getTargetABI(StringRef ABIName) { +- auto TargetABI = StringSwitch(ABIName) +- .Case("ilp32s", ABI_ILP32S) +- .Case("ilp32f", ABI_ILP32F) +- .Case("ilp32d", ABI_ILP32D) +- .Case("lp64s", ABI_LP64S) +- .Case("lp64f", ABI_LP64F) +- .Case("lp64d", ABI_LP64D) +- .Default(ABI_Unknown); +- return TargetABI; +-} +- +-// FIXME: other register? +-MCRegister getBPReg() { return LoongArch::R31; } +- +-} // end namespace LoongArchABI +- +-} // end namespace llvm +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h +index fee247a0c..707333c18 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h +@@ -1,4 +1,4 @@ +-//=- LoongArchBaseInfo.h - Top level definitions for LoongArch MC -*- C++ -*-=// ++//===-- LoongArchBaseInfo.h - Top level definitions for LoongArch MC ------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,39 +6,123 @@ + // + //===----------------------------------------------------------------------===// + // +-// This file contains small standalone enum definitions and helper function +-// definitions for the LoongArch target useful for the compiler back-end and the +-// MC libraries. ++// This file contains small standalone helper functions and enum definitions for ++// the LoongArch target useful for the compiler back-end and the MC libraries. + // + //===----------------------------------------------------------------------===// + #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H + #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H + +-#include "MCTargetDesc/LoongArchMCTargetDesc.h" +-#include "llvm/ADT/StringRef.h" +-#include "llvm/ADT/StringSwitch.h" +-#include "llvm/MC/MCInstrDesc.h" +-#include "llvm/MC/SubtargetFeature.h" ++#include "LoongArchFixupKinds.h" ++#include "LoongArchMCTargetDesc.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/Support/DataTypes.h" ++#include "llvm/Support/ErrorHandling.h" + + namespace llvm { + +-namespace LoongArchABI { +-enum ABI { +- ABI_ILP32S, +- ABI_ILP32F, +- ABI_ILP32D, +- ABI_LP64S, +- ABI_LP64F, +- ABI_LP64D, +- ABI_Unknown +-}; ++/// LoongArchII - This namespace holds all of the target specific flags that ++/// instruction info tracks. ++/// ++namespace LoongArchII { ++ /// Target Operand Flag enum. ++ enum TOF { ++ //===------------------------------------------------------------------===// ++ // LoongArch Specific MachineOperand flags. + +-ABI getTargetABI(StringRef ABIName); ++ MO_NO_FLAG, + +-// Returns the register used to hold the stack pointer after realignment. +-MCRegister getBPReg(); +-} // end namespace LoongArchABI ++ /// MO_ABS_XXX - Represents the hi or low part of an absolute symbol ++ /// address. ++ MO_ABS_HI, ++ MO_ABS_LO, ++ MO_ABS_HIGHER, ++ MO_ABS_HIGHEST, + +-} // end namespace llvm ++ /// MO_PCREL_XXX - Represents the hi or low part of an pc relative symbol ++ /// address. ++ MO_PCREL_HI, ++ MO_PCREL_LO, ++ // with tmp reg ++ MO_PCREL_RRHI, ++ MO_PCREL_RRLO, ++ MO_PCREL_RRHIGHER, ++ MO_PCREL_RRHIGHEST, + +-#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H ++ // LArch Tls gd and ld ++ MO_TLSGD_HI, ++ MO_TLSGD_LO, ++ // with tmp reg ++ MO_TLSGD_RRHI, ++ MO_TLSGD_RRLO, ++ MO_TLSGD_RRHIGHER, ++ MO_TLSGD_RRHIGHEST, ++ ++ // LArch thread tprel (ie/le) ++ // LArch Tls ie ++ MO_TLSIE_HI, ++ MO_TLSIE_LO, ++ // with tmp reg ++ MO_TLSIE_RRHI, ++ MO_TLSIE_RRLO, ++ MO_TLSIE_RRHIGHER, ++ MO_TLSIE_RRHIGHEST, ++ // LArch Tls le ++ MO_TLSLE_HI, ++ MO_TLSLE_LO, ++ MO_TLSLE_HIGHER, ++ MO_TLSLE_HIGHEST, ++ ++ // Loongarch got ++ MO_GOT_HI, ++ MO_GOT_LO, ++ // with tmp reg ++ MO_GOT_RRHI, ++ MO_GOT_RRLO, ++ MO_GOT_RRHIGHER, ++ MO_GOT_RRHIGHEST, ++ ++ MO_CALL_HI, ++ MO_CALL_LO, ++ }; ++ ++ enum { ++ //===------------------------------------------------------------------===// ++ // Instruction encodings. These are the standard/most common forms for ++ // LoongArch instructions. ++ // ++ ++ // Pseudo - This represents an instruction that is a pseudo instruction ++ // or one that has not been implemented yet. It is illegal to code generate ++ // it, but tolerated for intermediate implementation stages. ++ Pseudo = 0, ++ ++ /// FrmR - This form is for instructions of the format R. ++ FrmR = 1, ++ /// FrmI - This form is for instructions of the format I. ++ FrmI = 2, ++ /// FrmJ - This form is for instructions of the format J. ++ FrmJ = 3, ++ /// FrmFR - This form is for instructions of the format FR. ++ FrmFR = 4, ++ /// FrmFI - This form is for instructions of the format FI. ++ FrmFI = 5, ++ /// FrmOther - This form is for instructions that have no specific format. ++ FrmOther = 6, ++ ++ FormMask = 15, ++ /// IsCTI - Instruction is a Control Transfer Instruction. ++ IsCTI = 1 << 4, ++ /// HasForbiddenSlot - Instruction has a forbidden slot. ++ HasForbiddenSlot = 1 << 5, ++ /// IsPCRelativeLoad - A Load instruction with implicit source register ++ /// ($pc) with explicit offset and destination register ++ IsPCRelativeLoad = 1 << 6, ++ /// HasFCCRegOperand - Instruction uses an $fcc register. ++ HasFCCRegOperand = 1 << 7 ++ ++ }; ++} ++} ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +index 1850b0d8a..e00b9af9d 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer ---*- C++ -*---===// ++//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer -------------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -6,59 +6,181 @@ + // + //===----------------------------------------------------------------------===// + ++#include "MCTargetDesc/LoongArchFixupKinds.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/BinaryFormat/ELF.h" + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCELFObjectWriter.h" + #include "llvm/MC/MCFixup.h" + #include "llvm/MC/MCObjectWriter.h" ++#include "llvm/MC/MCSymbolELF.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/Compiler.h" ++#include "llvm/Support/Debug.h" + #include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Support/raw_ostream.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DEBUG_TYPE "loongarch-elf-object-writer" + + using namespace llvm; + + namespace { ++ + class LoongArchELFObjectWriter : public MCELFObjectTargetWriter { + public: +- LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); ++ LoongArchELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64); + +- ~LoongArchELFObjectWriter() override; ++ ~LoongArchELFObjectWriter() override = default; + +- // Return true if the given relocation must be with a symbol rather than +- // section plus offset. ++ unsigned getRelocType(MCContext &Ctx, const MCValue &Target, ++ const MCFixup &Fixup, bool IsPCRel) const override; + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override { + return true; + } +- +-protected: +- unsigned getRelocType(MCContext &Ctx, const MCValue &Target, +- const MCFixup &Fixup, bool IsPCRel) const override; + }; +-} // end namespace + +-LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) +- : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH, +- /*HasRelocationAddend*/ true) {} ++} // end anonymous namespace + +-LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {} ++LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, ++ bool HasRelocationAddend, bool Is64) ++ : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_LOONGARCH, HasRelocationAddend) {} + + unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx, +- const MCValue &Target, +- const MCFixup &Fixup, +- bool IsPCRel) const { +- // Determine the type of the relocation +- unsigned Kind = Fixup.getTargetKind(); +- +- if (Kind >= FirstLiteralRelocationKind) +- return Kind - FirstLiteralRelocationKind; ++ const MCValue &Target, ++ const MCFixup &Fixup, ++ bool IsPCRel) const { ++ // Determine the type of the relocation. ++ ///XXX:Reloc ++ unsigned Kind = (unsigned)Fixup.getKind(); + + switch (Kind) { +- // TODO: Implement this when we defined fixup kind. +- default: +- return ELF::R_LARCH_NONE; ++ default: ++ return ELF::R_LARCH_NONE; ++ //llvm_unreachable("invalid fixup kind!"); ++ case FK_Data_4: ++ case LoongArch::fixup_LARCH_32: ++ return ELF::R_LARCH_32; ++ case FK_GPRel_4: ++ case FK_Data_8: ++ case LoongArch::fixup_LARCH_64: ++ return ELF::R_LARCH_64; ++ case LoongArch::fixup_LARCH_NONE: ++ return ELF::R_LARCH_NONE; ++ case LoongArch::fixup_LARCH_RELATIVE: ++ return ELF::R_LARCH_RELATIVE; ++ case LoongArch::fixup_LARCH_COPY: ++ return ELF::R_LARCH_COPY; ++ case LoongArch::fixup_LARCH_JUMP_SLOT: ++ return ELF::R_LARCH_JUMP_SLOT; ++ case LoongArch::fixup_LARCH_TLS_DTPMOD32: ++ return ELF::R_LARCH_TLS_DTPMOD32; ++ case LoongArch::fixup_LARCH_TLS_DTPMOD64: ++ return ELF::R_LARCH_TLS_DTPMOD64; ++ case LoongArch::fixup_LARCH_TLS_DTPREL32: ++ return ELF::R_LARCH_TLS_DTPREL32; ++ case LoongArch::fixup_LARCH_TLS_DTPREL64: ++ return ELF::R_LARCH_TLS_DTPREL64; ++ case LoongArch::fixup_LARCH_TLS_TPREL32: ++ return ELF::R_LARCH_TLS_TPREL32; ++ case LoongArch::fixup_LARCH_TLS_TPREL64: ++ return ELF::R_LARCH_TLS_TPREL64; ++ case LoongArch::fixup_LARCH_IRELATIVE: ++ return ELF::R_LARCH_IRELATIVE; ++ case LoongArch::fixup_LARCH_MARK_LA: ++ return ELF::R_LARCH_MARK_LA; ++ case LoongArch::fixup_LARCH_MARK_PCREL: ++ return ELF::R_LARCH_MARK_PCREL; ++ case LoongArch::fixup_LARCH_SOP_PUSH_PCREL: ++ return ELF::R_LARCH_SOP_PUSH_PCREL; ++ case LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE: ++ return ELF::R_LARCH_SOP_PUSH_ABSOLUTE; ++ case LoongArch::fixup_LARCH_SOP_PUSH_DUP: ++ return ELF::R_LARCH_SOP_PUSH_DUP; ++ case LoongArch::fixup_LARCH_SOP_PUSH_GPREL: ++ return ELF::R_LARCH_SOP_PUSH_GPREL; ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL: ++ return ELF::R_LARCH_SOP_PUSH_TLS_TPREL; ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT: ++ return ELF::R_LARCH_SOP_PUSH_TLS_GOT; ++ case LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD: ++ return ELF::R_LARCH_SOP_PUSH_TLS_GD; ++ case LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL: ++ return ELF::R_LARCH_SOP_PUSH_PLT_PCREL; ++ case LoongArch::fixup_LARCH_SOP_ASSERT: ++ return ELF::R_LARCH_SOP_ASSERT; ++ case LoongArch::fixup_LARCH_SOP_NOT: ++ return ELF::R_LARCH_SOP_NOT; ++ case LoongArch::fixup_LARCH_SOP_SUB: ++ return ELF::R_LARCH_SOP_SUB; ++ case LoongArch::fixup_LARCH_SOP_SL: ++ return ELF::R_LARCH_SOP_SL; ++ case LoongArch::fixup_LARCH_SOP_SR: ++ return ELF::R_LARCH_SOP_SR; ++ case LoongArch::fixup_LARCH_SOP_ADD: ++ return ELF::R_LARCH_SOP_ADD; ++ case LoongArch::fixup_LARCH_SOP_AND: ++ return ELF::R_LARCH_SOP_AND; ++ case LoongArch::fixup_LARCH_SOP_IF_ELSE: ++ return ELF::R_LARCH_SOP_IF_ELSE; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_5: ++ return ELF::R_LARCH_SOP_POP_32_S_10_5; ++ case LoongArch::fixup_LARCH_SOP_POP_32_U_10_12: ++ return ELF::R_LARCH_SOP_POP_32_U_10_12; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_12: ++ return ELF::R_LARCH_SOP_POP_32_S_10_12; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16: ++ return ELF::R_LARCH_SOP_POP_32_S_10_16; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2: ++ return ELF::R_LARCH_SOP_POP_32_S_10_16_S2; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_5_20: ++ return ELF::R_LARCH_SOP_POP_32_S_5_20; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ return ELF::R_LARCH_SOP_POP_32_S_0_5_10_16_S2; ++ case LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ return ELF::R_LARCH_SOP_POP_32_S_0_10_10_16_S2; ++ case LoongArch::fixup_LARCH_SOP_POP_32_U: ++ return ELF::R_LARCH_SOP_POP_32_U; ++ case LoongArch::fixup_LARCH_ADD8: ++ return ELF::R_LARCH_ADD8; ++ case LoongArch::fixup_LARCH_ADD16: ++ return ELF::R_LARCH_ADD16; ++ case LoongArch::fixup_LARCH_ADD24: ++ return ELF::R_LARCH_ADD24; ++ case LoongArch::fixup_LARCH_ADD32: ++ return ELF::R_LARCH_ADD32; ++ case LoongArch::fixup_LARCH_ADD64: ++ return ELF::R_LARCH_ADD64; ++ case LoongArch::fixup_LARCH_SUB8: ++ return ELF::R_LARCH_SUB8; ++ case LoongArch::fixup_LARCH_SUB16: ++ return ELF::R_LARCH_SUB16; ++ case LoongArch::fixup_LARCH_SUB24: ++ return ELF::R_LARCH_SUB24; ++ case LoongArch::fixup_LARCH_SUB32: ++ return ELF::R_LARCH_SUB32; ++ case LoongArch::fixup_LARCH_SUB64: ++ return ELF::R_LARCH_SUB64; ++ case LoongArch::fixup_LARCH_GNU_VTINHERIT: ++ return ELF::R_LARCH_GNU_VTINHERIT; ++ case LoongArch::fixup_LARCH_GNU_VTENTRY: ++ return ELF::R_LARCH_GNU_VTENTRY; + } + } + + std::unique_ptr +-llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { +- return std::make_unique(OSABI, Is64Bit); ++llvm::createLoongArchELFObjectWriter(const Triple &TT, bool IsLPX32) { ++ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); ++ bool IsLP64 = TT.isArch64Bit() && !IsLPX32; ++ bool HasRelocationAddend = TT.isArch64Bit(); ++ return std::make_unique(OSABI, HasRelocationAddend, ++ IsLP64); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp +new file mode 100644 +index 000000000..a74fee3f8 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp +@@ -0,0 +1,138 @@ ++//===-------- LoongArchELFStreamer.cpp - ELF Object Output ---------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchELFStreamer.h" ++#include "LoongArchFixupKinds.h" ++#include "LoongArchTargetStreamer.h" ++#include "llvm/BinaryFormat/ELF.h" ++#include "llvm/MC/MCAsmBackend.h" ++#include "llvm/MC/MCAssembler.h" ++#include "llvm/MC/MCCodeEmitter.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCDwarf.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCObjectWriter.h" ++#include "llvm/MC/MCSymbolELF.h" ++#include "llvm/MC/MCValue.h" ++#include "llvm/Support/Casting.h" ++ ++using namespace llvm; ++ ++static std::pair getRelocPairForSize(unsigned Size) { ++ switch (Size) { ++ default: ++ llvm_unreachable("unsupported fixup size"); ++ case 1: ++ return std::make_pair(LoongArch::fixup_LARCH_ADD8, ++ LoongArch::fixup_LARCH_SUB8); ++ case 2: ++ return std::make_pair(LoongArch::fixup_LARCH_ADD16, ++ LoongArch::fixup_LARCH_SUB16); ++ case 4: ++ return std::make_pair(LoongArch::fixup_LARCH_ADD32, ++ LoongArch::fixup_LARCH_SUB32); ++ case 8: ++ return std::make_pair(LoongArch::fixup_LARCH_ADD64, ++ LoongArch::fixup_LARCH_SUB64); ++ } ++} ++ ++static bool requiresFixups(MCContext &C, const MCExpr *Value, ++ const MCExpr *&LHS, const MCExpr *&RHS, ++ LoongArchELFStreamer *MCS) { ++ const auto *MBE = dyn_cast(Value); ++ if (MBE == nullptr) ++ return false; ++ ++ MCValue E; ++ if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) ++ return false; ++ if (E.getSymA() == nullptr || E.getSymB() == nullptr) ++ return false; ++ ++ const auto &A = E.getSymA()->getSymbol(); ++ const auto &B = E.getSymB()->getSymbol(); ++ ++ if (A.getName().empty() && B.getName().empty()) ++ return false; ++ ++ if (!A.isInSection() && !B.isInSection() && ++ !A.getName().empty() && !B.getName().empty()) ++ return false; ++ ++ LHS = ++ MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), ++ MCConstantExpr::create(E.getConstant(), C), C); ++ RHS = E.getSymB(); ++ ++ bool isCheckInstr = ++ StringSwitch(MCS->getCurrentSectionOnly()->getName()) ++ .Case(".debug_aranges", true) ++ .Default(false); ++ ++ return (A.isInSection() ++ ? (isCheckInstr ? A.getSection().hasInstructions() : true) ++ : !A.getName().empty()) || ++ (B.isInSection() ? B.getSection().hasInstructions() ++ : !B.getName().empty()); ++} ++ ++LoongArchELFStreamer::LoongArchELFStreamer(MCContext &Context, ++ std::unique_ptr MAB, ++ std::unique_ptr OW, ++ std::unique_ptr Emitter) ++ : MCELFStreamer(Context, std::move(MAB), std::move(OW), ++ std::move(Emitter)) { ++ } ++ ++void LoongArchELFStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { ++ Frame.Begin = getContext().createTempSymbol(); ++ MCELFStreamer::emitLabel(Frame.Begin); ++} ++ ++MCSymbol *LoongArchELFStreamer::emitCFILabel() { ++ MCSymbol *Label = getContext().createTempSymbol("cfi", true); ++ MCELFStreamer::emitLabel(Label); ++ return Label; ++} ++ ++void LoongArchELFStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { ++ Frame.End = getContext().createTempSymbol(); ++ MCELFStreamer::emitLabel(Frame.End); ++} ++ ++void LoongArchELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, ++ SMLoc Loc) { ++ const MCExpr *A, *B; ++ if (!requiresFixups(getContext(), Value, A, B, this)) ++ return MCELFStreamer::emitValueImpl(Value, Size, Loc); ++ ++ MCStreamer::emitValueImpl(Value, Size, Loc); ++ ++ MCDataFragment *DF = getOrCreateDataFragment(); ++ flushPendingLabels(DF, DF->getContents().size()); ++ MCDwarfLineEntry::make(this, getCurrentSectionOnly()); ++ ++ unsigned Add, Sub; ++ std::tie(Add, Sub) = getRelocPairForSize(Size); ++ ++ DF->getFixups().push_back(MCFixup::create( ++ DF->getContents().size(), A, static_cast(Add), Loc)); ++ DF->getFixups().push_back(MCFixup::create( ++ DF->getContents().size(), B, static_cast(Sub), Loc)); ++ ++ DF->getContents().resize(DF->getContents().size() + Size, 0); ++} ++ ++MCELFStreamer *llvm::createLoongArchELFStreamer( ++ MCContext &Context, std::unique_ptr MAB, ++ std::unique_ptr OW, std::unique_ptr Emitter, ++ bool RelaxAll) { ++ return new LoongArchELFStreamer(Context, std::move(MAB), std::move(OW), ++ std::move(Emitter)); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h +new file mode 100644 +index 000000000..875cebcb7 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h +@@ -0,0 +1,53 @@ ++//===- LoongArchELFStreamer.h - ELF Object Output --------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This is a custom MCELFStreamer which allows us to insert some hooks before ++// emitting data into an actual object file. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H ++#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H ++ ++#include "llvm/ADT/SmallVector.h" ++#include "llvm/MC/MCELFStreamer.h" ++#include ++ ++namespace llvm { ++ ++class MCAsmBackend; ++class MCCodeEmitter; ++class MCContext; ++class MCSubtargetInfo; ++struct MCDwarfFrameInfo; ++ ++class LoongArchELFStreamer : public MCELFStreamer { ++ ++public: ++ LoongArchELFStreamer(MCContext &Context, std::unique_ptr MAB, ++ std::unique_ptr OW, ++ std::unique_ptr Emitter); ++ ++ /// Overriding these functions allows us to dismiss all labels. ++ void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; ++ ++ // Overriding these functions allows us to avoid recording of these labels ++ // in emitLabel. ++ void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; ++ void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; ++ MCSymbol *emitCFILabel() override; ++}; ++ ++MCELFStreamer *createLoongArchELFStreamer(MCContext &Context, ++ std::unique_ptr MAB, ++ std::unique_ptr OW, ++ std::unique_ptr Emitter, ++ bool RelaxAll); ++} // end namespace llvm ++ ++#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHELFSTREAMER_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +new file mode 100644 +index 000000000..e0e1200d8 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +@@ -0,0 +1,90 @@ ++//===-- LoongArchFixupKinds.h - LoongArch Specific Fixup Entries ----------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H ++#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H ++ ++#include "llvm/MC/MCFixup.h" ++ ++namespace llvm { ++namespace LoongArch { ++ // Although most of the current fixup types reflect a unique relocation ++ // one can have multiple fixup types for a given relocation and thus need ++ // to be uniquely named. ++ // ++ // This table *must* be in the same order of ++ // MCFixupKindInfo Infos[LoongArch::NumTargetFixupKinds] ++ // in LoongArchAsmBackend.cpp. ++ // ++ enum Fixups { ++ // R_LARCH_NONE. ++ fixup_LARCH_NONE = FirstTargetFixupKind, ++ ++ // reloc_hint ++ fixup_LARCH_SOP_PUSH_ABSOLUTE, ++ fixup_LARCH_SOP_PUSH_PCREL, ++ fixup_LARCH_SOP_PUSH_GPREL, ++ fixup_LARCH_SOP_PUSH_TLS_TPREL, ++ fixup_LARCH_SOP_PUSH_TLS_GOT, ++ fixup_LARCH_SOP_PUSH_TLS_GD, ++ fixup_LARCH_SOP_PUSH_PLT_PCREL, ++ // fixup methods ++ fixup_LARCH_32, ++ fixup_LARCH_64, ++ fixup_LARCH_RELATIVE, ++ fixup_LARCH_COPY, ++ fixup_LARCH_JUMP_SLOT, ++ fixup_LARCH_TLS_DTPMOD32, ++ fixup_LARCH_TLS_DTPMOD64, ++ fixup_LARCH_TLS_DTPREL32, ++ fixup_LARCH_TLS_DTPREL64, ++ fixup_LARCH_TLS_TPREL32, ++ fixup_LARCH_TLS_TPREL64, ++ fixup_LARCH_IRELATIVE, ++ fixup_LARCH_MARK_LA, ++ fixup_LARCH_MARK_PCREL, ++ fixup_LARCH_SOP_PUSH_DUP, ++ fixup_LARCH_SOP_ASSERT, ++ fixup_LARCH_SOP_NOT, ++ fixup_LARCH_SOP_SUB, ++ fixup_LARCH_SOP_SL, ++ fixup_LARCH_SOP_SR, ++ fixup_LARCH_SOP_ADD, ++ fixup_LARCH_SOP_AND, ++ fixup_LARCH_SOP_IF_ELSE, ++ fixup_LARCH_SOP_POP_32_S_10_5, ++ fixup_LARCH_SOP_POP_32_U_10_12, ++ fixup_LARCH_SOP_POP_32_S_10_12, ++ fixup_LARCH_SOP_POP_32_S_10_16, ++ fixup_LARCH_SOP_POP_32_S_10_16_S2, ++ fixup_LARCH_SOP_POP_32_S_5_20, ++ fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2, ++ fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2, ++ fixup_LARCH_SOP_POP_32_U, ++ fixup_LARCH_ADD8, ++ fixup_LARCH_ADD16, ++ fixup_LARCH_ADD24, ++ fixup_LARCH_ADD32, ++ fixup_LARCH_ADD64, ++ fixup_LARCH_SUB8, ++ fixup_LARCH_SUB16, ++ fixup_LARCH_SUB24, ++ fixup_LARCH_SUB32, ++ fixup_LARCH_SUB64, ++ fixup_LARCH_GNU_VTINHERIT, ++ fixup_LARCH_GNU_VTENTRY, ++ ++ // Marker ++ LastTargetFixupKind, ++ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind ++ }; ++} // namespace LoongArch ++} // namespace llvm ++ ++ ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp +index 66183868f..065020ad4 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp +@@ -1,4 +1,4 @@ +-//===- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to asm syntax --===// ++//===-- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to assembly syntax ------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,53 +11,242 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchInstPrinter.h" +-#include "LoongArchBaseInfo.h" +-#include "llvm/MC/MCAsmInfo.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" ++#include "LoongArchInstrInfo.h" ++#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#include "llvm/ADT/StringExtras.h" ++#include "llvm/MC/MCExpr.h" + #include "llvm/MC/MCInst.h" +-#include "llvm/MC/MCRegisterInfo.h" +-#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCInstrInfo.h" + #include "llvm/MC/MCSymbol.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/raw_ostream.h" + using namespace llvm; + +-#define DEBUG_TYPE "loongarch-asm-printer" ++#define DEBUG_TYPE "asm-printer" + +-// Include the auto-generated portion of the assembly writer. + #define PRINT_ALIAS_INSTR + #include "LoongArchGenAsmWriter.inc" + ++template ++static bool isReg(const MCInst &MI, unsigned OpNo) { ++ assert(MI.getOperand(OpNo).isReg() && "Register operand expected."); ++ return MI.getOperand(OpNo).getReg() == R; ++} ++ ++const char* LoongArch::LoongArchFCCToString(LoongArch::CondCode CC) { ++ switch (CC) { ++ case FCOND_T: ++ case FCOND_F: return "caf"; ++ case FCOND_OR: ++ case FCOND_UN: return "cun"; ++ case FCOND_UNE: ++ case FCOND_OEQ: return "ceq"; ++ case FCOND_ONE: ++ case FCOND_UEQ: return "cueq"; ++ case FCOND_UGE: ++ case FCOND_OLT: return "clt"; ++ case FCOND_OGE: ++ case FCOND_ULT: return "cult"; ++ case FCOND_UGT: ++ case FCOND_OLE: return "cle"; ++ case FCOND_OGT: ++ case FCOND_ULE: return "cule"; ++ case FCOND_ST: ++ case FCOND_SF: return "saf"; ++ case FCOND_GLE: ++ case FCOND_NGLE:return "sun"; ++ case FCOND_SEQ: return "seq"; ++ case FCOND_SNE: return "sne"; ++ case FCOND_GL: ++ case FCOND_NGL: return "sueq"; ++ case FCOND_NLT: ++ case FCOND_LT: return "slt"; ++ case FCOND_GE: ++ case FCOND_NGE: return "sult"; ++ case FCOND_NLE: ++ case FCOND_LE: return "sle"; ++ case FCOND_GT: ++ case FCOND_NGT: return "sule"; ++ case FCOND_CNE: return "cne"; ++ case FCOND_COR: return "cor"; ++ case FCOND_SOR: return "sor"; ++ case FCOND_CUNE: return "cune"; ++ case FCOND_SUNE: return "sune"; ++ } ++ llvm_unreachable("Impossible condition code!"); ++} ++ ++void LoongArchInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { ++ OS << '$' << StringRef(getRegisterName(RegNo)).lower(); ++} ++ + void LoongArchInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, + const MCSubtargetInfo &STI, + raw_ostream &O) { +- if (!printAliasInstr(MI, Address, STI, O)) +- printInstruction(MI, Address, STI, O); +- printAnnotation(O, Annot); +-} ++ switch (MI->getOpcode()) { ++ default: ++ break; ++ case LoongArch::PCADDU12I_ri: ++ case LoongArch::PCADDU12I_rii: ++ case LoongArch::LU12I_W_ri: ++ printLoadAddr(MI, O); ++ return; ++ case LoongArch::ADD_D_rrr: ++ case LoongArch::LDX_D_rrr: ++ case LoongArch::ADDI_D_rri: ++ case LoongArch::ADDI_D_rrii: ++ case LoongArch::LD_D_rri: ++ case LoongArch::LD_D_rrii: ++ case LoongArch::ORI_rri: ++ case LoongArch::ORI_rrii: ++ case LoongArch::LU32I_D_ri: ++ case LoongArch::LU32I_D_rii: ++ case LoongArch::LU52I_D_rri: ++ case LoongArch::LU52I_D_rrii: ++ O << "\t# la expanded slot"; ++ return; ++ } + +-void LoongArchInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { +- O << '$' << getRegisterName(RegNo); ++ // Try to print any aliases first. ++ if (!printAliasInstr(MI, Address, O) && !printAlias(*MI, O)) ++ printInstruction(MI, Address, O); ++ printAnnotation(O, Annot); + } + + void LoongArchInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, +- const MCSubtargetInfo &STI, +- raw_ostream &O) { +- const MCOperand &MO = MI->getOperand(OpNo); ++ raw_ostream &O) { ++ const MCOperand &Op = MI->getOperand(OpNo); ++ if (Op.isReg()) { ++ printRegName(O, Op.getReg()); ++ return; ++ } + +- if (MO.isReg()) { +- printRegName(O, MO.getReg()); ++ if (Op.isImm()) { ++ O << formatImm(Op.getImm()); + return; + } + ++ assert(Op.isExpr() && "unknown operand kind in printOperand"); ++ Op.getExpr()->print(O, &MAI, true); ++} ++ ++template ++void LoongArchInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) { ++ const MCOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) { +- O << MO.getImm(); ++ uint64_t Imm = MO.getImm(); ++ Imm -= Offset; ++ Imm &= (1 << Bits) - 1; ++ Imm += Offset; ++ O << formatImm(Imm); + return; + } + +- assert(MO.isExpr() && "Unknown operand kind in printOperand"); +- MO.getExpr()->print(O, &MAI); ++ printOperand(MI, opNum, O); ++} ++ ++void LoongArchInstPrinter:: ++printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { ++ // Load/Store memory operands -- $reg, imm ++ printOperand(MI, opNum, O); ++ O << ", "; ++ printOperand(MI, opNum+1, O); ++} ++ ++void LoongArchInstPrinter::printAMemOperand(const MCInst *MI, int opNum, ++ raw_ostream &O) { ++ // AM* instruction memory operand: "rj, 0" ++ printRegName(O, MI->getOperand(opNum).getReg()); ++ O << ", 0"; ++} ++ ++void LoongArchInstPrinter:: ++printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { ++ // when using stack locations for not load/store instructions ++ // print the same way as all normal 3 operand instructions. ++ printOperand(MI, opNum, O); ++ O << ", "; ++ printOperand(MI, opNum+1, O); ++} ++ ++void LoongArchInstPrinter:: ++printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { ++ const MCOperand& MO = MI->getOperand(opNum); ++ O << LoongArchFCCToString((LoongArch::CondCode)MO.getImm()); ++} ++ ++bool LoongArchInstPrinter::printAlias(const char *Str, const MCInst &MI, ++ unsigned OpNo, raw_ostream &OS) { ++ OS << "\t" << Str << "\t"; ++ if(MI.getOpcode() == LoongArch::JIRL) { ++ printOperand(&MI, OpNo, OS); ++ OS << "@plt"; ++ }else ++ printOperand(&MI, OpNo, OS); ++ return true; ++} ++ ++bool LoongArchInstPrinter::printAlias(const char *Str, const MCInst &MI, ++ unsigned OpNo0, unsigned OpNo1, ++ raw_ostream &OS) { ++ printAlias(Str, MI, OpNo0, OS); ++ OS << ", "; ++ printOperand(&MI, OpNo1, OS); ++ return true; ++} ++ ++bool LoongArchInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { ++ switch (MI.getOpcode()) { ++ case LoongArch::OR: ++ // or $r0, $r1, $zero => move $r0, $r1 ++ return isReg(MI, 2) && printAlias("move", MI, 0, 1, OS); ++ default: return false; ++ } ++} ++ ++void LoongArchInstPrinter:: ++printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) { ++ // - 2 because register List is always first operand of instruction and it is ++ // always followed by memory operand (base + offset). ++ for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) { ++ if (i != opNum) ++ O << ", "; ++ printRegName(O, MI->getOperand(i).getReg()); ++ } + } + +-const char *LoongArchInstPrinter::getRegisterName(unsigned RegNo) { +- // Default print reg alias name +- return getRegisterName(RegNo, LoongArch::RegAliasName); ++void LoongArchInstPrinter:: ++printLoadAddr(const MCInst *MI, raw_ostream &O) { ++ const MCOperand &Op = MI->getOperand(1); ++ const MCExpr *Expr = Op.getExpr(); ++ const LoongArchMCExpr *LoongArchExpr = cast(Expr); ++ switch (LoongArchExpr->getKind()) { ++ default: ++ llvm_unreachable("invalid handled!"); ++ return; ++ case LoongArchMCExpr::MEK_ABS_HI: ++ O << "\tla.abs\t"; ++ break; ++ case LoongArchMCExpr::MEK_GOT_HI: ++ O << "\tla.got\t"; ++ break; ++ case LoongArchMCExpr::MEK_PCREL_HI: ++ O << "\tla.pcrel\t"; ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_HI: ++ O << "\tla.tls.gd\t"; ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_HI: ++ O << "\tla.tls.ie\t"; ++ break; ++ case LoongArchMCExpr::MEK_TLSLE_HI: ++ O << "\tla.tls.le\t"; ++ break; ++ } ++ printRegName(O, MI->getOperand(0).getReg()); ++ O << ", "; ++ Expr->print(O, nullptr); ++ return; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h +index 0cbb3d73c..050dcc137 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h +@@ -1,4 +1,4 @@ +-//===-- LoongArchInstPrinter.h - Convert LoongArch MCInst to asm syntax ---===// ++//=== LoongArchInstPrinter.h - Convert LoongArch MCInst to assembly syntax -*- C++ -*-==// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -10,40 +10,110 @@ + // + //===----------------------------------------------------------------------===// + +-#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H +-#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H +- +-#include "MCTargetDesc/LoongArchMCTargetDesc.h" ++#ifndef LLVM_LIB_TARGET_LOONGARCH_INSTPRINTER_LOONGARCHINSTPRINTER_H ++#define LLVM_LIB_TARGET_LOONGARCH_INSTPRINTER_LOONGARCHINSTPRINTER_H + #include "llvm/MC/MCInstPrinter.h" + + namespace llvm { + ++namespace LoongArch { ++// LoongArch Branch Codes ++enum FPBranchCode { ++ BRANCH_F, ++ BRANCH_T, ++ BRANCH_INVALID ++}; ++ ++// LoongArch Condition Codes ++enum CondCode { ++ FCOND_F = 0x0, ++ FCOND_SF, ++ FCOND_OLT, ++ FCOND_LT, ++ FCOND_OEQ, ++ FCOND_SEQ, ++ FCOND_OLE, ++ FCOND_LE, ++ FCOND_UN, ++ FCOND_NGLE, ++ FCOND_ULT, ++ FCOND_NGE, ++ FCOND_UEQ, ++ FCOND_NGL, ++ FCOND_ULE, ++ FCOND_NGT, ++ FCOND_CNE, ++ FCOND_SNE, ++ FCOND_COR = 0x14, ++ FCOND_SOR = 0x15, ++ FCOND_CUNE = 0x18, ++ FCOND_SUNE = 0x19, ++ ++ // To be used with float branch False ++ // This conditions have the same mnemonic as the ++ // above ones, but are used with a branch False; ++ FCOND_T, ++ FCOND_UNE, ++ FCOND_ST, ++ FCOND_UGE, ++ FCOND_NLT, ++ FCOND_UGT, ++ FCOND_NLE, ++ FCOND_OR, ++ FCOND_GLE, ++ FCOND_OGE, ++ FCOND_GE, ++ FCOND_ONE, ++ FCOND_GL, ++ FCOND_OGT, ++ FCOND_GT ++}; ++ ++const char *LoongArchFCCToString(LoongArch::CondCode CC); ++} // end namespace LoongArch ++ + class LoongArchInstPrinter : public MCInstPrinter { + public: + LoongArchInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, +- const MCRegisterInfo &MRI) +- : MCInstPrinter(MAI, MII, MRI) {} ++ const MCRegisterInfo &MRI) ++ : MCInstPrinter(MAI, MII, MRI) {} + ++ // Autogenerated by tblgen. ++ std::pair getMnemonic(const MCInst *MI) override; ++ void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O); ++ static const char *getRegisterName(unsigned RegNo); ++ ++ void printRegName(raw_ostream &OS, unsigned RegNo) const override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &O) override; +- void printRegName(raw_ostream &O, unsigned RegNo) const override; + +- // Autogenerated by tblgen. +- std::pair getMnemonic(const MCInst *MI) override; +- void printInstruction(const MCInst *MI, uint64_t Address, +- const MCSubtargetInfo &STI, raw_ostream &O); +- bool printAliasInstr(const MCInst *MI, uint64_t Address, +- const MCSubtargetInfo &STI, raw_ostream &O); ++ bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS); + void printCustomAliasOperand(const MCInst *MI, uint64_t Address, + unsigned OpIdx, unsigned PrintMethodIdx, +- const MCSubtargetInfo &STI, raw_ostream &O); +- static const char *getRegisterName(unsigned RegNo); +- static const char *getRegisterName(unsigned RegNo, unsigned AltIdx); ++ raw_ostream &O); + + private: +- void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, +- raw_ostream &O); ++ void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); ++ void printOperand(const MCInst *MI, uint64_t /*Address*/, unsigned OpNum, ++ raw_ostream &O) { ++ printOperand(MI, OpNum, O); ++ } ++ template ++ void printUImm(const MCInst *MI, int opNum, raw_ostream &O); ++ void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); ++ void printAMemOperand(const MCInst *MI, int opNum, raw_ostream &O); ++ void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); ++ void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); ++ ++ bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, ++ raw_ostream &OS); ++ bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo0, ++ unsigned OpNo1, raw_ostream &OS); ++ bool printAlias(const MCInst &MI, raw_ostream &OS); ++ void printSaveRestore(const MCInst *MI, raw_ostream &O); ++ void printRegisterList(const MCInst *MI, int opNum, raw_ostream &O); ++ void printLoadAddr(const MCInst *MI, raw_ostream &O); + }; + } // end namespace llvm + +-#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp +index bc946db2f..b3091a107 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm properties ------*- C++ -*--===// ++//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm Properties ---------------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -12,23 +12,28 @@ + + #include "LoongArchMCAsmInfo.h" + #include "llvm/ADT/Triple.h" +-#include "llvm/BinaryFormat/Dwarf.h" +-#include "llvm/MC/MCStreamer.h" + + using namespace llvm; + +-void LoongArchMCAsmInfo::anchor() {} ++void LoongArchMCAsmInfo::anchor() { } + +-LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) { +- CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; +- AlignmentIsInBytes = false; +- Data8bitsDirective = "\t.byte\t"; +- Data16bitsDirective = "\t.half\t"; +- Data32bitsDirective = "\t.word\t"; +- Data64bitsDirective = "\t.dword\t"; +- ZeroDirective = "\t.space\t"; +- CommentString = "#"; ++LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TheTriple, ++ const MCTargetOptions &Options) { ++ ++ if (TheTriple.isLoongArch64() ++ && TheTriple.getEnvironment() != Triple::GNUABILPX32) ++ CodePointerSize = CalleeSaveStackSlotSize = 8; ++ ++ AlignmentIsInBytes = false; ++ Data16bitsDirective = "\t.half\t"; ++ Data32bitsDirective = "\t.word\t"; ++ Data64bitsDirective = "\t.dword\t"; ++ CommentString = "#"; ++ ZeroDirective = "\t.space\t"; + SupportsDebugInformation = true; +- DwarfRegNumForCFI = true; + ExceptionsType = ExceptionHandling::DwarfCFI; ++ DwarfRegNumForCFI = true; ++ //HasLoongArchExpressions = true; ++ UseIntegratedAssembler = true; ++ UsesELFSectionDirectiveForBSS = true; + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h +index ed1abbf46..244db58db 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h +@@ -1,4 +1,4 @@ +-//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info --------------*- C++ -*--===// ++//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info ------------------------*- C++ -*--===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -22,9 +22,10 @@ class LoongArchMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + + public: +- explicit LoongArchMCAsmInfo(const Triple &TargetTriple); ++ explicit LoongArchMCAsmInfo(const Triple &TheTriple, ++ const MCTargetOptions &Options); + }; + +-} // end namespace llvm ++} // namespace llvm + +-#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +index 01a370a90..df4e72e90 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +@@ -1,4 +1,4 @@ +-//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// ++//===-- LoongArchMCCodeEmitter.cpp - Convert LoongArch Code to Machine Code ---------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -10,118 +10,1422 @@ + // + //===----------------------------------------------------------------------===// + +-#include "MCTargetDesc/LoongArchBaseInfo.h" ++#include "LoongArchMCCodeEmitter.h" ++#include "MCTargetDesc/LoongArchFixupKinds.h" ++#include "MCTargetDesc/LoongArchMCExpr.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" +-#include "llvm/MC/MCCodeEmitter.h" ++#include "MCTargetDesc/LoongArchInstPrinter.h" ++#include "llvm/ADT/APFloat.h" ++#include "llvm/ADT/APInt.h" ++#include "llvm/ADT/SmallVector.h" + #include "llvm/MC/MCContext.h" +-#include "llvm/MC/MCInstBuilder.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCFixup.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCInstrDesc.h" + #include "llvm/MC/MCInstrInfo.h" + #include "llvm/MC/MCRegisterInfo.h" +-#include "llvm/Support/EndianStream.h" ++#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/raw_ostream.h" ++#include ++#include + + using namespace llvm; + + #define DEBUG_TYPE "mccodeemitter" + +-namespace { +-class LoongArchMCCodeEmitter : public MCCodeEmitter { +- LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; +- void operator=(const LoongArchMCCodeEmitter &) = delete; +- MCContext &Ctx; +- MCInstrInfo const &MCII; +- +-public: +- LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) +- : Ctx(ctx), MCII(MCII) {} +- +- ~LoongArchMCCodeEmitter() override {} +- +- void encodeInstruction(const MCInst &MI, raw_ostream &OS, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const override; +- +- /// TableGen'erated function for getting the binary encoding for an +- /// instruction. +- uint64_t getBinaryCodeForInstr(const MCInst &MI, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const; +- +- /// Return binary encoding of operand. If the machine operand requires +- /// relocation, record the relocation and return zero. +- unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const; +- +- /// Return binary encoding of an immediate operand specified by OpNo. +- /// The value returned is the value of the immediate minus 1. +- /// Note that this function is dedicated to specific immediate types, +- /// e.g. uimm2_plus1. +- unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const; +- +- /// Return binary encoding of an immediate operand specified by OpNo. +- /// The value returned is the value of the immediate shifted right +- // arithmetically by 2. +- /// Note that this function is dedicated to specific immediate types, +- /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. +- unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const; +-}; +-} // end namespace ++#define GET_INSTRMAP_INFO ++#include "LoongArchGenInstrInfo.inc" ++#undef GET_INSTRMAP_INFO + +-unsigned +-LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const { ++namespace llvm { + +- if (MO.isReg()) +- return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); ++MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, ++ MCContext &Ctx) { ++ return new LoongArchMCCodeEmitter(MCII, Ctx); ++} + +- if (MO.isImm()) +- return static_cast(MO.getImm()); ++} // end namespace llvm + +- llvm_unreachable("Unhandled expression!"); ++void LoongArchMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { ++ OS << (char)C; + } + +-unsigned +-LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const { +- return MI.getOperand(OpNo).getImm() - 1; ++void LoongArchMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, ++ const MCSubtargetInfo &STI, ++ raw_ostream &OS) const { ++ for (unsigned i = 0; i < Size; ++i) { ++ unsigned Shift = i * 8; ++ EmitByte((Val >> Shift) & 0xff, OS); ++ } + } + +-unsigned +-LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, +- SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const { +- unsigned Res = MI.getOperand(OpNo).getImm(); +- assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); +- return Res >> 2; +-} +- +-void LoongArchMCCodeEmitter::encodeInstruction( +- const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, +- const MCSubtargetInfo &STI) const { +- const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); +- // Get byte count of instruction. ++/// encodeInstruction - Emit the instruction. ++/// Size the instruction with Desc.getSize(). ++void LoongArchMCCodeEmitter:: ++encodeInstruction(const MCInst &MI, raw_ostream &OS, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const ++{ ++ MCInst TmpInst = MI; ++ ++ uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); ++ ++ const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); ++ ++ // Get byte count of instruction + unsigned Size = Desc.getSize(); ++ if (!Size) ++ llvm_unreachable("Desc.getSize() returns 0"); ++ ++ EmitInstruction(Binary, Size, STI, OS); ++} ++ ++/// getBranchTargetOpValue - Return binary encoding of the branch ++/// target operand. If the machine operand requires relocation, ++/// record the relocation and return zero. ++unsigned LoongArchMCCodeEmitter:: ++getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); + +- switch (Size) { ++ // If the destination is an immediate, divide by 4. ++ if (MO.isImm()) return MO.getImm() >> 2; ++ ++ assert(MO.isExpr() && ++ "getBranchTargetOpValue expects only expressions or immediates"); ++ ++ // XXX: brtarget reloc EncoderMethod. ++ const MCExpr *Expr = MO.getExpr(); ++ int64_t Value = 0x0; ++ const MCConstantExpr *tmpExpr = MCConstantExpr::create(Value, Ctx); ++ Fixups.push_back(MCFixup::create(0, Expr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_PCREL))); ++ switch (MI.getOpcode()) { + default: +- llvm_unreachable("Unhandled encodeInstruction length!"); +- case 4: { +- uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); +- support::endian::write(OS, Bits, support::little); ++ llvm_unreachable("Unhandled reloc instruction!"); ++ break; ++ case LoongArch::BEQZ: ++ case LoongArch::BEQZ32: ++ case LoongArch::BNEZ: ++ case LoongArch::BNEZ32: ++ case LoongArch::BCEQZ: ++ case LoongArch::BCNEZ: ++ Fixups.push_back(MCFixup::create(0, tmpExpr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_5_10_16_S2))); + break; ++ case LoongArch::BEQ: ++ case LoongArch::BEQ32: ++ case LoongArch::BNE: ++ case LoongArch::BNE32: ++ case LoongArch::BLT: ++ case LoongArch::BLT32: ++ case LoongArch::BGE: ++ case LoongArch::BGE32: ++ case LoongArch::BLTU: ++ case LoongArch::BLTU32: ++ case LoongArch::BGEU: ++ case LoongArch::BGEU32: ++ Fixups.push_back(MCFixup::create(0, tmpExpr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); ++ break; ++ } ++ return 0; ++} ++ ++/// getJumpTargetOpValue - Return binary encoding of the jump ++/// target operand. If the machine operand requires relocation, ++/// record the relocation and return zero. ++unsigned LoongArchMCCodeEmitter:: ++getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ // If the destination is an immediate, divide by 4. ++ if (MO.isImm()) return MO.getImm()>>2; ++ ++ assert(MO.isExpr() && ++ "getJumpTargetOpValue expects only expressions or an immediate"); ++ ++ const MCExpr *Expr = MO.getExpr(); ++ int64_t Value = 0x0; ++ const MCConstantExpr *tmpExpr = MCConstantExpr::create(Value, Ctx); ++ Fixups.push_back(MCFixup::create(0, Expr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL))); ++ if (MI.getOpcode() == LoongArch::JIRL) ++ Fixups.push_back(MCFixup::create(0, tmpExpr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); ++ else // B or BL ++ Fixups.push_back(MCFixup::create(0, tmpExpr, ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2))); ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm11Lsl1Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 1; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm10Lsl2Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 2; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm9Lsl3Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 3; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm8Lsl1Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 1; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm8Lsl2Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 2; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getSImm8Lsl3Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isImm()) { ++ unsigned Value = MO.getImm(); ++ return Value >> 3; ++ } ++ ++ return 0; ++} ++ ++unsigned LoongArchMCCodeEmitter:: ++getExprOpValue(const MCInst &MI, const MCExpr *Expr, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ int64_t Res; ++ ++ if (Expr->evaluateAsAbsolute(Res)) ++ return Res; ++ ++ MCExpr::ExprKind Kind = Expr->getKind(); ++ if (Kind == MCExpr::Constant) { ++ return cast(Expr)->getValue(); ++ } ++ ++ if (Kind == MCExpr::Binary) { ++ unsigned Res = getExprOpValue(MI, cast(Expr)->getLHS(), Fixups, STI); ++ Res += getExprOpValue(MI, cast(Expr)->getRHS(), Fixups, STI); ++ return Res; ++ } ++ ++ if (Kind == MCExpr::Target) { ++ int64_t Value = 0x0; ++ const LoongArchMCExpr *LoongArchExpr = cast(Expr); ++ const MCExpr *BinExpr = nullptr; ++ const MCExpr *GOTExpr = nullptr; ++ const MCSymbol *GOTSymbol = Ctx.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); ++ ++ LoongArch::Fixups FixupKind = LoongArch::Fixups(0); ++ switch (LoongArchExpr->getKind()) { ++ case LoongArchMCExpr::MEK_None: ++ case LoongArchMCExpr::MEK_Special: ++ llvm_unreachable("Unhandled fixup kind!"); ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ break; ++ case LoongArchMCExpr::MEK_PLT: ++ Value = 0x0; ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ if (MI.getOpcode() == LoongArch::JIRL) ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); ++ else // B or BL ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_0_10_10_16_S2))); ++ break; ++ case LoongArchMCExpr::MEK_CALL_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ ++ Value = 0x20000; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x12; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ ++ break; ++ case LoongArchMCExpr::MEK_CALL_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PLT_PCREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ ++ Value = 0x4; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x20004; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x12; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x12; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_16_S2))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x800; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x804; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_RRHI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000000; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_RRLO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000004; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_RRHIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x80000008; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_GOT_RRHIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x8000000c; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_GPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_ABS_HI: ++ FixupKind = LoongArch::fixup_LARCH_MARK_LA; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_ABS_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_ABS_HIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_ABS_HIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x800; ++ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x804; ++ BinExpr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_RRHI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000000; ++ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_RRLO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000004; ++ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_RRHIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000008; ++ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_PCREL_RRHIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x8000000c; ++ BinExpr = MCBinaryExpr::createAdd(LoongArchExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x800; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x804; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_RRHI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000000; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_RRLO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000004; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_RRHIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x80000008; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSGD_RRHIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x8000000c; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GD; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x800; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x804; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_RRHI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Fixups.push_back(MCFixup::create(0, GOTExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000000; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_RRLO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x4; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ Value = 0x80000004; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SUB))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_RRHIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x80000008; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSIE_RRHIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_PCREL; ++ GOTExpr = MCSymbolRefExpr::create(GOTSymbol, ++ MCSymbolRefExpr::VK_None, Ctx); ++ Value = 0x8000000c; ++ BinExpr = MCBinaryExpr::createAdd(GOTExpr, MCConstantExpr::create(Value, Ctx), Ctx); ++ Fixups.push_back(MCFixup::create(0, BinExpr, MCFixupKind(FixupKind))); ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_GOT; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_ADD))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSLE_HI: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ ++ Value = 0x20; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSLE_LO: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0xfff; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_AND))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_U_10_12))); ++ break; ++ case LoongArchMCExpr::MEK_TLSLE_HIGHER: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0xc; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SL))); ++ Value = 0x2c; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_5_20))); ++ break; ++ case LoongArchMCExpr::MEK_TLSLE_HIGHEST: ++ FixupKind = LoongArch::fixup_LARCH_SOP_PUSH_TLS_TPREL; ++ Fixups.push_back(MCFixup::create(0, LoongArchExpr, MCFixupKind(FixupKind))); ++ Value = 0x34; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_PUSH_ABSOLUTE))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_SR))); ++ Value = 0x0; ++ Fixups.push_back(MCFixup::create(0, MCConstantExpr::create(Value, Ctx), ++ MCFixupKind(LoongArch::fixup_LARCH_SOP_POP_32_S_10_12))); ++ break; ++ } ++ return 0; + } ++ ++ if (Kind == MCExpr::SymbolRef) { ++ LoongArch::Fixups FixupKind = LoongArch::Fixups(0); ++ ++ switch(cast(Expr)->getKind()) { ++ default: llvm_unreachable("Unknown fixup kind!"); ++ break; ++ } ++ Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); ++ return 0; ++ } ++ return 0; ++} ++ ++/// getMachineOpValue - Return binary encoding of operand. If the machine ++/// operand requires relocation, record the relocation and return zero. ++unsigned LoongArchMCCodeEmitter:: ++getMachineOpValue(const MCInst &MI, const MCOperand &MO, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ if (MO.isReg()) { ++ unsigned Reg = MO.getReg(); ++ unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); ++ return RegNo; ++ } else if (MO.isImm()) { ++ return static_cast(MO.getImm()); ++ } else if (MO.isDFPImm()) { ++ return static_cast(bit_cast(MO.getDFPImm())); + } ++ // MO must be an Expr. ++ assert(MO.isExpr()); ++ return getExprOpValue(MI, MO.getExpr(),Fixups, STI); + } + +-MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, +- MCContext &Ctx) { +- return new LoongArchMCCodeEmitter(Ctx, MCII); ++/// Return binary encoding of memory related operand. ++/// If the offset operand requires relocation, record the relocation. ++template ++unsigned LoongArchMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 12; ++ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); ++ ++ // Apply the scale factor if there is one. ++ OffBits >>= ShiftAmount; ++ ++ return (OffBits & 0xFFF) | RegBits; ++} ++ ++/// Return binary encoding of AM* memory related operand. ++unsigned ++LoongArchMCCodeEmitter::getAMemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 16-12, bits 11-0 are not used. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) ++ << 12; ++ return RegBits; ++} ++ ++unsigned LoongArchMCCodeEmitter::getMemEncoding10l2(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 10; ++ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); ++ ++ // Apply the scale factor if there is one. ++ OffBits >>= 2; ++ ++ return (OffBits & 0x3FF) | RegBits; ++} ++ ++unsigned LoongArchMCCodeEmitter::getMemEncoding11l1(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 11; ++ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); ++ ++ // Apply the scale factor if there is one. ++ OffBits >>= 1; ++ ++ return (OffBits & 0x7FF) | RegBits; ++} ++ ++unsigned LoongArchMCCodeEmitter::getMemEncoding9l3(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 16-12, offset is encoded in bits 11-0. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 9; ++ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); ++ ++ // Apply the scale factor if there is one. ++ OffBits >>= 3; ++ ++ return (OffBits & 0x1FF) | RegBits; ++} ++ ++/// Return binary encoding of simm14 memory related operand. Such as LL/SC instructions. ++/// If the offset operand requires relocation, record the relocation. ++template ++unsigned LoongArchMCCodeEmitter::getSimm14MemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ // Base register is encoded in bits 18-14, offset is encoded in bits 13-0. ++ assert(MI.getOperand(OpNo).isReg()); ++ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 14; ++ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); ++ ++ // Apply the scale factor if there is one. ++ OffBits >>= ShiftAmount; ++ ++ return (OffBits & 0x3FFF) | RegBits; ++} ++ ++unsigned ++LoongArchMCCodeEmitter::getFCMPEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ const MCOperand& MO = MI.getOperand(OpNo); ++ switch((LoongArch::CondCode)MO.getImm()){ ++ case LoongArch::FCOND_T: ++ return 0x0; ++ case LoongArch::FCOND_OR: ++ return 0x8; ++ case LoongArch::FCOND_UNE: ++ return 0x4; ++ case LoongArch::FCOND_ONE: ++ return 0xC; ++ case LoongArch::FCOND_UGE: ++ return 0x2; ++ case LoongArch::FCOND_OGE: ++ return 0xA; ++ case LoongArch::FCOND_UGT: ++ return 0x6; ++ case LoongArch::FCOND_OGT: ++ return 0xE; ++ case LoongArch::FCOND_ST: ++ return 0x1; ++ case LoongArch::FCOND_GLE: ++ return 0x9; ++ case LoongArch::FCOND_GL: ++ return 0xD; ++ case LoongArch::FCOND_NLT: ++ return 0x3; ++ case LoongArch::FCOND_GE: ++ return 0xB; ++ case LoongArch::FCOND_NLE: ++ return 0x7; ++ case LoongArch::FCOND_GT: ++ return 0xF; ++ default: ++ return MO.getImm(); ++ } ++} ++ ++template ++unsigned ++LoongArchMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const { ++ assert(MI.getOperand(OpNo).isImm()); ++ unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); ++ Value -= Offset; ++ return Value; + } + + #include "LoongArchGenMCCodeEmitter.inc" +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h +new file mode 100644 +index 000000000..016340151 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.h +@@ -0,0 +1,146 @@ ++//===- LoongArchMCCodeEmitter.h - Convert LoongArch Code to Machine Code --*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file defines the LoongArchMCCodeEmitter class. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H ++#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H ++ ++#include "llvm/MC/MCCodeEmitter.h" ++#include "llvm/ADT/StringRef.h" ++#include ++#include ++ ++namespace llvm { ++ ++class MCContext; ++class MCExpr; ++class MCFixup; ++class MCInst; ++class MCInstrInfo; ++class MCOperand; ++class MCSubtargetInfo; ++class raw_ostream; ++ ++class LoongArchMCCodeEmitter : public MCCodeEmitter { ++ const MCInstrInfo &MCII; ++ MCContext &Ctx; ++ ++public: ++ LoongArchMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_) ++ : MCII(mcii), Ctx(Ctx_) {} ++ LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; ++ LoongArchMCCodeEmitter &operator=(const LoongArchMCCodeEmitter &) = delete; ++ ~LoongArchMCCodeEmitter() override = default; ++ ++ void EmitByte(unsigned char C, raw_ostream &OS) const; ++ ++ void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, ++ raw_ostream &OS) const; ++ ++ void encodeInstruction(const MCInst &MI, raw_ostream &OS, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const override; ++ ++ // getBinaryCodeForInstr - TableGen'erated function for getting the ++ // binary encoding for an instruction. ++ uint64_t getBinaryCodeForInstr(const MCInst &MI, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ // getJumpTargetOpValue - Return binary encoding of the jump ++ // target operand. If the machine operand requires relocation, ++ // record the relocation and return zero. ++ unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ // getBranchTargetOpValue - Return binary encoding of the branch ++ // target operand. If the machine operand requires relocation, ++ // record the relocation and return zero. ++ unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ // getMachineOpValue - Return binary encoding of operand. If the machin ++ // operand requires relocation, record the relocation and return zero. ++ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ template ++ unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getAMemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getMemEncoding10l2(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getMemEncoding11l1(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getMemEncoding9l3(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ template ++ unsigned getSimm14MemEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getFCMPEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ /// Subtract Offset then encode as a N-bit unsigned integer. ++ template ++ unsigned getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm11Lsl1Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm10Lsl2Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm9Lsl3Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm8Lsl1Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm8Lsl2Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++ unsigned getSImm8Lsl3Encoding(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups, ++ const MCSubtargetInfo &STI) const; ++ ++}; ++ ++} // end namespace llvm ++ ++#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCCODEEMITTER_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +new file mode 100644 +index 000000000..1af027f15 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +@@ -0,0 +1,158 @@ ++//===-- LoongArchMCExpr.cpp - LoongArch specific MC expression classes --------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchMCExpr.h" ++#include "llvm/BinaryFormat/ELF.h" ++#include "llvm/MC/MCAsmInfo.h" ++#include "llvm/MC/MCAssembler.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCStreamer.h" ++#include "llvm/MC/MCSymbolELF.h" ++#include "llvm/MC/MCValue.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/MathExtras.h" ++#include "llvm/Support/raw_ostream.h" ++#include ++ ++using namespace llvm; ++ ++#define DEBUG_TYPE "loongarchmcexpr" ++ ++const LoongArchMCExpr *LoongArchMCExpr::create(LoongArchMCExpr::LoongArchExprKind Kind, ++ const MCExpr *Expr, MCContext &Ctx) { ++ return new (Ctx) LoongArchMCExpr(Kind, Expr); ++} ++ ++void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { ++ int64_t AbsVal; ++ if (Expr->evaluateAsAbsolute(AbsVal)) ++ OS << AbsVal; ++ else ++ Expr->print(OS, MAI, true); ++} ++ ++bool ++LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res, ++ const MCAsmLayout *Layout, ++ const MCFixup *Fixup) const { ++ if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) ++ return false; ++ ++ if (Res.getRefKind() != MCSymbolRefExpr::VK_None) ++ return false; ++ ++ // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the ++ // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the ++ // caller. ++ if (Res.isAbsolute() && Fixup == nullptr) { ++ int64_t AbsVal = Res.getConstant(); ++ switch (Kind) { ++ default: ++ break; ++ case MEK_None: ++ case MEK_Special: ++ llvm_unreachable("MEK_None and MEK_Special are invalid"); ++ } ++ Res = MCValue::get(AbsVal); ++ return true; ++ } ++ ++ // We want to defer it for relocatable expressions since the constant is ++ // applied to the whole symbol value. ++ // ++ // The value of getKind() that is given to MCValue is only intended to aid ++ // debugging when inspecting MCValue objects. It shouldn't be relied upon ++ // for decision making. ++ Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); ++ ++ return true; ++} ++ ++void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const { ++ Streamer.visitUsedExpr(*getSubExpr()); ++} ++ ++static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { ++ switch (Expr->getKind()) { ++ case MCExpr::Target: ++ fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); ++ break; ++ case MCExpr::Constant: ++ break; ++ case MCExpr::Binary: { ++ const MCBinaryExpr *BE = cast(Expr); ++ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); ++ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); ++ break; ++ } ++ case MCExpr::SymbolRef: { ++ // We're known to be under a TLS fixup, so any symbol should be ++ // modified. There should be only one. ++ const MCSymbolRefExpr &SymRef = *cast(Expr); ++ cast(SymRef.getSymbol()).setType(ELF::STT_TLS); ++ break; ++ } ++ case MCExpr::Unary: ++ fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); ++ break; ++ } ++} ++ ++void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { ++ switch (getKind()) { ++ default: ++ break; ++ case MEK_None: ++ case MEK_Special: ++ llvm_unreachable("MEK_None and MEK_Special are invalid"); ++ break; ++ case MEK_CALL_HI: ++ case MEK_CALL_LO: ++ case MEK_GOT_HI: ++ case MEK_GOT_LO: ++ case MEK_GOT_RRHI: ++ case MEK_GOT_RRLO: ++ case MEK_GOT_RRHIGHER: ++ case MEK_GOT_RRHIGHEST: ++ case MEK_ABS_HI: ++ case MEK_ABS_LO: ++ case MEK_ABS_HIGHER: ++ case MEK_ABS_HIGHEST: ++ case MEK_PCREL_HI: ++ case MEK_PCREL_LO: ++ case MEK_PCREL_RRHI: ++ case MEK_PCREL_RRHIGHER: ++ case MEK_PCREL_RRHIGHEST: ++ case MEK_PCREL_RRLO: ++ case MEK_PLT: ++ // If we do have nested target-specific expressions, they will be in ++ // a consecutive chain. ++ if (const LoongArchMCExpr *E = dyn_cast(getSubExpr())) ++ E->fixELFSymbolsInTLSFixups(Asm); ++ break; ++ case MEK_TLSGD_HI: ++ case MEK_TLSGD_LO: ++ case MEK_TLSGD_RRHI: ++ case MEK_TLSGD_RRHIGHER: ++ case MEK_TLSGD_RRHIGHEST: ++ case MEK_TLSGD_RRLO: ++ case MEK_TLSLE_HI: ++ case MEK_TLSLE_HIGHER: ++ case MEK_TLSLE_HIGHEST: ++ case MEK_TLSLE_LO: ++ case MEK_TLSIE_HI: ++ case MEK_TLSIE_LO: ++ case MEK_TLSIE_RRHI: ++ case MEK_TLSIE_RRHIGHER: ++ case MEK_TLSIE_RRHIGHEST: ++ case MEK_TLSIE_RRLO: ++ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); ++ break; ++ } ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +new file mode 100644 +index 000000000..7851d478e +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +@@ -0,0 +1,97 @@ ++//===- LoongArchMCExpr.h - LoongArch specific MC expression classes -------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H ++#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H ++ ++#include "llvm/MC/MCAsmLayout.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCValue.h" ++ ++namespace llvm { ++ ++class LoongArchMCExpr : public MCTargetExpr { ++public: ++ enum LoongArchExprKind { ++ MEK_None, ++ MEK_CALL_HI, ++ MEK_CALL_LO, ++ MEK_GOT_HI, ++ MEK_GOT_LO, ++ MEK_GOT_RRHI, ++ MEK_GOT_RRHIGHER, ++ MEK_GOT_RRHIGHEST, ++ MEK_GOT_RRLO, ++ MEK_ABS_HI, ++ MEK_ABS_HIGHER, ++ MEK_ABS_HIGHEST, ++ MEK_ABS_LO, ++ MEK_PCREL_HI, ++ MEK_PCREL_LO, ++ MEK_PCREL_RRHI, ++ MEK_PCREL_RRHIGHER, ++ MEK_PCREL_RRHIGHEST, ++ MEK_PCREL_RRLO, ++ MEK_TLSLE_HI, ++ MEK_TLSLE_HIGHER, ++ MEK_TLSLE_HIGHEST, ++ MEK_TLSLE_LO, ++ MEK_TLSIE_HI, ++ MEK_TLSIE_LO, ++ MEK_TLSIE_RRHI, ++ MEK_TLSIE_RRHIGHER, ++ MEK_TLSIE_RRHIGHEST, ++ MEK_TLSIE_RRLO, ++ MEK_TLSGD_HI, ++ MEK_TLSGD_LO, ++ MEK_TLSGD_RRHI, ++ MEK_TLSGD_RRHIGHER, ++ MEK_TLSGD_RRHIGHEST, ++ MEK_TLSGD_RRLO, ++ MEK_PLT, ++ MEK_Special, ++ }; ++ ++private: ++ const LoongArchExprKind Kind; ++ const MCExpr *Expr; ++ ++ explicit LoongArchMCExpr(LoongArchExprKind Kind, const MCExpr *Expr) ++ : Kind(Kind), Expr(Expr) {} ++ ++public: ++ static const LoongArchMCExpr *create(LoongArchExprKind Kind, const MCExpr *Expr, ++ MCContext &Ctx); ++ static const LoongArchMCExpr *createGpOff(LoongArchExprKind Kind, const MCExpr *Expr, ++ MCContext &Ctx); ++ ++ /// Get the kind of this expression. ++ LoongArchExprKind getKind() const { return Kind; } ++ ++ /// Get the child of this expression. ++ const MCExpr *getSubExpr() const { return Expr; } ++ ++ void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; ++ bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, ++ const MCFixup *Fixup) const override; ++ void visitUsedExpr(MCStreamer &Streamer) const override; ++ ++ MCFragment *findAssociatedFragment() const override { ++ return getSubExpr()->findAssociatedFragment(); ++ } ++ ++ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; ++ ++ static bool classof(const MCExpr *E) { ++ return E->getKind() == MCExpr::Target; ++ } ++}; ++ ++} // end namespace llvm ++ ++#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCEXPR_H +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp +index 8d71235f6..18e3224ab 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions ---------===// ++//===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions -------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -11,35 +11,47 @@ + //===----------------------------------------------------------------------===// + + #include "LoongArchMCTargetDesc.h" +-#include "LoongArchBaseInfo.h" +-#include "LoongArchInstPrinter.h" +-#include "LoongArchMCAsmInfo.h" ++#include "LoongArchTargetStreamer.h" ++#include "MCTargetDesc/LoongArchAsmBackend.h" ++#include "MCTargetDesc/LoongArchELFStreamer.h" ++#include "MCTargetDesc/LoongArchInstPrinter.h" ++#include "MCTargetDesc/LoongArchMCAsmInfo.h" + #include "TargetInfo/LoongArchTargetInfo.h" +-#include "llvm/MC/MCAsmInfo.h" +-#include "llvm/MC/MCDwarf.h" ++#include "llvm/ADT/Triple.h" ++#include "llvm/MC/MCCodeEmitter.h" ++#include "llvm/MC/MCELFStreamer.h" + #include "llvm/MC/MCInstrAnalysis.h" + #include "llvm/MC/MCInstrInfo.h" ++#include "llvm/MC/MCObjectWriter.h" + #include "llvm/MC/MCRegisterInfo.h" + #include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCSymbol.h" ++#include "llvm/MC/MachineLocation.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/FormattedStream.h" + #include "llvm/MC/TargetRegistry.h" +-#include "llvm/Support/Compiler.h" ++ ++using namespace llvm; + + #define GET_INSTRINFO_MC_DESC +-#define ENABLE_INSTR_PREDICATE_VERIFIER + #include "LoongArchGenInstrInfo.inc" + +-#define GET_REGINFO_MC_DESC +-#include "LoongArchGenRegisterInfo.inc" +- + #define GET_SUBTARGETINFO_MC_DESC + #include "LoongArchGenSubtargetInfo.inc" + +-using namespace llvm; ++#define GET_REGINFO_MC_DESC ++#include "LoongArchGenRegisterInfo.inc" + +-static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { +- MCRegisterInfo *X = new MCRegisterInfo(); +- InitLoongArchMCRegisterInfo(X, LoongArch::R1); +- return X; ++/// Select the LoongArch CPU for the given triple and cpu name. ++/// FIXME: Merge with the copy in LoongArchSubtarget.cpp ++StringRef LoongArch_MC::selectLoongArchCPU(const Triple &TT, StringRef CPU) { ++ if (CPU.empty() || CPU == "generic") { ++ if (TT.isLoongArch32()) ++ CPU = "loongarch32"; //FIXME ++ else ++ CPU = "la464"; ++ } ++ return CPU; + } + + static MCInstrInfo *createLoongArchMCInstrInfo() { +@@ -48,20 +60,24 @@ static MCInstrInfo *createLoongArchMCInstrInfo() { + return X; + } + +-static MCSubtargetInfo * +-createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { +- if (CPU.empty()) +- CPU = TT.isArch64Bit() ? "la464" : "generic-la32"; ++static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { ++ MCRegisterInfo *X = new MCRegisterInfo(); ++ InitLoongArchMCRegisterInfo(X, LoongArch::RA); ++ return X; ++} ++ ++static MCSubtargetInfo *createLoongArchMCSubtargetInfo(const Triple &TT, ++ StringRef CPU, StringRef FS) { ++ CPU = LoongArch_MC::selectLoongArchCPU(TT, CPU); + return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); + } + + static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT, + const MCTargetOptions &Options) { +- MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT); ++ MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT, Options); + +- // Initial state of the frame pointer is sp(r3). +- MCRegister SP = MRI.getDwarfRegNum(LoongArch::R3, true); ++ unsigned SP = MRI.getDwarfRegNum(LoongArch::SP, true); + MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); + MAI->addInitialFrameState(Inst); + +@@ -76,40 +92,96 @@ static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T, + return new LoongArchInstPrinter(MAI, MII, MRI); + } + ++static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, ++ std::unique_ptr &&MAB, ++ std::unique_ptr &&OW, ++ std::unique_ptr &&Emitter, ++ bool RelaxAll) { ++ MCStreamer *S; ++ S = createLoongArchELFStreamer(Context, std::move(MAB), std::move(OW), ++ std::move(Emitter), RelaxAll); ++ return S; ++} ++ ++static MCTargetStreamer *createLoongArchAsmTargetStreamer(MCStreamer &S, ++ formatted_raw_ostream &OS, ++ MCInstPrinter *InstPrint, ++ bool isVerboseAsm) { ++ return new LoongArchTargetAsmStreamer(S, OS); ++} ++ ++static MCTargetStreamer *createLoongArchNullTargetStreamer(MCStreamer &S) { ++ return new LoongArchTargetStreamer(S); ++} ++ ++static MCTargetStreamer * ++createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { ++ return new LoongArchTargetELFStreamer(S, STI); ++} ++ + namespace { + + class LoongArchMCInstrAnalysis : public MCInstrAnalysis { + public: +- explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info) +- : MCInstrAnalysis(Info) {} ++ LoongArchMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + unsigned NumOps = Inst.getNumOperands(); +- if (isBranch(Inst) || Inst.getOpcode() == LoongArch::BL) { ++ if (NumOps == 0) ++ return false; ++ if (Info->get(Inst.getOpcode()).isBranch() || Inst.getOpcode() == LoongArch::BL) { ++ // just not jirl + Target = Addr + Inst.getOperand(NumOps - 1).getImm(); + return true; ++ } else { ++ return false; + } +- +- return false; + } + }; ++} + +-} // end namespace +- +-static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) { ++static MCInstrAnalysis *createLoongArchMCInstrAnalysis(const MCInstrInfo *Info) { + return new LoongArchMCInstrAnalysis(Info); + } + + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() { + for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) { +- TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); ++ // Register the MC asm info. ++ RegisterMCAsmInfoFn X(*T, createLoongArchMCAsmInfo); ++ ++ // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo); ++ ++ // Register the MC register info. ++ TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); ++ ++ // Register the elf streamer. ++ TargetRegistry::RegisterELFStreamer(*T, createMCStreamer); ++ ++ // Register the asm target streamer. ++ TargetRegistry::RegisterAsmTargetStreamer(*T, createLoongArchAsmTargetStreamer); ++ ++ TargetRegistry::RegisterNullTargetStreamer(*T, ++ createLoongArchNullTargetStreamer); ++ ++ // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo); +- TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo); +- TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); +- TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); ++ ++ // Register the MC instruction analyzer. ++ TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchMCInstrAnalysis); ++ ++ // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter); +- TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis); ++ ++ TargetRegistry::RegisterObjectTargetStreamer( ++ *T, createLoongArchObjectTargetStreamer); ++ ++ // Register the asm backend. ++ TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); + } ++ ++ // Register the MC Code Emitter ++ for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) ++ TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h +index ab35a0096..04a5c79e6 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h +@@ -1,4 +1,4 @@ +-//===- LoongArchMCTargetDesc.h - LoongArch Target Descriptions --*- C++ -*-===// ++//===-- LoongArchMCTargetDesc.h - LoongArch Target Descriptions -----------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -13,8 +13,8 @@ + #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H + #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H + +-#include "llvm/MC/MCTargetOptions.h" + #include "llvm/Support/DataTypes.h" ++ + #include + + namespace llvm { +@@ -25,7 +25,15 @@ class MCInstrInfo; + class MCObjectTargetWriter; + class MCRegisterInfo; + class MCSubtargetInfo; ++class MCTargetOptions; ++class StringRef; + class Target; ++class Triple; ++class raw_ostream; ++class raw_pwrite_stream; ++ ++Target &getTheLoongArch32Target(); ++Target &getTheLoongArch64Target(); + + MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, + MCContext &Ctx); +@@ -36,20 +44,24 @@ MCAsmBackend *createLoongArchAsmBackend(const Target &T, + const MCTargetOptions &Options); + + std::unique_ptr +-createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); ++createLoongArchELFObjectWriter(const Triple &TT, bool IsLPX32); ++ ++namespace LoongArch_MC { ++StringRef selectLoongArchCPU(const Triple &TT, StringRef CPU); ++} + +-} // end namespace llvm ++} // End llvm namespace + +-// Defines symbolic names for LoongArch registers. ++// Defines symbolic names for LoongArch registers. This defines a mapping from ++// register name to register number. + #define GET_REGINFO_ENUM + #include "LoongArchGenRegisterInfo.inc" + +-// Defines symbolic names for LoongArch instructions. ++// Defines symbolic names for the LoongArch instructions. + #define GET_INSTRINFO_ENUM +-#define GET_INSTRINFO_MC_HELPER_DECLS + #include "LoongArchGenInstrInfo.inc" + + #define GET_SUBTARGETINFO_ENUM + #include "LoongArchGenSubtargetInfo.inc" + +-#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H ++#endif +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp +deleted file mode 100644 +index 1509c436c..000000000 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMatInt.cpp ++++ /dev/null +@@ -1,51 +0,0 @@ +-//===- LoongArchMatInt.cpp - Immediate materialisation ---------*- C++ -*--===// +-// +-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +-// See https://llvm.org/LICENSE.txt for license information. +-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-// +-//===----------------------------------------------------------------------===// +- +-#include "LoongArchMatInt.h" +-#include "MCTargetDesc/LoongArchMCTargetDesc.h" +-#include "llvm/Support/MathExtras.h" +- +-using namespace llvm; +- +-LoongArchMatInt::InstSeq LoongArchMatInt::generateInstSeq(int64_t Val) { +- // Val: +- // | hi32 | lo32 | +- // +-----------+------------------+------------------+-----------+ +- // | Highest12 | Higher20 | Hi20 | Lo12 | +- // +-----------+------------------+------------------+-----------+ +- // 63 52 51 32 31 12 11 0 +- // +- const int64_t Highest12 = Val >> 52 & 0xFFF; +- const int64_t Higher20 = Val >> 32 & 0xFFFFF; +- const int64_t Hi20 = Val >> 12 & 0xFFFFF; +- const int64_t Lo12 = Val & 0xFFF; +- InstSeq Insts; +- +- if (Highest12 != 0 && SignExtend64<52>(Val) == 0) { +- Insts.push_back(Inst(LoongArch::LU52I_D, SignExtend64<12>(Highest12))); +- return Insts; +- } +- +- if (Hi20 == 0) +- Insts.push_back(Inst(LoongArch::ORI, Lo12)); +- else if (SignExtend32<1>(Lo12 >> 11) == SignExtend32<20>(Hi20)) +- Insts.push_back(Inst(LoongArch::ADDI_W, SignExtend64<12>(Lo12))); +- else { +- Insts.push_back(Inst(LoongArch::LU12I_W, SignExtend64<20>(Hi20))); +- if (Lo12 != 0) +- Insts.push_back(Inst(LoongArch::ORI, Lo12)); +- } +- +- if (SignExtend32<1>(Hi20 >> 19) != SignExtend32<20>(Higher20)) +- Insts.push_back(Inst(LoongArch::LU32I_D, SignExtend64<20>(Higher20))); +- +- if (SignExtend32<1>(Higher20 >> 19) != SignExtend32<12>(Highest12)) +- Insts.push_back(Inst(LoongArch::LU52I_D, SignExtend64<12>(Highest12))); +- +- return Insts; +-} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp +new file mode 100644 +index 000000000..4d0e785a3 +--- /dev/null ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchTargetStreamer.cpp +@@ -0,0 +1,330 @@ ++//===-- LoongArchTargetStreamer.cpp - LoongArch Target Streamer Methods -------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++// ++// This file provides LoongArch specific target streamer methods. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "LoongArchABIInfo.h" ++#include "LoongArchELFStreamer.h" ++#include "LoongArchInstPrinter.h" ++#include "LoongArchMCExpr.h" ++#include "LoongArchMCTargetDesc.h" ++#include "LoongArchTargetObjectFile.h" ++#include "LoongArchTargetStreamer.h" ++#include "llvm/BinaryFormat/ELF.h" ++#include "llvm/MC/MCAssembler.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCSectionELF.h" ++#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCSymbolELF.h" ++#include "llvm/Support/Casting.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "llvm/Support/FormattedStream.h" ++ ++using namespace llvm; ++ ++namespace { ++static cl::opt RoundSectionSizes( ++ "loongarch-round-section-sizes", cl::init(false), ++ cl::desc("Round section sizes up to the section alignment"), cl::Hidden); ++} // end anonymous namespace ++ ++LoongArchTargetStreamer::LoongArchTargetStreamer(MCStreamer &S) ++ : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { ++ GPRInfoSet = FPRInfoSet = FrameInfoSet = false; ++} ++void LoongArchTargetStreamer::emitDirectiveOptionPic0() {} ++void LoongArchTargetStreamer::emitDirectiveOptionPic2() {} ++void LoongArchTargetStreamer::emitDirectiveSetArch(StringRef Arch) { ++ forbidModuleDirective(); ++} ++void LoongArchTargetStreamer::emitDirectiveSetLoongArch32() { forbidModuleDirective(); } ++void LoongArchTargetStreamer::emitDirectiveSetloongarch64() { forbidModuleDirective(); } ++ ++void LoongArchTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRXX(unsigned Opcode, unsigned Reg0, MCOperand Op1, ++ MCOperand Op2, SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.addOperand(Op1); ++ TmpInst.addOperand(Op2); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRRXX(unsigned Opcode, unsigned Reg0, unsigned Reg1, ++ MCOperand Op2, MCOperand Op3, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.addOperand(MCOperand::createReg(Reg1)); ++ TmpInst.addOperand(Op2); ++ TmpInst.addOperand(Op3); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, ++ SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.addOperand(Op1); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, ++ SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI); ++} ++ ++void LoongArchTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, ++ SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI); ++} ++ ++void LoongArchTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, ++ SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createImm(Imm1)); ++ TmpInst.addOperand(MCOperand::createImm(Imm2)); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, ++ MCOperand Op2, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.addOperand(MCOperand::createReg(Reg1)); ++ TmpInst.addOperand(Op2); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, ++ unsigned Reg2, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); ++} ++ ++void LoongArchTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, ++ unsigned Reg1, int32_t Imm, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI); ++} ++ ++void LoongArchTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0, ++ unsigned Reg1, int16_t Imm0, int16_t Imm1, ++ int16_t Imm2, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ MCInst TmpInst; ++ TmpInst.setOpcode(Opcode); ++ TmpInst.addOperand(MCOperand::createReg(Reg0)); ++ TmpInst.addOperand(MCOperand::createReg(Reg1)); ++ TmpInst.addOperand(MCOperand::createImm(Imm0)); ++ TmpInst.addOperand(MCOperand::createImm(Imm1)); ++ TmpInst.addOperand(MCOperand::createImm(Imm2)); ++ TmpInst.setLoc(IDLoc); ++ getStreamer().emitInstruction(TmpInst, *STI); ++} ++ ++void LoongArchTargetStreamer::emitAdd(unsigned DstReg, unsigned SrcReg, ++ unsigned TrgReg, bool Is64Bit, ++ const MCSubtargetInfo *STI) { ++ emitRRR(Is64Bit ? LoongArch::ADD_D : LoongArch::ADD_W, DstReg, SrcReg, TrgReg, SMLoc(), ++ STI); ++} ++ ++void LoongArchTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg, ++ int16_t ShiftAmount, SMLoc IDLoc, ++ const MCSubtargetInfo *STI) { ++ if (ShiftAmount >= 32) { ++ emitRRI(LoongArch::SLLI_D, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI); ++ return; ++ } ++ ++ emitRRI(LoongArch::SLLI_D, DstReg, SrcReg, ShiftAmount, IDLoc, STI); ++} ++ ++void LoongArchTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { ++ emitRRI(LoongArch::ANDI, LoongArch::ZERO, LoongArch::ZERO, 0, IDLoc, STI); ++} ++ ++LoongArchTargetAsmStreamer::LoongArchTargetAsmStreamer(MCStreamer &S, ++ formatted_raw_ostream &OS) ++ : LoongArchTargetStreamer(S), OS(OS) {} ++ ++void LoongArchTargetAsmStreamer::emitDirectiveOptionPic0() { ++ OS << "\t.option\tpic0\n"; ++} ++ ++void LoongArchTargetAsmStreamer::emitDirectiveOptionPic2() { ++ OS << "\t.option\tpic2\n"; ++} ++ ++void LoongArchTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { ++ OS << "\t.set arch=" << Arch << "\n"; ++ LoongArchTargetStreamer::emitDirectiveSetArch(Arch); ++} ++ ++void LoongArchTargetAsmStreamer::emitDirectiveSetLoongArch32() { ++ //OS << "\t.set\tloongarch32\n"; ++ LoongArchTargetStreamer::emitDirectiveSetLoongArch32(); ++} ++ ++void LoongArchTargetAsmStreamer::emitDirectiveSetloongarch64() { ++ //OS << "\t.set\tloongarch64\n"; ++ LoongArchTargetStreamer::emitDirectiveSetloongarch64(); ++} ++ ++// This part is for ELF object output. ++LoongArchTargetELFStreamer::LoongArchTargetELFStreamer(MCStreamer &S, ++ const MCSubtargetInfo &STI) ++ : LoongArchTargetStreamer(S), STI(STI) { ++ MCAssembler &MCA = getStreamer().getAssembler(); ++ ++ // It's possible that MCObjectFileInfo isn't fully initialized at this point ++ // due to an initialization order problem where LLVMTargetMachine creates the ++ // target streamer before TargetLoweringObjectFile calls ++ // InitializeMCObjectFileInfo. There doesn't seem to be a single place that ++ // covers all cases so this statement covers most cases and direct object ++ // emission must call setPic() once MCObjectFileInfo has been initialized. The ++ // cases we don't handle here are covered by LoongArchAsmPrinter. ++ Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent(); ++ ++ // Set the header flags that we can in the constructor. ++ // FIXME: This is a fairly terrible hack. We set the rest ++ // of these in the destructor. The problem here is two-fold: ++ // ++ // a: Some of the eflags can be set/reset by directives. ++ // b: There aren't any usage paths that initialize the ABI ++ // pointer until after we initialize either an assembler ++ // or the target machine. ++ // We can fix this by making the target streamer construct ++ // the ABI, but this is fraught with wide ranging dependency ++ // issues as well. ++ unsigned EFlags = MCA.getELFHeaderEFlags(); ++ ++ // FIXME: Fix a dependency issue by instantiating the ABI object to some ++ // default based off the triple. The triple doesn't describe the target ++ // fully, but any external user of the API that uses the MCTargetStreamer ++ // would otherwise crash on assertion failure. ++ ++ ABI = LoongArchABIInfo( ++ STI.getTargetTriple().getArch() == Triple::ArchType::loongarch32 ++ ? LoongArchABIInfo::LP32() ++ : LoongArchABIInfo::LP64()); ++ ++ EFlags |= ELF::EF_LARCH_ABI; ++ MCA.setELFHeaderEFlags(EFlags); ++} ++ ++void LoongArchTargetELFStreamer::emitLabel(MCSymbol *S) { ++ auto *Symbol = cast(S); ++ getStreamer().getAssembler().registerSymbol(*Symbol); ++ uint8_t Type = Symbol->getType(); ++ if (Type != ELF::STT_FUNC) ++ return; ++ ++} ++ ++void LoongArchTargetELFStreamer::finish() { ++ MCAssembler &MCA = getStreamer().getAssembler(); ++ const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); ++ ++ // .bss, .text and .data are always at least 16-byte aligned. ++ MCSection &TextSection = *OFI.getTextSection(); ++ MCA.registerSection(TextSection); ++ MCSection &DataSection = *OFI.getDataSection(); ++ MCA.registerSection(DataSection); ++ MCSection &BSSSection = *OFI.getBSSSection(); ++ MCA.registerSection(BSSSection); ++ ++ TextSection.setAlignment(Align(std::max(16u, TextSection.getAlignment()))); ++ DataSection.setAlignment(Align(std::max(16u, DataSection.getAlignment()))); ++ BSSSection.setAlignment(Align(std::max(16u, BSSSection.getAlignment()))); ++ ++ if (RoundSectionSizes) { ++ // Make sections sizes a multiple of the alignment. This is useful for ++ // verifying the output of IAS against the output of other assemblers but ++ // it's not necessary to produce a correct object and increases section ++ // size. ++ MCStreamer &OS = getStreamer(); ++ for (MCSection &S : MCA) { ++ MCSectionELF &Section = static_cast(S); ++ ++ unsigned Alignment = Section.getAlignment(); ++ if (Alignment) { ++ OS.switchSection(&Section); ++ if (Section.useCodeAlign()) ++ OS.emitCodeAlignment(Alignment, &STI, Alignment); ++ else ++ OS.emitValueToAlignment(Alignment, 0, 1, Alignment); ++ } ++ } ++ } ++ ++ // Update e_header flags. See the FIXME and comment above in ++ // the constructor for a full rundown on this. ++ unsigned EFlags = MCA.getELFHeaderEFlags(); ++ ++ // ABI ++ // LP64 does not require any ABI bits. ++ if (getABI().IsLP32()) ++ EFlags |= ELF::EF_LARCH_ABI_LP32; ++ else if (getABI().IsLPX32()) ++ EFlags |= ELF::EF_LARCH_ABI_LPX32; ++ else ++ EFlags |= ELF::EF_LARCH_ABI_LP64; ++ ++ MCA.setELFHeaderEFlags(EFlags); ++} ++ ++MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() { ++ return static_cast(Streamer); ++} ++ ++void LoongArchTargetELFStreamer::emitDirectiveOptionPic0() { ++ MCAssembler &MCA = getStreamer().getAssembler(); ++ unsigned Flags = MCA.getELFHeaderEFlags(); ++ // This option overrides other PIC options like -KPIC. ++ Pic = false; ++ ///XXX:Reloc no this flags ++ //Flags &= ~ELF::EF_LOONGARCH_PIC; ++ MCA.setELFHeaderEFlags(Flags); ++} ++ ++void LoongArchTargetELFStreamer::emitDirectiveOptionPic2() { ++ MCAssembler &MCA = getStreamer().getAssembler(); ++ unsigned Flags = MCA.getELFHeaderEFlags(); ++ Pic = true; ++ // NOTE: We are following the GAS behaviour here which means the directive ++ // 'pic2' also sets the CPIC bit in the ELF header. This is different from ++ // what is stated in the SYSV ABI which consider the bits EF_LOONGARCH_PIC and ++ // EF_LOONGARCH_CPIC to be mutually exclusive. ++ ///XXX:Reloc no this flags ++ //Flags |= ELF::EF_LOONGARCH_PIC | ELF::EF_LOONGARCH_CPIC; ++ MCA.setELFHeaderEFlags(Flags); ++} +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt +index e14360ff5..f53ddba40 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt +@@ -2,7 +2,6 @@ add_llvm_component_library(LLVMLoongArchInfo + LoongArchTargetInfo.cpp + + LINK_COMPONENTS +- MC + Support + + ADD_TO_COMPONENT +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp +index 106545100..e6b845180 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp +@@ -1,4 +1,4 @@ +-//===-- LoongArchTargetInfo.cpp - LoongArch Target Implementation ---------===// ++//===-- LoongArchTargetInfo.cpp - LoongArch Target Implementation -------------------===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -21,10 +21,14 @@ Target &llvm::getTheLoongArch64Target() { + } + + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetInfo() { +- RegisterTarget X( +- getTheLoongArch32Target(), "loongarch32", "32-bit LoongArch", +- "LoongArch"); +- RegisterTarget Y( +- getTheLoongArch64Target(), "loongarch64", "64-bit LoongArch", +- "LoongArch"); ++#if 0 ++ //TODO: support it in futrue ++ RegisterTarget ++ X(getTheLoongArch32Target(), "loongarch32", "LoongArch (32-bit)", "LoongArch"); ++#endif ++ RegisterTarget ++ A(getTheLoongArch64Target(), "loongarch64", "LoongArch (64-bit)", ++ "LoongArch"); + } +diff --git a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h +index b24cf8795..7dce2497f 100644 +--- a/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h ++++ b/src/llvm-project/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h +@@ -1,4 +1,4 @@ +-//===-- LoongArchTargetInfo.h - LoongArch Target Implementation -*- C++ -*-===// ++//===-- LoongArchTargetInfo.h - LoongArch Target Implementation -----------*- C++ -*-===// + // + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. +@@ -16,6 +16,6 @@ class Target; + Target &getTheLoongArch32Target(); + Target &getTheLoongArch64Target(); + +-} // end namespace llvm ++} // namespace llvm + + #endif // LLVM_LIB_TARGET_LOONGARCH_TARGETINFO_LOONGARCHTARGETINFO_H +diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td b/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td +index e6d23f741..8afd0a7fc 100644 +--- a/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td ++++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcCallingConv.td +@@ -125,10 +125,14 @@ def CC_Sparc64 : CallingConv<[ + def RetCC_Sparc64 : CallingConv<[ + // A single f32 return value always goes in %f0. The ABI doesn't specify what + // happens to multiple f32 return values outside a struct. +- CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, ++ CCIfType<[f32], CCCustom<"RetCC_Sparc64_Half">>, + +- // Otherwise, return values are passed exactly like arguments. +- CCDelegateTo ++ // Otherwise, return values are passed exactly like arguments, except that ++ // returns that are too big to fit into the registers is passed as an sret ++ // instead. ++ CCIfInReg>>, ++ CCIfType<[i32], CCPromoteToType>, ++ CCCustom<"RetCC_Sparc64_Full"> + ]>; + + // Callee-saved registers are handled by the register window mechanism. +diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp +index 2cb74e770..f55675089 100644 +--- a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp ++++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp +@@ -101,9 +101,9 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, + } + + // Allocate a full-sized argument for the 64-bit ABI. +-static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, +- MVT &LocVT, CCValAssign::LocInfo &LocInfo, +- ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, ++ MVT &LocVT, CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { + assert((LocVT == MVT::f32 || LocVT == MVT::f128 + || LocVT.getSizeInBits() == 64) && + "Can't handle non-64 bits locations"); +@@ -133,6 +133,11 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, + return true; + } + ++ // Bail out if this is a return CC and we run out of registers to place ++ // values into. ++ if (IsReturn) ++ return false; ++ + // This argument goes on the stack in an 8-byte slot. + // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to + // the right-aligned float. The first 4 bytes of the stack slot are undefined. +@@ -146,9 +151,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, + // Allocate a half-sized argument for the 64-bit ABI. + // + // This is used when passing { float, int } structs by value in registers. +-static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, +- MVT &LocVT, CCValAssign::LocInfo &LocInfo, +- ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT, ++ MVT &LocVT, CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { + assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); + unsigned Offset = State.AllocateStack(4, Align(4)); + +@@ -174,10 +179,43 @@ static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, + return true; + } + ++ // Bail out if this is a return CC and we run out of registers to place ++ // values into. ++ if (IsReturn) ++ return false; ++ + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return true; + } + ++static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, ++ CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++ return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, ++ State); ++} ++ ++static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, ++ CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++ return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, ++ State); ++} ++ ++static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, ++ CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++ return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, ++ State); ++} ++ ++static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, ++ CCValAssign::LocInfo &LocInfo, ++ ISD::ArgFlagsTy &ArgFlags, CCState &State) { ++ return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, ++ State); ++} ++ + #include "SparcGenCallingConv.inc" + + // The calling conventions in SparcCallingConv.td are described in terms of the +@@ -191,6 +229,15 @@ static unsigned toCallerWindow(unsigned Reg) { + return Reg; + } + ++bool SparcTargetLowering::CanLowerReturn( ++ CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, ++ const SmallVectorImpl &Outs, LLVMContext &Context) const { ++ SmallVector RVLocs; ++ CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); ++ return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64 ++ : RetCC_Sparc32); ++} ++ + SDValue + SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, +@@ -1031,6 +1078,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { ++ assert(RVLocs[i].isRegLoc() && "Can only return in registers!"); + if (RVLocs[i].getLocVT() == MVT::v2i32) { + SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); + SDValue Lo = DAG.getCopyFromReg( +@@ -1346,6 +1394,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; ++ assert(VA.isRegLoc() && "Can only return in registers!"); + unsigned Reg = toCallerWindow(VA.getLocReg()); + + // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can +diff --git a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h +index 2768bb205..16e4f2687 100644 +--- a/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h ++++ b/src/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.h +@@ -144,6 +144,11 @@ namespace llvm { + SDValue LowerCall_64(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const; + ++ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, ++ bool isVarArg, ++ const SmallVectorImpl &Outs, ++ LLVMContext &Context) const override; ++ + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, +diff --git a/src/llvm-project/llvm/lib/Target/X86/X86.td b/src/llvm-project/llvm/lib/Target/X86/X86.td +index fa0a6bd41..f98916e81 100644 +--- a/src/llvm-project/llvm/lib/Target/X86/X86.td ++++ b/src/llvm-project/llvm/lib/Target/X86/X86.td +@@ -909,7 +909,6 @@ def ProcessorFeatures { + FeatureTSXLDTRK, + FeatureENQCMD, + FeatureSHSTK, +- FeatureVP2INTERSECT, + FeatureMOVDIRI, + FeatureMOVDIR64B, + FeatureUINTR]; +diff --git a/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp +index 6df040925..6fc7b29c5 100644 +--- a/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp +@@ -2003,7 +2003,7 @@ OptimizeFunctions(Module &M, + // FIXME: We should also hoist alloca affected by this to the entry + // block if possible. + if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) && +- !F.hasAddressTaken() && !hasMustTailCallers(&F)) { ++ !F.hasAddressTaken() && !hasMustTailCallers(&F) && !F.isVarArg()) { + RemoveAttribute(&F, Attribute::InAlloca); + Changed = true; + } +diff --git a/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +index bc01d2ef7..52596b304 100644 +--- a/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +@@ -3289,6 +3289,10 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) { + if (CallerPAL.hasParamAttr(i, Attribute::SwiftError)) + return false; + ++ if (CallerPAL.hasParamAttr(i, Attribute::ByVal) != ++ Callee->getAttributes().hasParamAttr(i, Attribute::ByVal)) ++ return false; // Cannot transform to or from byval. ++ + // If the parameter is passed as a byval argument, then we have to have a + // sized type and the sized type has to have the same size as the old type. + if (ParamTy != ActTy && CallerPAL.hasParamAttr(i, Attribute::ByVal)) { +diff --git a/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp +index 0d2662108..adc007dac 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp +@@ -406,6 +406,7 @@ static bool shouldApply(Function &F, ProfileSummaryInfo& PSI) { + return CHRFunctions.count(F.getName()); + } + ++ assert(PSI.hasProfileSummary() && "Empty PSI?"); + return PSI.isFunctionEntryHot(&F); + } + +diff --git a/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp b/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp +index 143a03574..644c5c82e 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Scalar/SROA.cpp +@@ -1210,8 +1210,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) { + BasicBlock *BB = PN.getParent(); + Align MaxAlign; + uint64_t APWidth = DL.getIndexTypeSizeInBits(PN.getType()); +- APInt MaxSize(APWidth, 0); +- bool HaveLoad = false; ++ Type *LoadType = nullptr; + for (User *U : PN.users()) { + LoadInst *LI = dyn_cast(U); + if (!LI || !LI->isSimple()) +@@ -1223,21 +1222,27 @@ static bool isSafePHIToSpeculate(PHINode &PN) { + if (LI->getParent() != BB) + return false; + ++ if (LoadType) { ++ if (LoadType != LI->getType()) ++ return false; ++ } else { ++ LoadType = LI->getType(); ++ } ++ + // Ensure that there are no instructions between the PHI and the load that + // could store. + for (BasicBlock::iterator BBI(PN); &*BBI != LI; ++BBI) + if (BBI->mayWriteToMemory()) + return false; + +- uint64_t Size = DL.getTypeStoreSize(LI->getType()).getFixedSize(); + MaxAlign = std::max(MaxAlign, LI->getAlign()); +- MaxSize = MaxSize.ult(Size) ? APInt(APWidth, Size) : MaxSize; +- HaveLoad = true; + } + +- if (!HaveLoad) ++ if (!LoadType) + return false; + ++ APInt LoadSize = APInt(APWidth, DL.getTypeStoreSize(LoadType).getFixedSize()); ++ + // We can only transform this if it is safe to push the loads into the + // predecessor blocks. The only thing to watch out for is that we can't put + // a possibly trapping load in the predecessor if it is a critical edge. +@@ -1259,7 +1264,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) { + // If this pointer is always safe to load, or if we can prove that there + // is already a load in the block, then we can move the load to the pred + // block. +- if (isSafeToLoadUnconditionally(InVal, MaxAlign, MaxSize, DL, TI)) ++ if (isSafeToLoadUnconditionally(InVal, MaxAlign, LoadSize, DL, TI)) + continue; + + return false; +diff --git a/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp b/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp +index 97f29527b..6309eed79 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Utils/LoopVersioning.cpp +@@ -137,8 +137,10 @@ void LoopVersioning::addPHINodes( + // See if we have a single-operand PHI with the value defined by the + // original loop. + for (auto I = PHIBlock->begin(); (PN = dyn_cast(I)); ++I) { +- if (PN->getIncomingValue(0) == Inst) ++ if (PN->getIncomingValue(0) == Inst) { ++ SE->forgetValue(PN); + break; ++ } + } + // If not create it. + if (!PN) { +diff --git a/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp b/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp +index 42be67f3c..264da2187 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Utils/VNCoercion.cpp +@@ -356,9 +356,9 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, + + // If this is memset, we just need to see if the offset is valid in the size + // of the memset.. +- if (MI->getIntrinsicID() == Intrinsic::memset) { ++ if (const auto *memset_inst = dyn_cast(MI)) { + if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) { +- auto *CI = dyn_cast(cast(MI)->getValue()); ++ auto *CI = dyn_cast(memset_inst->getValue()); + if (!CI || !CI->isZero()) + return -1; + } +diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +index 2cdae028e..5fd4e45d8 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +@@ -8154,7 +8154,7 @@ VPRecipeBase *VPRecipeBuilder::tryToOptimizeInductionPHI( + Phi, Operands[0], *II, *PSE.getSE(), + LoopVectorizationPlanner::getDecisionAndClampRange( + [&](ElementCount VF) { +- return !VF.isScalable() && CM.isScalarAfterVectorization(Phi, VF); ++ return CM.isScalarAfterVectorization(Phi, VF); + }, + Range)); + } +@@ -9338,7 +9338,7 @@ void VPWidenPointerInductionRecipe::execute(VPTransformState &State) { + auto *IVR = getParent()->getPlan()->getCanonicalIV(); + PHINode *CanonicalIV = cast(State.get(IVR, 0)); + +- if (onlyScalarsGenerated()) { ++ if (onlyScalarsGenerated(State.VF)) { + // This is the normalized GEP that starts counting at zero. + Value *PtrInd = State.Builder.CreateSExtOrTrunc( + CanonicalIV, IndDesc.getStep()->getType()); +diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp +index 0662ca883..30032dda7 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.cpp +@@ -698,7 +698,7 @@ void VPlan::execute(VPTransformState *State) { + auto *WidenPhi = cast(&R); + // TODO: Split off the case that all users of a pointer phi are scalar + // from the VPWidenPointerInductionRecipe. +- if (WidenPhi->onlyScalarsGenerated()) ++ if (WidenPhi->onlyScalarsGenerated(State->VF)) + continue; + + auto *GEP = cast(State->get(WidenPhi, 0)); +diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h +index 329843bf9..7a6bc48e2 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h ++++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h +@@ -1220,7 +1220,7 @@ public: + void execute(VPTransformState &State) override; + + /// Returns true if only scalar values will be generated. +- bool onlyScalarsGenerated(); ++ bool onlyScalarsGenerated(ElementCount VF); + + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + /// Print the recipe. +diff --git a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +index f214563af..9a404640b 100644 +--- a/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp ++++ b/src/llvm-project/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +@@ -982,8 +982,9 @@ void VPCanonicalIVPHIRecipe::print(raw_ostream &O, const Twine &Indent, + } + #endif + +-bool VPWidenPointerInductionRecipe::onlyScalarsGenerated() { +- return IsScalarAfterVectorization; ++bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(ElementCount VF) { ++ return IsScalarAfterVectorization && ++ (!VF.isScalable() || vputils::onlyFirstLaneUsed(this)); + } + + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +diff --git a/src/llvm-project/llvm/test/CMakeLists.txt b/src/llvm-project/llvm/test/CMakeLists.txt +index 86ca20ada..e7dd22261 100644 +--- a/src/llvm-project/llvm/test/CMakeLists.txt ++++ b/src/llvm-project/llvm/test/CMakeLists.txt +@@ -8,6 +8,7 @@ llvm_canonicalize_cmake_booleans( + LLVM_ENABLE_CURL + LLVM_ENABLE_HTTPLIB + LLVM_ENABLE_ZLIB ++ LLVM_ENABLE_ZSTD + LLVM_ENABLE_LIBXML2 + LLVM_INCLUDE_GO_TESTS + LLVM_LINK_LLVM_DYLIB +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir +deleted file mode 100644 +index c7d74b987..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/1ri.mir ++++ /dev/null +@@ -1,96 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 1RI20 +-# ------------------------------------------------------------------------------------------------- +-# ---------------------+-----------------------------------------------------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------+-----------------------------------------------------------+--------------- +-# opcode | imm20 | rd +-# ---------------------+-----------------------------------------------------------+--------------- +- +---- +-# CHECK-LABEL: test_LU12I_W: +-# CHECK-ENC: 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 +-# CHECK-ASM: lu12i.w $a0, 49 +-name: test_LU12I_W +-body: | +- bb.0: +- $r4 = LU12I_W 49 +-... +---- +-# CHECK-LABEL: test_LU32I_D: +-# CHECK-ENC: 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 +-# CHECK-ASM: lu32i.d $a0, 196 +-name: test_LU32I_D +-body: | +- bb.0: +- $r4 = LU32I_D $r4, 196 +-... +---- +-# CHECK-LABEL: test_PCADDI: +-# CHECK-ENC: 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 0 1 0 0 +-# CHECK-ASM: pcaddi $a0, 187 +-name: test_PCADDI +-body: | +- bb.0: +- $r4 = PCADDI 187 +-... +---- +-# CHECK-LABEL: test_PCALAU12I: +-# CHECK-ENC: 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 0 +-# CHECK-ASM: pcalau12i $a0, 89 +-name: test_PCALAU12I +-body: | +- bb.0: +- $r4 = PCALAU12I 89 +-... +---- +-# CHECK-LABEL: test_PCADDU12I: +-# CHECK-ENC: 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: pcaddu12i $a0, 37 +-name: test_PCADDU12I +-body: | +- bb.0: +- $r4 = PCADDU12I 37 +-... +---- +-# CHECK-LABEL: test_PCADDU18I: +-# CHECK-ENC: 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 +-# CHECK-ASM: pcaddu18i $a0, 26 +-name: test_PCADDU18I +-body: | +- bb.0: +- $r4 = PCADDU18I 26 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 1RI21 +-# ------------------------------------------------------------------------------------------------- +-# ------------------+-----------------------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------+-----------------------------------------------+--------------+--------------- +-# opcode | imm21{15-0} | rj | imm21{20-16} +-# ------------------+-----------------------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_BEQZ: +-# CHECK-ENC: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 0 +-# CHECK-ASM: beqz $a0, 92 +-name: test_BEQZ +-body: | +- bb.0: +- BEQZ $r4, 92 +-... +---- +-# CHECK-LABEL: test_BNEZ: +-# CHECK-ENC: 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 +-# CHECK-ASM: bnez $a0, 84 +-name: test_BNEZ +-body: | +- bb.0: +- BNEZ $r4, 84 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir +deleted file mode 100644 +index 488944526..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/2r.mir ++++ /dev/null +@@ -1,230 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2R +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------------------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------------------------------------------+--------------+--------------- +-# opcode | rj | rd +-# ------------------------------------------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_CLO_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: clo.w $a0, $a1 +-name: test_CLO_W +-body: | +- bb.0: +- $r4 = CLO_W $r5 +-... +---- +-# CHECK-LABEL: test_CLZ_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: clz.w $a0, $a1 +-name: test_CLZ_W +-body: | +- bb.0: +- $r4 = CLZ_W $r5 +-... +---- +-# CHECK-LABEL: test_CTO_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: cto.w $a0, $a1 +-name: test_CTO_W +-body: | +- bb.0: +- $r4 = CTO_W $r5 +-... +---- +-# CHECK-LABEL: test_CTZ_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ctz.w $a0, $a1 +-name: test_CTZ_W +-body: | +- bb.0: +- $r4 = CTZ_W $r5 +-... +---- +-# CHECK-LABEL: test_CLO_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: clo.d $a0, $a1 +-name: test_CLO_D +-body: | +- bb.0: +- $r4 = CLO_D $r5 +-... +---- +-# CHECK-LABEL: test_CLZ_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: clz.d $a0, $a1 +-name: test_CLZ_D +-body: | +- bb.0: +- $r4 = CLZ_D $r5 +-... +---- +-# CHECK-LABEL: test_CTO_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: cto.d $a0, $a1 +-name: test_CTO_D +-body: | +- bb.0: +- $r4 = CTO_D $r5 +-... +---- +-# CHECK-LABEL: test_CTZ_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ctz.d $a0, $a1 +-name: test_CTZ_D +-body: | +- bb.0: +- $r4 = CTZ_D $r5 +-... +---- +-# CHECK-LABEL: test_REVB_2H: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revb.2h $a0, $a1 +-name: test_REVB_2H +-body: | +- bb.0: +- $r4 = REVB_2H $r5 +-... +---- +-# CHECK-LABEL: test_REVB_4H: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revb.4h $a0, $a1 +-name: test_REVB_4H +-body: | +- bb.0: +- $r4 = REVB_4H $r5 +-... +---- +-# CHECK-LABEL: test_REVB_2W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revb.2w $a0, $a1 +-name: test_REVB_2W +-body: | +- bb.0: +- $r4 = REVB_2W $r5 +-... +---- +-# CHECK-LABEL: test_REVB_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revb.d $a0, $a1 +-name: test_REVB_D +-body: | +- bb.0: +- $r4 = REVB_D $r5 +-... +---- +-# CHECK-LABEL: test_REVH_2W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revh.2w $a0, $a1 +-name: test_REVH_2W +-body: | +- bb.0: +- $r4 = REVH_2W $r5 +-... +---- +-# CHECK-LABEL: test_REVH_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: revh.d $a0, $a1 +-name: test_REVH_D +-body: | +- bb.0: +- $r4 = REVH_D $r5 +-... +---- +-# CHECK-LABEL: test_BITREV_4B: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bitrev.4b $a0, $a1 +-name: test_BITREV_4B +-body: | +- bb.0: +- $r4 = BITREV_4B $r5 +-... +---- +-# CHECK-LABEL: test_BITREV_8B: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bitrev.8b $a0, $a1 +-name: test_BITREV_8B +-body: | +- bb.0: +- $r4 = BITREV_8B $r5 +-... +---- +-# CHECK-LABEL: test_BITREV_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bitrev.w $a0, $a1 +-name: test_BITREV_W +-body: | +- bb.0: +- $r4 = BITREV_W $r5 +-... +---- +-# CHECK-LABEL: test_BITREV_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bitrev.d $a0, $a1 +-name: test_BITREV_D +-body: | +- bb.0: +- $r4 = BITREV_D $r5 +-... +---- +-# CHECK-LABEL: test_EXT_W_H: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ext.w.h $a0, $a1 +-name: test_EXT_W_H +-body: | +- bb.0: +- $r4 = EXT_W_H $r5 +-... +---- +-# CHECK-LABEL: test_EXT_W_B: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ext.w.b $a0, $a1 +-name: test_EXT_W_B +-body: | +- bb.0: +- $r4 = EXT_W_B $r5 +-... +---- +-# CHECK-LABEL: test_CPUCFG: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: cpucfg $a0, $a1 +-name: test_CPUCFG +-body: | +- bb.0: +- $r4 = CPUCFG $r5 +-... +---- +-# CHECK-LABEL: test_RDTIMEL_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rdtimel.w $a0, $a1 +-name: test_RDTIMEL_W +-body: | +- bb.0: +- $r4, $r5 = RDTIMEL_W +-... +---- +-# CHECK-LABEL: test_RDTIMEH_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rdtimeh.w $a0, $a1 +-name: test_RDTIMEH_W +-body: | +- bb.0: +- $r4, $r5 = RDTIMEH_W +-... +---- +-# CHECK-LABEL: test_RDTIME_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rdtime.d $a0, $a1 +-name: test_RDTIME_D +-body: | +- bb.0: +- $r4, $r5 = RDTIME_D +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir +deleted file mode 100644 +index 263fed42c..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/2ri.mir ++++ /dev/null +@@ -1,432 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2RI5 +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------------+--------------+--------------+--------------- +-# opcode | imm5 | rj | rd +-# ---------------------------------------------------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_SLLI_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: slli.w $a0, $a1, 0 +-name: test_SLLI_W +-body: | +- bb.0: +- $r4 = SLLI_W $r5, 0 +-... +---- +-# CHECK-LABEL: test_SRLI_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srli.w $a0, $a1, 30 +-name: test_SRLI_W +-body: | +- bb.0: +- $r4 = SRLI_W $r5, 30 +-... +---- +-# CHECK-LABEL: test_SRAI_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srai.w $a0, $a1, 24 +-name: test_SRAI_W +-body: | +- bb.0: +- $r4 = SRAI_W $r5, 24 +-... +---- +-# CHECK-LABEL: test_ROTRI_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rotri.w $a0, $a1, 23 +-name: test_ROTRI_W +-body: | +- bb.0: +- $r4 = ROTRI_W $r5, 23 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2RI6 +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------------------------+-----------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------------------------+-----------------+--------------+--------------- +-# opcode | imm6 | rj | rd +-# ------------------------------------------------+-----------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_SLLI_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: slli.d $a0, $a1, 39 +-name: test_SLLI_D +-body: | +- bb.0: +- $r4 = SLLI_D $r5, 39 +-... +---- +-# CHECK-LABEL: test_SRLI_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srli.d $a0, $a1, 38 +-name: test_SRLI_D +-body: | +- bb.0: +- $r4 = SRLI_D $r5, 38 +-... +---- +-# CHECK-LABEL: test_SRAI_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srai.d $a0, $a1, 27 +-name: test_SRAI_D +-body: | +- bb.0: +- $r4 = SRAI_D $r5, 27 +-... +---- +-# CHECK-LABEL: test_ROTRI_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rotri.d $a0, $a1, 7 +-name: test_ROTRI_D +-body: | +- bb.0: +- $r4 = ROTRI_D $r5, 7 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2RI12 +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------+-----------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------+-----------------------------------+--------------+--------------- +-# opcode | imm12 | rj | rd +-# ------------------------------+-----------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_SLTI: +-# CHECK-ENC: 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: slti $a0, $a1, 235 +-name: test_SLTI +-body: | +- bb.0: +- $r4 = SLTI $r5, 235 +-... +---- +-# CHECK-LABEL: test_SLTUI: +-# CHECK-ENC: 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sltui $a0, $a1, 162 +-name: test_SLTUI +-body: | +- bb.0: +- $r4 = SLTUI $r5, 162 +-... +---- +-# CHECK-LABEL: test_ADDI_W: +-# CHECK-ENC: 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 1 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: addi.w $a0, $a1, 246 +-name: test_ADDI_W +-body: | +- bb.0: +- $r4 = ADDI_W $r5, 246 +-... +---- +-# CHECK-LABEL: test_ADDI_D: +-# CHECK-ENC: 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: addi.d $a0, $a1, 75 +-name: test_ADDI_D +-body: | +- bb.0: +- $r4 = ADDI_D $r5, 75 +-... +---- +-# CHECK-LABEL: test_LU52I_D: +-# CHECK-ENC: 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: lu52i.d $a0, $a1, 195 +-name: test_LU52I_D +-body: | +- bb.0: +- $r4 = LU52I_D $r5, 195 +-... +---- +-# CHECK-LABEL: test_ANDI: +-# CHECK-ENC: 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: andi $a0, $a1, 106 +-name: test_ANDI +-body: | +- bb.0: +- $r4 = ANDI $r5, 106 +-... +---- +-# CHECK-LABEL: test_ORI: +-# CHECK-ENC: 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ori $a0, $a1, 47 +-name: test_ORI +-body: | +- bb.0: +- $r4 = ORI $r5, 47 +-... +---- +-# CHECK-LABEL: test_XORI: +-# CHECK-ENC: 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: xori $a0, $a1, 99 +-name: test_XORI +-body: | +- bb.0: +- $r4 = XORI $r5, 99 +-... +---- +-# CHECK-LABEL: test_LD_B: +-# CHECK-ENC: 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.b $a0, $a1, 21 +-name: test_LD_B +-body: | +- bb.0: +- $r4 = LD_B $r5, 21 +-... +---- +-# CHECK-LABEL: test_LD_H: +-# CHECK-ENC: 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.h $a0, $a1, 80 +-name: test_LD_H +-body: | +- bb.0: +- $r4 = LD_H $r5, 80 +-... +---- +-# CHECK-LABEL: test_LD_W: +-# CHECK-ENC: 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.w $a0, $a1, 92 +-name: test_LD_W +-body: | +- bb.0: +- $r4 = LD_W $r5, 92 +-... +---- +-# CHECK-LABEL: test_LD_BU: +-# CHECK-ENC: 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.bu $a0, $a1, 150 +-name: test_LD_BU +-body: | +- bb.0: +- $r4 = LD_BU $r5, 150 +-... +---- +-# CHECK-LABEL: test_LD_HU: +-# CHECK-ENC: 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.hu $a0, $a1, 198 +-name: test_LD_HU +-body: | +- bb.0: +- $r4 = LD_HU $r5, 198 +-... +---- +-# CHECK-LABEL: test_LD_WU: +-# CHECK-ENC: 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ld.wu $a0, $a1, 31 +-name: test_LD_WU +-body: | +- bb.0: +- $r4 = LD_WU $r5, 31 +-... +---- +-# CHECK-LABEL: test_ST_B: +-# CHECK-ENC: 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: st.b $a0, $a1, 95 +-name: test_ST_B +-body: | +- bb.0: +- ST_B $r4, $r5, 95 +-... +---- +-# CHECK-LABEL: test_ST_H: +-# CHECK-ENC: 0 0 1 0 1 0 0 1 0 1 0 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: st.h $a0, $a1, 122 +-name: test_ST_H +-body: | +- bb.0: +- ST_H $r4, $r5, 122 +-... +---- +-# CHECK-LABEL: test_ST_W: +-# CHECK-ENC: 0 0 1 0 1 0 0 1 1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: st.w $a0, $a1, 175 +-name: test_ST_W +-body: | +- bb.0: +- ST_W $r4, $r5, 175 +-... +---- +-# CHECK-LABEL: test_ST_D: +-# CHECK-ENC: 0 0 1 0 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: st.d $a0, $a1, 60 +-name: test_ST_D +-body: | +- bb.0: +- ST_D $r4, $r5, 60 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2RI14 +-# ------------------------------------------------------------------------------------------------- +-# ------------------------+-----------------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------+-----------------------------------------+--------------+--------------- +-# opcode | imm14 | rj | rd +-# ------------------------+-----------------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_LDPTR_W: +-# CHECK-ENC: 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldptr.w $a0, $a1, 264 +-name: test_LDPTR_W +-body: | +- bb.0: +- $r4 = LDPTR_W $r5, 264 +-... +---- +-# CHECK-LABEL: test_LDPTR_D: +-# CHECK-ENC: 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldptr.d $a0, $a1, 224 +-name: test_LDPTR_D +-body: | +- bb.0: +- $r4 = LDPTR_D $r5, 224 +-... +---- +-# CHECK-LABEL: test_STPTR_W: +-# CHECK-ENC: 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stptr.w $a0, $a1, 348 +-name: test_STPTR_W +-body: | +- bb.0: +- STPTR_W $r4, $r5, 348 +-... +---- +-# CHECK-LABEL: test_STPTR_D: +-# CHECK-ENC: 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stptr.d $a0, $a1, 580 +-name: test_STPTR_D +-body: | +- bb.0: +- STPTR_D $r4, $r5, 580 +-... +---- +-# CHECK-LABEL: test_LL_W: +-# CHECK-ENC: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ll.w $a0, $a1, 972 +-name: test_LL_W +-body: | +- bb.0: +- $r4 = LL_W $r5, 972 +-... +---- +-# CHECK-LABEL: test_LL_D: +-# CHECK-ENC: 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ll.d $a0, $a1, 296 +-name: test_LL_D +-body: | +- bb.0: +- $r4 = LL_D $r5, 296 +-... +---- +-# CHECK-LABEL: test_SC_W: +-# CHECK-ENC: 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sc.w $a0, $a1, 384 +-name: test_SC_W +-body: | +- bb.0: +- $r4 = SC_W $r4, $r5, 384 +-... +---- +-# CHECK-LABEL: test_SC_D: +-# CHECK-ENC: 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sc.d $a0, $a1, 420 +-name: test_SC_D +-body: | +- bb.0: +- $r4 = SC_D $r4, $r5, 420 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 2RI16 +-# ------------------------------------------------------------------------------------------------- +-# ------------------+-----------------------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------+-----------------------------------------------+--------------+--------------- +-# opcode | imm16 | rj | rd +-# ------------------+-----------------------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_ADDU16I_D: +-# CHECK-ENC: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: addu16i.d $a0, $a1, 23 +-name: test_ADDU16I_D +-body: | +- bb.0: +- $r4 = ADDU16I_D $r5, 23 +-... +---- +-# CHECK-LABEL: test_JIRL: +-# CHECK-ENC: 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: jirl $a0, $a1, 196 +-name: test_JIRL +-body: | +- bb.0: +- $r4 = JIRL $r5, 196 +-... +---- +-# CHECK-LABEL: test_BEQ: +-# CHECK-ENC: 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: beq $a0, $a1, 784 +-name: test_BEQ +-body: | +- bb.0: +- BEQ $r4, $r5, 784 +-... +---- +-# CHECK-LABEL: test_BNE: +-# CHECK-ENC: 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: bne $a0, $a1, 76 +-name: test_BNE +-body: | +- bb.0: +- BNE $r4, $r5, 76 +-... +---- +-# CHECK-LABEL: test_BLT: +-# CHECK-ENC: 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: blt $a0, $a1, 492 +-name: test_BLT +-body: | +- bb.0: +- BLT $r4, $r5, 492 +-... +---- +-# CHECK-LABEL: test_BGE: +-# CHECK-ENC: 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: bge $a0, $a1, 48 +-name: test_BGE +-body: | +- bb.0: +- BGE $r4, $r5, 48 +-... +---- +-# CHECK-LABEL: test_BLTU: +-# CHECK-ENC: 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: bltu $a0, $a1, 68 +-name: test_BLTU +-body: | +- bb.0: +- BLTU $r4, $r5, 68 +-... +---- +-# CHECK-LABEL: test_BGEU: +-# CHECK-ENC: 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 +-# CHECK-ASM: bgeu $a0, $a1, 352 +-name: test_BGEU +-body: | +- bb.0: +- BGEU $r4, $r5, 352 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir +deleted file mode 100644 +index a1b97d563..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/3r.mir ++++ /dev/null +@@ -1,995 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 3R +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------------+--------------+--------------+--------------- +-# opcode | rk | rj | rd +-# ---------------------------------------------------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_ADD_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: add.w $a0, $a1, $a0 +-name: test_ADD_W +-body: | +- bb.0: +- $r4 = ADD_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_ADD_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: add.d $a0, $a1, $a0 +-name: test_ADD_D +-body: | +- bb.0: +- $r4 = ADD_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SUB_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sub.w $a0, $a1, $a0 +-name: test_SUB_W +-body: | +- bb.0: +- $r4 = SUB_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SUB_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sub.d $a0, $a1, $a0 +-name: test_SUB_D +-body: | +- bb.0: +- $r4 = SUB_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SLT: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: slt $a0, $a1, $a0 +-name: test_SLT +-body: | +- bb.0: +- $r4 = SLT $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SLTU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sltu $a0, $a1, $a0 +-name: test_SLTU +-body: | +- bb.0: +- $r4 = SLTU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MASKEQZ: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: maskeqz $a0, $a1, $a0 +-name: test_MASKEQZ +-body: | +- bb.0: +- $r4 = MASKEQZ $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MASKNEZ: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: masknez $a0, $a1, $a0 +-name: test_MASKNEZ +-body: | +- bb.0: +- $r4 = MASKNEZ $r5, $r4 +-... +---- +-# CHECK-LABEL: test_NOR: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: nor $a0, $a1, $a0 +-name: test_NOR +-body: | +- bb.0: +- $r4 = NOR $r5, $r4 +-... +---- +-# CHECK-LABEL: test_AND: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: and $a0, $a1, $a0 +-name: test_AND +-body: | +- bb.0: +- $r4 = AND $r5, $r4 +-... +---- +-# CHECK-LABEL: test_OR: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: or $a0, $a1, $a0 +-name: test_OR +-body: | +- bb.0: +- $r4 = OR $r5, $r4 +-... +---- +-# CHECK-LABEL: test_XOR: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: xor $a0, $a1, $a0 +-name: test_XOR +-body: | +- bb.0: +- $r4 = XOR $r5, $r4 +-... +---- +-# CHECK-LABEL: test_ORN: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: orn $a0, $a1, $a0 +-name: test_ORN +-body: | +- bb.0: +- $r4 = ORN $r5, $r4 +-... +---- +-# CHECK-LABEL: test_ANDN: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: andn $a0, $a1, $a0 +-name: test_ANDN +-body: | +- bb.0: +- $r4 = ANDN $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SLL_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sll.w $a0, $a1, $a0 +-name: test_SLL_W +-body: | +- bb.0: +- $r4 = SLL_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SRL_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srl.w $a0, $a1, $a0 +-name: test_SRL_W +-body: | +- bb.0: +- $r4 = SRL_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SRA_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sra.w $a0, $a1, $a0 +-name: test_SRA_W +-body: | +- bb.0: +- $r4 = SRA_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SLL_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sll.d $a0, $a1, $a0 +-name: test_SLL_D +-body: | +- bb.0: +- $r4 = SLL_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SRL_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: srl.d $a0, $a1, $a0 +-name: test_SRL_D +-body: | +- bb.0: +- $r4 = SRL_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_SRA_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: sra.d $a0, $a1, $a0 +-name: test_SRA_D +-body: | +- bb.0: +- $r4 = SRA_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_ROTR_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rotr.w $a0, $a1, $a0 +-name: test_ROTR_W +-body: | +- bb.0: +- $r4 = ROTR_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_ROTR_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: rotr.d $a0, $a1, $a0 +-name: test_ROTR_D +-body: | +- bb.0: +- $r4 = ROTR_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MUL_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mul.w $a0, $a1, $a0 +-name: test_MUL_W +-body: | +- bb.0: +- $r4 = MUL_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULH_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulh.w $a0, $a1, $a0 +-name: test_MULH_W +-body: | +- bb.0: +- $r4 = MULH_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULH_WU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulh.wu $a0, $a1, $a0 +-name: test_MULH_WU +-body: | +- bb.0: +- $r4 = MULH_WU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MUL_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mul.d $a0, $a1, $a0 +-name: test_MUL_D +-body: | +- bb.0: +- $r4 = MUL_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULH_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulh.d $a0, $a1, $a0 +-name: test_MULH_D +-body: | +- bb.0: +- $r4 = MULH_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULH_DU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulh.du $a0, $a1, $a0 +-name: test_MULH_DU +-body: | +- bb.0: +- $r4 = MULH_DU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULW_D_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulw.d.w $a0, $a1, $a0 +-name: test_MULW_D_W +-body: | +- bb.0: +- $r4 = MULW_D_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MULW_D_WU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mulw.d.wu $a0, $a1, $a0 +-name: test_MULW_D_WU +-body: | +- bb.0: +- $r4 = MULW_D_WU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_DIV_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: div.w $a0, $a1, $a0 +-name: test_DIV_W +-body: | +- bb.0: +- $r4 = DIV_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MOD_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mod.w $a0, $a1, $a0 +-name: test_MOD_W +-body: | +- bb.0: +- $r4 = MOD_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_DIV_WU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: div.wu $a0, $a1, $a0 +-name: test_DIV_WU +-body: | +- bb.0: +- $r4 = DIV_WU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MOD_WU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mod.wu $a0, $a1, $a0 +-name: test_MOD_WU +-body: | +- bb.0: +- $r4 = MOD_WU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_DIV_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: div.d $a0, $a1, $a0 +-name: test_DIV_D +-body: | +- bb.0: +- $r4 = DIV_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MOD_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mod.d $a0, $a1, $a0 +-name: test_MOD_D +-body: | +- bb.0: +- $r4 = MOD_D $r5, $r4 +-... +---- +-# CHECK-LABEL: test_DIV_DU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: div.du $a0, $a1, $a0 +-name: test_DIV_DU +-body: | +- bb.0: +- $r4 = DIV_DU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_MOD_DU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: mod.du $a0, $a1, $a0 +-name: test_MOD_DU +-body: | +- bb.0: +- $r4 = MOD_DU $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRC_W_B_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crc.w.b.w $a0, $a1, $a0 +-name: test_CRC_W_B_W +-body: | +- bb.0: +- $r4 = CRC_W_B_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRC_W_H_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crc.w.h.w $a0, $a1, $a0 +-name: test_CRC_W_H_W +-body: | +- bb.0: +- $r4 = CRC_W_H_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRC_W_W_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crc.w.w.w $a0, $a1, $a0 +-name: test_CRC_W_W_W +-body: | +- bb.0: +- $r4 = CRC_W_W_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRC_W_D_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crc.w.d.w $a0, $a1, $a0 +-name: test_CRC_W_D_W +-body: | +- bb.0: +- $r4 = CRC_W_D_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRCC_W_B_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crcc.w.b.w $a0, $a1, $a0 +-name: test_CRCC_W_B_W +-body: | +- bb.0: +- $r4 = CRCC_W_B_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRCC_W_H_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crcc.w.h.w $a0, $a1, $a0 +-name: test_CRCC_W_H_W +-body: | +- bb.0: +- $r4 = CRCC_W_H_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRCC_W_W_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crcc.w.w.w $a0, $a1, $a0 +-name: test_CRCC_W_W_W +-body: | +- bb.0: +- $r4 = CRCC_W_W_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_CRCC_W_D_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: crcc.w.d.w $a0, $a1, $a0 +-name: test_CRCC_W_D_W +-body: | +- bb.0: +- $r4 = CRCC_W_D_W $r5, $r4 +-... +---- +-# CHECK-LABEL: test_AMSWAP_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amswap_db.w $a0, $a1, $a2 +-name: test_AMSWAP_DB_W +-body: | +- bb.0: +- $r4 = AMSWAP_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMSWAP_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amswap_db.d $a0, $a1, $a2 +-name: test_AMSWAP_DB_D +-body: | +- bb.0: +- $r4 = AMSWAP_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMADD_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amadd_db.w $a0, $a1, $a2 +-name: test_AMADD_DB_W +-body: | +- bb.0: +- $r4 = AMADD_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMADD_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amadd_db.d $a0, $a1, $a2 +-name: test_AMADD_DB_D +-body: | +- bb.0: +- $r4 = AMADD_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMAND_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amand_db.w $a0, $a1, $a2 +-name: test_AMAND_DB_W +-body: | +- bb.0: +- $r4 = AMAND_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMAND_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amand_db.d $a0, $a1, $a2 +-name: test_AMAND_DB_D +-body: | +- bb.0: +- $r4 = AMAND_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMOR_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amor_db.w $a0, $a1, $a2 +-name: test_AMOR_DB_W +-body: | +- bb.0: +- $r4 = AMOR_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMOR_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amor_db.d $a0, $a1, $a2 +-name: test_AMOR_DB_D +-body: | +- bb.0: +- $r4 = AMOR_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMXOR_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amxor_db.w $a0, $a1, $a2 +-name: test_AMXOR_DB_W +-body: | +- bb.0: +- $r4 = AMXOR_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMXOR_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amxor_db.d $a0, $a1, $a2 +-name: test_AMXOR_DB_D +-body: | +- bb.0: +- $r4 = AMXOR_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax_db.w $a0, $a1, $a2 +-name: test_AMMAX_DB_W +-body: | +- bb.0: +- $r4 = AMMAX_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax_db.d $a0, $a1, $a2 +-name: test_AMMAX_DB_D +-body: | +- bb.0: +- $r4 = AMMAX_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_DB_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin_db.w $a0, $a1, $a2 +-name: test_AMMIN_DB_W +-body: | +- bb.0: +- $r4 = AMMIN_DB_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_DB_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin_db.d $a0, $a1, $a2 +-name: test_AMMIN_DB_D +-body: | +- bb.0: +- $r4 = AMMIN_DB_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_DB_WU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax_db.wu $a0, $a1, $a2 +-name: test_AMMAX_DB_WU +-body: | +- bb.0: +- $r4 = AMMAX_DB_WU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_DB_DU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax_db.du $a0, $a1, $a2 +-name: test_AMMAX_DB_DU +-body: | +- bb.0: +- $r4 = AMMAX_DB_DU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_DB_WU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin_db.wu $a0, $a1, $a2 +-name: test_AMMIN_DB_WU +-body: | +- bb.0: +- $r4 = AMMIN_DB_WU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_DB_DU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin_db.du $a0, $a1, $a2 +-name: test_AMMIN_DB_DU +-body: | +- bb.0: +- $r4 = AMMIN_DB_DU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMSWAP_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amswap.w $a0, $a1, $a2 +-name: test_AMSWAP_W +-body: | +- bb.0: +- $r4 = AMSWAP_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMSWAP_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amswap.d $a0, $a1, $a2 +-name: test_AMSWAP_D +-body: | +- bb.0: +- $r4 = AMSWAP_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMADD_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amadd.w $a0, $a1, $a2 +-name: test_AMADD_W +-body: | +- bb.0: +- $r4 = AMADD_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMADD_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amadd.d $a0, $a1, $a2 +-name: test_AMADD_D +-body: | +- bb.0: +- $r4 = AMADD_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMAND_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amand.w $a0, $a1, $a2 +-name: test_AMAND_W +-body: | +- bb.0: +- $r4 = AMAND_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMAND_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amand.d $a0, $a1, $a2 +-name: test_AMAND_D +-body: | +- bb.0: +- $r4 = AMAND_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMOR_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amor.w $a0, $a1, $a2 +-name: test_AMOR_W +-body: | +- bb.0: +- $r4 = AMOR_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMOR_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amor.d $a0, $a1, $a2 +-name: test_AMOR_D +-body: | +- bb.0: +- $r4 = AMOR_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMXOR_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amxor.w $a0, $a1, $a2 +-name: test_AMXOR_W +-body: | +- bb.0: +- $r4 = AMXOR_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMXOR_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: amxor.d $a0, $a1, $a2 +-name: test_AMXOR_D +-body: | +- bb.0: +- $r4 = AMXOR_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax.w $a0, $a1, $a2 +-name: test_AMMAX_W +-body: | +- bb.0: +- $r4 = AMMAX_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax.d $a0, $a1, $a2 +-name: test_AMMAX_D +-body: | +- bb.0: +- $r4 = AMMAX_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin.w $a0, $a1, $a2 +-name: test_AMMIN_W +-body: | +- bb.0: +- $r4 = AMMIN_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin.d $a0, $a1, $a2 +-name: test_AMMIN_D +-body: | +- bb.0: +- $r4 = AMMIN_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_WU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax.wu $a0, $a1, $a2 +-name: test_AMMAX_WU +-body: | +- bb.0: +- $r4 = AMMAX_WU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMAX_DU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammax.du $a0, $a1, $a2 +-name: test_AMMAX_DU +-body: | +- bb.0: +- $r4 = AMMAX_DU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_WU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin.wu $a0, $a1, $a2 +-name: test_AMMIN_WU +-body: | +- bb.0: +- $r4 = AMMIN_WU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_AMMIN_DU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 +-# CHECK-ASM: ammin.du $a0, $a1, $a2 +-name: test_AMMIN_DU +-body: | +- bb.0: +- $r4 = AMMIN_DU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.b $a0, $a1, $a2 +-name: test_LDX_B +-body: | +- bb.0: +- $r4 = LDX_B $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.h $a0, $a1, $a2 +-name: test_LDX_H +-body: | +- bb.0: +- $r4 = LDX_H $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.w $a0, $a1, $a2 +-name: test_LDX_W +-body: | +- bb.0: +- $r4 = LDX_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.d $a0, $a1, $a2 +-name: test_LDX_D +-body: | +- bb.0: +- $r4 = LDX_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_BU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.bu $a0, $a1, $a2 +-name: test_LDX_BU +-body: | +- bb.0: +- $r4 = LDX_BU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_HU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.hu $a0, $a1, $a2 +-name: test_LDX_HU +-body: | +- bb.0: +- $r4 = LDX_HU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDX_WU: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldx.wu $a0, $a1, $a2 +-name: test_LDX_WU +-body: | +- bb.0: +- $r4 = LDX_WU $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDGT_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldgt.b $a0, $a1, $a2 +-name: test_LDGT_B +-body: | +- bb.0: +- $r4 = LDGT_B $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDGT_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldgt.h $a0, $a1, $a2 +-name: test_LDGT_H +-body: | +- bb.0: +- $r4 = LDGT_H $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDGT_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldgt.w $a0, $a1, $a2 +-name: test_LDGT_W +-body: | +- bb.0: +- $r4 = LDGT_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDGT_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldgt.d $a0, $a1, $a2 +-name: test_LDGT_D +-body: | +- bb.0: +- $r4 = LDGT_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDLE_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldle.b $a0, $a1, $a2 +-name: test_LDLE_B +-body: | +- bb.0: +- $r4 = LDLE_B $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDLE_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldle.h $a0, $a1, $a2 +-name: test_LDLE_H +-body: | +- bb.0: +- $r4 = LDLE_H $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDLE_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldle.w $a0, $a1, $a2 +-name: test_LDLE_W +-body: | +- bb.0: +- $r4 = LDLE_W $r5, $r6 +-... +---- +-# CHECK-LABEL: test_LDLE_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: ldle.d $a0, $a1, $a2 +-name: test_LDLE_D +-body: | +- bb.0: +- $r4 = LDLE_D $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STX_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stx.b $a0, $a1, $a2 +-name: test_STX_B +-body: | +- bb.0: +- STX_B $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STX_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stx.h $a0, $a1, $a2 +-name: test_STX_H +-body: | +- bb.0: +- STX_H $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STX_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stx.w $a0, $a1, $a2 +-name: test_STX_W +-body: | +- bb.0: +- STX_W $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STX_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stx.d $a0, $a1, $a2 +-name: test_STX_D +-body: | +- bb.0: +- STX_D $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STGT_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stgt.b $a0, $a1, $a2 +-name: test_STGT_B +-body: | +- bb.0: +- STGT_B $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STGT_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stgt.h $a0, $a1, $a2 +-name: test_STGT_H +-body: | +- bb.0: +- STGT_H $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STGT_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stgt.w $a0, $a1, $a2 +-name: test_STGT_W +-body: | +- bb.0: +- STGT_W $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STGT_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stgt.d $a0, $a1, $a2 +-name: test_STGT_D +-body: | +- bb.0: +- STGT_D $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STLE_B: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stle.b $a0, $a1, $a2 +-name: test_STLE_B +-body: | +- bb.0: +- STLE_B $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STLE_H: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stle.h $a0, $a1, $a2 +-name: test_STLE_H +-body: | +- bb.0: +- STLE_H $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STLE_W: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stle.w $a0, $a1, $a2 +-name: test_STLE_W +-body: | +- bb.0: +- STLE_W $r4, $r5, $r6 +-... +---- +-# CHECK-LABEL: test_STLE_D: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: stle.d $a0, $a1, $a2 +-name: test_STLE_D +-body: | +- bb.0: +- STLE_D $r4, $r5, $r6 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir +deleted file mode 100644 +index c86e14189..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/3ri.mir ++++ /dev/null +@@ -1,69 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 3RI2 +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------+-----+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------+-----+--------------+--------------+--------------- +-# opcode |imm2 | rk | rj | rd +-# ---------------------------------------------+-----+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_ALSL_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: alsl.w $a0, $a1, $a2, 4 +-name: test_ALSL_W +-body: | +- bb.0: +- $r4 = ALSL_W $r5, $r6, 4 +-... +---- +-# CHECK-LABEL: test_ALSL_WU: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: alsl.wu $a0, $a1, $a2, 2 +-name: test_ALSL_WU +-body: | +- bb.0: +- $r4 = ALSL_WU $r5, $r6, 2 +-... +---- +-# CHECK-LABEL: test_ALSL_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: alsl.d $a0, $a1, $a2, 4 +-name: test_ALSL_D +-body: | +- bb.0: +- $r4 = ALSL_D $r5, $r6, 4 +-... +---- +-# CHECK-LABEL: test_BYTEPICK_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bytepick.w $a0, $a1, $a2, 0 +-name: test_BYTEPICK_W +-body: | +- bb.0: +- $r4 = BYTEPICK_W $r5, $r6, 0 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: 3RI3 +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------------------+--------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------------------+--------+--------------+--------------+--------------- +-# opcode | imm3 | rk | rj | rd +-# ------------------------------------------+--------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_BYTEPICK_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bytepick.d $a0, $a1, $a2, 4 +-name: test_BYTEPICK_D +-body: | +- bb.0: +- $r4 = BYTEPICK_D $r5, $r6, 4 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll +new file mode 100644 +index 000000000..c5b08dbd4 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/align.ll +@@ -0,0 +1,8 @@ ++; RUN: llc -mtriple=loongarch64 %s -o - | FileCheck %s ++ ++define void @foo() { ++;CHECK: .p2align 2 ++;CHECK: foo: ++entry: ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll +new file mode 100644 +index 000000000..d1d0c0bc4 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic-operand-imm0.ll +@@ -0,0 +1,17 @@ ++; Test that the last immediate 0 operand of amtomic instruction is printed ++ ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define void @test_i32(i32* %dst, i32 %val) { ++; CHECK: ammax_db.wu $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG3:[0-9]+]], 0 ++entry: ++ %a = atomicrmw umax i32* %dst, i32 %val monotonic ++ ret void ++} ++ ++define void @test_i64(i64* %dst, i64 %val) { ++; CHECK: ammax_db.du $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG3:[0-9]+]], 0 ++entry: ++ %a = atomicrmw umax i64* %dst, i64 %val monotonic ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll +new file mode 100644 +index 000000000..d5c3e0dad +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_16_8.ll +@@ -0,0 +1,809 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -mtriple=loongarch64 -o - %s | FileCheck %s ++ ++ ++define void @umax_8(i8* %ptr) { ++; CHECK-LABEL: umax_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: sltu $r13, $r14, $r5 ++; CHECK-NEXT: masknez $r11, $r14, $r13 ++; CHECK-NEXT: maskeqz $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB0_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umax i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @umax_16(i16* %ptr) { ++; CHECK-LABEL: umax_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB1_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: sltu $r13, $r14, $r5 ++; CHECK-NEXT: masknez $r11, $r14, $r13 ++; CHECK-NEXT: maskeqz $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB1_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umax i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++define void @max_8(i8* %ptr) { ++; CHECK-LABEL: max_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB2_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: slt $r13, $r14, $r5 ++; CHECK-NEXT: masknez $r11, $r14, $r13 ++; CHECK-NEXT: maskeqz $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB2_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw max i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @max_16(i16* %ptr) { ++; CHECK-LABEL: max_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB3_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: slt $r13, $r14, $r5 ++; CHECK-NEXT: masknez $r11, $r14, $r13 ++; CHECK-NEXT: maskeqz $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB3_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw max i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @umin_8(i8* %ptr) { ++; CHECK-LABEL: umin_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB4_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: sltu $r13, $r14, $r5 ++; CHECK-NEXT: maskeqz $r11, $r14, $r13 ++; CHECK-NEXT: masknez $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB4_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umin i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @umin_16(i16* %ptr) { ++; CHECK-LABEL: umin_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB5_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: sltu $r13, $r14, $r5 ++; CHECK-NEXT: maskeqz $r11, $r14, $r13 ++; CHECK-NEXT: masknez $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB5_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umin i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++define void @min_8(i8* %ptr) { ++; CHECK-LABEL: min_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB6_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: slt $r13, $r14, $r5 ++; CHECK-NEXT: maskeqz $r11, $r14, $r13 ++; CHECK-NEXT: masknez $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB6_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw min i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @min_16(i16* %ptr) { ++; CHECK-LABEL: min_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB7_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r14, $r10, $r7 ++; CHECK-NEXT: and $r5, $r5, $r7 ++; CHECK-NEXT: slt $r13, $r14, $r5 ++; CHECK-NEXT: maskeqz $r11, $r14, $r13 ++; CHECK-NEXT: masknez $r13, $r5, $r13 ++; CHECK-NEXT: or $r11, $r11, $r13 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB7_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw min i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @or_8(i8* %ptr) { ++; CHECK-LABEL: or_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB8_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: or $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB8_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw or i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @or_16(i16* %ptr) { ++; CHECK-LABEL: or_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB9_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: or $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB9_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw or i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @add_8(i8* %ptr) { ++; CHECK-LABEL: add_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB10_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: add.w $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB10_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw add i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @add_16(i16* %ptr) { ++; CHECK-LABEL: add_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB11_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: add.w $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB11_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw add i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @sub_8(i8* %ptr) { ++; CHECK-LABEL: sub_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: sub.w $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB12_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw sub i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @sub_16(i16* %ptr) { ++; CHECK-LABEL: sub_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB13_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: sub.w $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB13_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw sub i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @and_8(i8* %ptr) { ++; CHECK-LABEL: and_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB14_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB14_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw and i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @and_16(i16* %ptr) { ++; CHECK-LABEL: and_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB15_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB15_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw and i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @nand_8(i8* %ptr) { ++; CHECK-LABEL: nand_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB16_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r10, $r5 ++; CHECK-NEXT: nor $r11, $zero, $r11 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB16_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw nand i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @nand_16(i16* %ptr) { ++; CHECK-LABEL: nand_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB17_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r10, $r5 ++; CHECK-NEXT: nor $r11, $zero, $r11 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB17_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw nand i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @xor_8(i8* %ptr) { ++; CHECK-LABEL: xor_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB18_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: xor $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB18_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xor i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @xor_16(i16* %ptr) { ++; CHECK-LABEL: xor_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB19_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: xor $r11, $r10, $r5 ++; CHECK-NEXT: and $r11, $r11, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB19_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xor i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++ ++define void @xchg_8(i8* %ptr) { ++; CHECK-LABEL: xchg_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r7, $zero, 255 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB20_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r5, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB20_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.b $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xchg i8* %ptr, i8 100 seq_cst ++ ret void ++} ++ ++define void @xchg_16(i16* %ptr) { ++; CHECK-LABEL: xchg_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: addi.d $r6, $zero, -4 ++; CHECK-NEXT: and $r6, $r4, $r6 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r7, 15 ++; CHECK-NEXT: ori $r7, $r7, 4095 ++; CHECK-NEXT: sll.w $r7, $r7, $r4 ++; CHECK-NEXT: nor $r8, $zero, $r7 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB21_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r10, $r6, 0 ++; CHECK-NEXT: and $r11, $r5, $r7 ++; CHECK-NEXT: and $r12, $r10, $r8 ++; CHECK-NEXT: or $r12, $r12, $r11 ++; CHECK-NEXT: sc.w $r12, $r6, 0 ++; CHECK-NEXT: beq $r12, $zero, .LBB21_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: and $r9, $r10, $r7 ++; CHECK-NEXT: srl.w $r9, $r9, $r4 ++; CHECK-NEXT: ext.w.h $r9, $r9 ++; CHECK-NEXT: # %bb.3: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xchg i16* %ptr, i16 100 seq_cst ++ ret void ++} ++ ++define void @cmpxchg_8(i8* %ptr) { ++; CHECK-LABEL: cmpxchg_8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 1 ++; CHECK-NEXT: ori $r6, $zero, 100 ++; CHECK-NEXT: addi.d $r7, $zero, -4 ++; CHECK-NEXT: and $r7, $r4, $r7 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: ori $r8, $zero, 255 ++; CHECK-NEXT: sll.w $r8, $r8, $r4 ++; CHECK-NEXT: nor $r9, $zero, $r8 ++; CHECK-NEXT: andi $r6, $r6, 255 ++; CHECK-NEXT: sll.w $r6, $r6, $r4 ++; CHECK-NEXT: andi $r5, $r5, 255 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB22_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r11, $r7, 0 ++; CHECK-NEXT: and $r12, $r11, $r8 ++; CHECK-NEXT: bne $r12, $r6, .LBB22_3 ++; CHECK-NEXT: # %bb.2: # in Loop: Header=BB22_1 Depth=1 ++; CHECK-NEXT: and $r11, $r11, $r9 ++; CHECK-NEXT: or $r11, $r11, $r5 ++; CHECK-NEXT: sc.w $r11, $r7, 0 ++; CHECK-NEXT: beq $r11, $zero, .LBB22_1 ++; CHECK-NEXT: .LBB22_3: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: srl.w $r10, $r12, $r4 ++; CHECK-NEXT: ext.w.b $r10, $r10 ++; CHECK-NEXT: # %bb.4: ++; CHECK-NEXT: jr $ra ++ %ret = cmpxchg i8* %ptr, i8 100, i8 1 seq_cst seq_cst ++ ret void ++} ++ ++define void @cmpxchg_16(i16* %ptr) { ++; CHECK-LABEL: cmpxchg_16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 1 ++; CHECK-NEXT: ori $r6, $zero, 100 ++; CHECK-NEXT: addi.d $r7, $zero, -4 ++; CHECK-NEXT: and $r7, $r4, $r7 ++; CHECK-NEXT: andi $r4, $r4, 3 ++; CHECK-NEXT: slli.w $r4, $r4, 3 ++; CHECK-NEXT: lu12i.w $r8, 15 ++; CHECK-NEXT: ori $r8, $r8, 4095 ++; CHECK-NEXT: sll.w $r9, $r8, $r4 ++; CHECK-NEXT: nor $r10, $zero, $r9 ++; CHECK-NEXT: and $r6, $r6, $r8 ++; CHECK-NEXT: sll.w $r6, $r6, $r4 ++; CHECK-NEXT: and $r5, $r5, $r8 ++; CHECK-NEXT: sll.w $r5, $r5, $r4 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB23_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r11, $r7, 0 ++; CHECK-NEXT: and $r12, $r11, $r9 ++; CHECK-NEXT: bne $r12, $r6, .LBB23_3 ++; CHECK-NEXT: # %bb.2: # in Loop: Header=BB23_1 Depth=1 ++; CHECK-NEXT: and $r11, $r11, $r10 ++; CHECK-NEXT: or $r11, $r11, $r5 ++; CHECK-NEXT: sc.w $r11, $r7, 0 ++; CHECK-NEXT: beq $r11, $zero, .LBB23_1 ++; CHECK-NEXT: .LBB23_3: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: srl.w $r8, $r12, $r4 ++; CHECK-NEXT: ext.w.h $r8, $r8 ++; CHECK-NEXT: # %bb.4: ++; CHECK-NEXT: jr $ra ++ %ret = cmpxchg i16* %ptr, i16 100, i16 1 seq_cst seq_cst ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll +new file mode 100644 +index 000000000..ce400fd43 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/atomic_64_32.ll +@@ -0,0 +1,327 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -mtriple=loongarch64 -o - %s | FileCheck %s ++ ++ ++define void @umax_32(i32* %ptr) { ++; CHECK-LABEL: umax_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammax_db.wu $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umax i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @umax_64(i64* %ptr) { ++; CHECK-LABEL: umax_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB1_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammax_db.du $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umax i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++define void @max_32(i32* %ptr) { ++; CHECK-LABEL: max_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB2_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammax_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw max i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @max_64(i64* %ptr) { ++; CHECK-LABEL: max_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB3_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammax_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw max i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @umin_32(i32* %ptr) { ++; CHECK-LABEL: umin_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB4_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammin_db.wu $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umin i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @umin_64(i64* %ptr) { ++; CHECK-LABEL: umin_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB5_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammin_db.du $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw umin i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++define void @min_32(i32* %ptr) { ++; CHECK-LABEL: min_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB6_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammin_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw min i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @min_64(i64* %ptr) { ++; CHECK-LABEL: min_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB7_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ammin_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw min i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @or_32(i32* %ptr) { ++; CHECK-LABEL: or_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB8_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amor_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw or i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @or_64(i64* %ptr) { ++; CHECK-LABEL: or_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB9_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amor_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw or i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @add_32(i32* %ptr) { ++; CHECK-LABEL: add_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB10_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amadd_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw add i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @add_64(i64* %ptr) { ++; CHECK-LABEL: add_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB11_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amadd_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw add i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @sub_32(i32* %ptr) { ++; CHECK-LABEL: sub_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: sub.w $r7, $zero, $r5 ++; CHECK-NEXT: amadd_db.w $r6, $r7, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw sub i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @sub_64(i64* %ptr) { ++; CHECK-LABEL: sub_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB13_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: sub.d $r7, $zero, $r5 ++; CHECK-NEXT: amadd_db.d $r6, $r7, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw sub i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @and_32(i32* %ptr) { ++; CHECK-LABEL: and_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB14_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amand_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw and i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @and_64(i64* %ptr) { ++; CHECK-LABEL: and_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB15_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amand_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw and i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @nand_32(i32* %ptr) { ++; CHECK-LABEL: nand_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB16_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r6, $r4, 0 ++; CHECK-NEXT: and $r7, $r6, $r5 ++; CHECK-NEXT: nor $r7, $zero, $r7 ++; CHECK-NEXT: sc.w $r7, $r4, 0 ++; CHECK-NEXT: beq $r7, $zero, .LBB16_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw nand i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @nand_64(i64* %ptr) { ++; CHECK-LABEL: nand_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB17_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.d $r6, $r4, 0 ++; CHECK-NEXT: and $r7, $r6, $r5 ++; CHECK-NEXT: nor $r7, $zero, $r7 ++; CHECK-NEXT: sc.d $r7, $r4, 0 ++; CHECK-NEXT: beq $r7, $zero, .LBB17_1 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw nand i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @xor_32(i32* %ptr) { ++; CHECK-LABEL: xor_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB18_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amxor_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xor i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @xor_64(i64* %ptr) { ++; CHECK-LABEL: xor_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB19_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amxor_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xor i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++ ++define void @xchg_32(i32* %ptr) { ++; CHECK-LABEL: xchg_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 100 ++; CHECK-NEXT: .LBB20_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amswap_db.w $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xchg i32* %ptr, i32 100 seq_cst ++ ret void ++} ++ ++define void @xchg_64(i64* %ptr) { ++; CHECK-LABEL: xchg_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 100 ++; CHECK-NEXT: .LBB21_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: amswap_db.d $r6, $r5, $r4, 0 ++; CHECK-NEXT: # %bb.2: ++; CHECK-NEXT: jr $ra ++ %ret = atomicrmw xchg i64* %ptr, i64 100 seq_cst ++ ret void ++} ++ ++define void @cmpxchg_32(i32* %ptr) { ++; CHECK-LABEL: cmpxchg_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r5, $zero, 1 ++; CHECK-NEXT: ori $r6, $zero, 100 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB22_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.w $r7, $r4, 0 ++; CHECK-NEXT: bne $r7, $r6, .LBB22_3 ++; CHECK-NEXT: # %bb.2: # in Loop: Header=BB22_1 Depth=1 ++; CHECK-NEXT: move $r8, $r5 ++; CHECK-NEXT: sc.w $r8, $r4, 0 ++; CHECK-NEXT: beq $r8, $zero, .LBB22_1 ++; CHECK-NEXT: .LBB22_3: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: jr $ra ++ %ret = cmpxchg i32* %ptr, i32 100, i32 1 seq_cst seq_cst ++ ret void ++} ++ ++define void @cmpxchg_64(i64* %ptr) { ++; CHECK-LABEL: cmpxchg_64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r5, $zero, 1 ++; CHECK-NEXT: addi.d $r6, $zero, 100 ++; CHECK-NEXT: dbar 0 ++; CHECK-NEXT: .LBB23_1: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: ll.d $r7, $r4, 0 ++; CHECK-NEXT: bne $r7, $r6, .LBB23_3 ++; CHECK-NEXT: # %bb.2: # in Loop: Header=BB23_1 Depth=1 ++; CHECK-NEXT: move $r8, $r5 ++; CHECK-NEXT: sc.d $r8, $r4, 0 ++; CHECK-NEXT: beq $r8, $zero, .LBB23_1 ++; CHECK-NEXT: .LBB23_3: ++; CHECK-NEXT: dbar 1792 ++; CHECK-NEXT: jr $ra ++ %ret = cmpxchg i64* %ptr, i64 100, i64 1 seq_cst seq_cst ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll +new file mode 100644 +index 000000000..cfc30b3a7 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/bss.ll +@@ -0,0 +1,5 @@ ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++; CHECK: .section .bss,"aw",@nobits ++; CHECK: .globl a ++@a = global i32 0, align 4 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll +new file mode 100644 +index 000000000..d6c8e72f2 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/builtins-loongarch-base.ll +@@ -0,0 +1,752 @@ ++; Test the base intrinsics. ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define void @cpucfg() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %u32_a = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i32 @llvm.loongarch.cpucfg(i32 %0) ++ store i32 %1, i32* %u32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.cpucfg(i32) ++ ++; CHECK-LABEL: cpucfg: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: cpucfg $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @csrrd_w() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %0 = call i32 @llvm.loongarch.csrrd.w(i32 1) ++ store i32 %0, i32* %u32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.csrrd.w(i32) ++ ++; CHECK-LABEL: csrrd_w: ++; CHECK: csrrd $r[[REG:[0-9]+]], 1 ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @csrrd_d() { ++entry: ++ %u64_r = alloca i64, align 8 ++ %0 = call i64 @llvm.loongarch.csrrd.d(i64 1) ++ store i64 %0, i64* %u64_r, align 8 ++ ret void ++} ++ ++declare i64 @llvm.loongarch.csrrd.d(i64) ++ ++; CHECK-LABEL: csrrd_d: ++; CHECK: csrrd $r[[REG:[0-9]+]], 1 ++; CHECK: st.d $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @csrwr_w() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %u32_a = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i32 @llvm.loongarch.csrwr.w(i32 %0, i32 1) ++ store i32 %1, i32* %u32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.csrwr.w(i32, i32) ++ ++; CHECK-LABEL: csrwr_w: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: csrwr $r[[REG:[0-9]+]], 1 ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @csrwr_d() { ++entry: ++ %u64_r = alloca i64, align 8 ++ %u64_a = alloca i64, align 8 ++ %0 = load i64, i64* %u64_a, align 8 ++ %1 = call i64 @llvm.loongarch.csrwr.d(i64 %0, i64 1) ++ store i64 %1, i64* %u64_r, align 8 ++ ret void ++} ++ ++declare i64 @llvm.loongarch.csrwr.d(i64, i64) ++ ++; CHECK-LABEL: csrwr_d: ++; CHECK: ld.d $r[[REG:[0-9]+]], $sp, 0 ++; CHECK: csrwr $r[[REG:[0-9]+]], 1 ++; CHECK: st.d $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @csrxchg_w() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %u32_a = alloca i32, align 4 ++ %u32_b = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = load i32, i32* %u32_b, align 4 ++ %2 = call i32 @llvm.loongarch.csrxchg.w(i32 %0, i32 %1, i32 1) ++ store i32 %2, i32* %u32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.csrxchg.w(i32, i32, i32) ++ ++; CHECK-LABEL: csrxchg_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 ++; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: csrxchg $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], 1 ++; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @csrxchg_d() { ++entry: ++ %u64_r = alloca i64, align 8 ++ %u64_a = alloca i64, align 8 ++ %u64_b = alloca i64, align 8 ++ %0 = load i64, i64* %u64_a, align 8 ++ %1 = load i64, i64* %u64_b, align 8 ++ %2 = call i64 @llvm.loongarch.csrxchg.d(i64 %0, i64 %1, i64 1) ++ store i64 %2, i64* %u64_r, align 8 ++ ret void ++} ++ ++declare i64 @llvm.loongarch.csrxchg.d(i64, i64, i64) ++ ++; CHECK-LABEL: csrxchg_d: ++; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 16 ++; CHECK: csrxchg $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], 1 ++; CHECK: st.d $r[[REG1:[0-9]+]], $sp, 24 ++; CHECK: jr $ra ++; ++ ++define void @iocsrrd_b() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u8_r = alloca i8, align 1 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i32 @llvm.loongarch.iocsrrd.b(i32 %0) ++ %conv = trunc i32 %1 to i8 ++ store i8 %conv, i8* %u8_r, align 1 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.iocsrrd.b(i32) ++ ++; CHECK-LABEL: iocsrrd_b: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: iocsrrd.b $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: st.b $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @iocsrrd_h() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u16_r = alloca i16, align 2 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i32 @llvm.loongarch.iocsrrd.h(i32 %0) ++ %conv = trunc i32 %1 to i16 ++ store i16 %conv, i16* %u16_r, align 2 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.iocsrrd.h(i32) ++ ++; CHECK-LABEL: iocsrrd_h: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: iocsrrd.h $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: st.h $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @iocsrrd_w() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %u32_a = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i32 @llvm.loongarch.iocsrrd.w(i32 %0) ++ store i32 %1, i32* %u32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.iocsrrd.w(i32) ++ ++; CHECK-LABEL: iocsrrd_w: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: iocsrrd.w $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @iocsrrd_d() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u64_r = alloca i64, align 8 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = call i64 @llvm.loongarch.iocsrrd.d(i32 %0) ++ store i64 %1, i64* %u64_r, align 8 ++ ret void ++} ++ ++declare i64 @llvm.loongarch.iocsrrd.d(i32) ++ ++; CHECK-LABEL: iocsrrd_d: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: iocsrrd.d $r[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: st.d $r[[REG:[0-9]+]], $sp, 0 ++; CHECK: jr $ra ++; ++ ++define void @iocsrwr_b() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u8_a = alloca i8, align 1 ++ %0 = load i8, i8* %u8_a, align 1 ++ %conv = zext i8 %0 to i32 ++ %1 = load i32, i32* %u32_a, align 4 ++ call void @llvm.loongarch.iocsrwr.b(i32 %conv, i32 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.iocsrwr.b(i32, i32) ++ ++; CHECK-LABEL: iocsrwr_b: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 ++; CHECK: ld.bu $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: iocsrwr.b $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @iocsrwr_h() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u16_a = alloca i16, align 2 ++ %0 = load i16, i16* %u16_a, align 2 ++ %conv = zext i16 %0 to i32 ++ %1 = load i32, i32* %u32_a, align 4 ++ call void @llvm.loongarch.iocsrwr.h(i32 %conv, i32 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.iocsrwr.h(i32, i32) ++ ++; CHECK-LABEL: iocsrwr_h: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 ++; CHECK: ld.hu $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: iocsrwr.h $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @iocsrwr_w() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u32_b = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ %1 = load i32, i32* %u32_b, align 4 ++ call void @llvm.loongarch.iocsrwr.w(i32 %0, i32 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.iocsrwr.w(i32, i32) ++ ++; CHECK-LABEL: iocsrwr_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 12 ++; CHECK: iocsrwr.w $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @iocsrwr_d() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %u64_a = alloca i64, align 8 ++ %0 = load i64, i64* %u64_a, align 8 ++ %1 = load i32, i32* %u32_a, align 4 ++ call void @llvm.loongarch.iocsrwr.d(i64 %0, i32 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.iocsrwr.d(i64, i32) ++ ++; CHECK-LABEL: iocsrwr_d: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 12 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 ++; CHECK: iocsrwr.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @cacop_w() { ++entry: ++ %i32_a = alloca i32, align 4 ++ %0 = load i32, i32* %i32_a, align 4 ++ call void @llvm.loongarch.cacop.w(i32 1, i32 %0, i32 2) ++ ret void ++} ++ ++declare void @llvm.loongarch.cacop.w(i32, i32, i32) ++ ++; CHECK-LABEL: cacop_w: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: cacop 1, $r[[REG:[0-9]+]], 2 ++; CHECK: jr $ra ++; ++ ++define void @cacop_d() { ++entry: ++ %i64_a = alloca i64, align 8 ++ %0 = load i64, i64* %i64_a, align 8 ++ call void @llvm.loongarch.cacop.d(i32 1, i64 %0, i64 2) ++ ret void ++} ++ ++declare void @llvm.loongarch.cacop.d(i32, i64, i64) ++ ++; CHECK-LABEL: cacop_d: ++; CHECK: ld.d $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: cacop 1, $r[[REG:[0-9]+]], 2 ++; CHECK: jr $ra ++; ++ ++define void @rdtime_d() { ++entry: ++ %value = alloca i64, align 8 ++ %timeid = alloca i64, align 8 ++ %0 = call { i64, i64 } asm sideeffect "rdtime.d\09$0,$1\0A\09", "=&r,=&r"() nounwind ++ %asmresult0 = extractvalue { i64, i64 } %0, 0 ++ %asmresult1 = extractvalue { i64, i64 } %0, 1 ++ store i64 %asmresult0, i64* %value, align 8 ++ store i64 %asmresult1, i64* %timeid, align 8 ++ ret void ++} ++ ++; CHECK-LABEL: rdtime_d: ++; CHECK: rdtime.d $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] ++; CHECK: st.d $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: st.d $r[[REG1:[0-9]+]], $sp, 0 ++; CHECK: jr $ra ++; ++ ++define void @rdtimeh_w() { ++entry: ++ %value = alloca i32, align 4 ++ %timeid = alloca i32, align 4 ++ %0 = call { i32, i32 } asm sideeffect "rdtimeh.w\09$0,$1\0A\09", "=&r,=&r"() nounwind ++ %asmresult0 = extractvalue { i32, i32 } %0, 0 ++ %asmresult1 = extractvalue { i32, i32 } %0, 1 ++ store i32 %asmresult0, i32* %value, align 4 ++ store i32 %asmresult1, i32* %timeid, align 4 ++ ret void ++} ++ ++; CHECK-LABEL: rdtimeh_w: ++; CHECK: rdtimeh.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] ++; CHECK: st.w $r[[REG2:[0-9]+]], $sp, 12 ++; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @rdtimel_w() { ++entry: ++ %value = alloca i32, align 4 ++ %timeid = alloca i32, align 4 ++ %0 = call { i32, i32 } asm sideeffect "rdtimel.w\09$0,$1\0A\09", "=&r,=&r"() nounwind ++ %asmresult0 = extractvalue { i32, i32 } %0, 0 ++ %asmresult1 = extractvalue { i32, i32 } %0, 1 ++ store i32 %asmresult0, i32* %value, align 4 ++ store i32 %asmresult1, i32* %timeid, align 4 ++ ret void ++} ++ ++; CHECK-LABEL: rdtimel_w: ++; CHECK: rdtimel.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]] ++; CHECK: st.w $r[[REG2:[0-9]+]], $sp, 12 ++; CHECK: st.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: jr $ra ++; ++ ++define void @crc_w_b_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i8_a = alloca i8, align 1 ++ %0 = load i8, i8* %i8_a, align 1 ++ %conv = sext i8 %0 to i32 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crc.w.b.w(i32 %conv, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) ++ ++; CHECK-LABEL: crc_w_b_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.b $r[[REG2:[0-9]+]], $sp, 4 ++; CHECK: crc.w.b.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crc_w_h_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i16_a = alloca i16, align 2 ++ %0 = load i16, i16* %i16_a, align 2 ++ %conv = sext i16 %0 to i32 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crc.w.h.w(i32 %conv, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crc.w.h.w(i32, i32) ++ ++; CHECK-LABEL: crc_w_h_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.h $r[[REG2:[0-9]+]], $sp, 4 ++; CHECK: crc.w.h.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crc_w_w_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i32_b = alloca i32, align 4 ++ %0 = load i32, i32* %i32_a, align 4 ++ %1 = load i32, i32* %i32_b, align 4 ++ %2 = call i32 @llvm.loongarch.crc.w.w.w(i32 %0, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crc.w.w.w(i32, i32) ++ ++; CHECK-LABEL: crc_w_w_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 ++; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: crc.w.w.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crc_w_d_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i64_a = alloca i64, align 8 ++ %0 = load i64, i64* %i64_a, align 8 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crc.w.d.w(i64 %0, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crc.w.d.w(i64, i32) ++ ++; CHECK-LABEL: crc_w_d_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 ++; CHECK: crc.w.d.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crcc_w_b_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i8_a = alloca i8, align 1 ++ %0 = load i8, i8* %i8_a, align 1 ++ %conv = sext i8 %0 to i32 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crcc.w.b.w(i32 %conv, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crcc.w.b.w(i32, i32) ++ ++; CHECK-LABEL: crcc_w_b_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.b $r[[REG2:[0-9]+]], $sp, 4 ++; CHECK: crcc.w.b.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crcc_w_h_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i16_a = alloca i16, align 2 ++ %0 = load i16, i16* %i16_a, align 2 ++ %conv = sext i16 %0 to i32 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crcc.w.h.w(i32 %conv, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crcc.w.h.w(i32, i32) ++ ++; CHECK-LABEL: crcc_w_h_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.h $r[[REG2:[0-9]+]], $sp, 4 ++; CHECK: crcc.w.h.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crcc_w_w_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i32_b = alloca i32, align 4 ++ %0 = load i32, i32* %i32_a, align 4 ++ %1 = load i32, i32* %i32_b, align 4 ++ %2 = call i32 @llvm.loongarch.crcc.w.w.w(i32 %0, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crcc.w.w.w(i32, i32) ++ ++; CHECK-LABEL: crcc_w_w_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 4 ++; CHECK: ld.w $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: crcc.w.w.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @crcc_w_d_w() { ++entry: ++ %i32_r = alloca i32, align 4 ++ %i32_a = alloca i32, align 4 ++ %i64_a = alloca i64, align 8 ++ %0 = load i64, i64* %i64_a, align 8 ++ %1 = load i32, i32* %i32_a, align 4 ++ %2 = call i32 @llvm.loongarch.crcc.w.d.w(i64 %0, i32 %1) ++ store i32 %2, i32* %i32_r, align 4 ++ ret void ++} ++ ++declare i32 @llvm.loongarch.crcc.w.d.w(i64, i32) ++ ++; CHECK-LABEL: crcc_w_d_w: ++; CHECK: ld.w $r[[REG1:[0-9]+]], $sp, 8 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 0 ++; CHECK: crcc.w.d.w $r[[REG1:[0-9]+]], $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @tlbclr() { ++entry: ++ call void @llvm.loongarch.tlbclr() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbclr() ++ ++; CHECK-LABEL: tlbclr: ++; CHECK: tlbclr ++; CHECK: jr $ra ++; ++ ++define void @tlbflush() { ++entry: ++ call void @llvm.loongarch.tlbflush() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbflush() ++ ++; CHECK-LABEL: tlbflush: ++; CHECK: tlbflush ++; CHECK: jr $ra ++; ++ ++define void @tlbfill() { ++entry: ++ call void @llvm.loongarch.tlbfill() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbfill() ++ ++; CHECK-LABEL: tlbfill: ++; CHECK: tlbfill ++; CHECK: jr $ra ++; ++ ++define void @tlbrd() { ++entry: ++ call void @llvm.loongarch.tlbrd() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbrd() ++ ++; CHECK-LABEL: tlbrd: ++; CHECK: tlbrd ++; CHECK: jr $ra ++; ++ ++define void @tlbwr() { ++entry: ++ call void @llvm.loongarch.tlbwr() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbwr() ++ ++; CHECK-LABEL: tlbwr: ++; CHECK: tlbwr ++; CHECK: jr $ra ++; ++ ++define void @tlbsrch() { ++entry: ++ call void @llvm.loongarch.tlbsrch() ++ ret void ++} ++ ++declare void @llvm.loongarch.tlbsrch() ++ ++; CHECK-LABEL: tlbsrch: ++; CHECK: tlbsrch ++; CHECK: jr $ra ++; ++ ++define void @syscall() { ++entry: ++ call void @llvm.loongarch.syscall(i64 1) ++ ret void ++} ++ ++declare void @llvm.loongarch.syscall(i64) ++ ++; CHECK-LABEL: syscall: ++; CHECK: syscall 1 ++; CHECK: jr $ra ++; ++ ++define void @break_builtin() { ++entry: ++ call void @llvm.loongarch.break(i64 1) ++ ret void ++} ++ ++declare void @llvm.loongarch.break(i64) ++ ++; CHECK-LABEL: break_builtin: ++; CHECK: break 1 ++; CHECK: jr $ra ++; ++ ++define void @asrtle_d() { ++entry: ++ %i64_a = alloca i64, align 8 ++ %i64_b = alloca i64, align 8 ++ %0 = load i64, i64* %i64_a, align 8 ++ %1 = load i64, i64* %i64_b, align 8 ++ call void @llvm.loongarch.asrtle.d(i64 %0, i64 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.asrtle.d(i64, i64) ++ ++; CHECK-LABEL: asrtle_d: ++; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 0 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: asrtle.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @asrtgt_d() { ++entry: ++ %i64_a = alloca i64, align 8 ++ %i64_b = alloca i64, align 8 ++ %0 = load i64, i64* %i64_a, align 8 ++ %1 = load i64, i64* %i64_b, align 8 ++ call void @llvm.loongarch.asrtgt.d(i64 %0, i64 %1) ++ ret void ++} ++ ++declare void @llvm.loongarch.asrtgt.d(i64, i64) ++ ++; CHECK-LABEL: asrtgt_d: ++; CHECK: ld.d $r[[REG1:[0-9]+]], $sp, 0 ++; CHECK: ld.d $r[[REG2:[0-9]+]], $sp, 8 ++; CHECK: asrtgt.d $r[[REG2:[0-9]+]], $r[[REG1:[0-9]+]] ++; CHECK: jr $ra ++; ++ ++define void @dbar() { ++entry: ++ call void @llvm.loongarch.dbar(i64 0) ++ ret void ++} ++ ++declare void @llvm.loongarch.dbar(i64) ++ ++; CHECK-LABEL: dbar: ++; CHECK: dbar 0 ++; CHECK: jr $ra ++; ++ ++define void @ibar() { ++entry: ++ call void @llvm.loongarch.ibar(i64 0) ++ ret void ++} ++ ++declare void @llvm.loongarch.ibar(i64) ++ ++; CHECK-LABEL: ibar: ++; CHECK: ibar 0 ++; CHECK: jr $ra ++; ++ ++define void @movfcsr2gr() { ++entry: ++ %u32_r = alloca i32, align 4 ++ %rd = alloca i32, align 4 ++ %0 = call i32 asm sideeffect "movfcsr2gr $0, $$fcsr0", "=&r"() ++ store i32 %0, i32* %rd, align 4 ++ %1 = load i32, i32* %rd, align 4 ++ store i32 %1, i32* %u32_r, align 4 ++ ret void ++} ++ ++; CHECK-LABEL: movfcsr2gr: ++; CHECK: movfcsr2gr $r[[REG:[0-9]+]], $fcsr[[REG:[0-9]+]] ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 8 ++; CHECK: st.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: jr $ra ++; ++ ++define void @movgr2fcsr() { ++entry: ++ %u32_a = alloca i32, align 4 ++ %0 = load i32, i32* %u32_a, align 4 ++ call void asm sideeffect "movgr2fcsr $$fcsr0, $0", "r"(i32 %0) ++ ret void ++} ++ ++; CHECK-LABEL: movgr2fcsr: ++; CHECK: ld.w $r[[REG:[0-9]+]], $sp, 12 ++; CHECK: movgr2fcsr $fcsr[[REG:[0-9]+]], $r[[REG:[0-9]+]] ++; CHECK: jr $ra ++; +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll +new file mode 100644 +index 000000000..955e16268 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/const-mult.ll +@@ -0,0 +1,245 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -mtriple=loongarch64-linux-gnu < %s | FileCheck %s ++ ++ ++; This test is copied from Mips except the mul2730_32 and mul2730_64 ++ ++define i32 @mul5_32(i32 signext %a) { ++; CHECK-LABEL: mul5_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: alsl.w $r4, $r4, $r4, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i32 %a, 5 ++ ret i32 %mul ++} ++ ++define i32 @mul27_32(i32 signext %a) { ++; CHECK-LABEL: mul27_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: alsl.w $r5, $r4, $r4, 2 ++; CHECK-NEXT: slli.w $r4, $r4, 5 ++; CHECK-NEXT: sub.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i32 %a, 27 ++ ret i32 %mul ++} ++ ++define i32 @muln2147483643_32(i32 signext %a) { ++; CHECK-LABEL: muln2147483643_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: alsl.w $r5, $r4, $r4, 2 ++; CHECK-NEXT: slli.w $r4, $r4, 31 ++; CHECK-NEXT: add.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i32 %a, -2147483643 ++ ret i32 %mul ++} ++ ++define i64 @muln9223372036854775805_64(i64 signext %a) { ++; CHECK-LABEL: muln9223372036854775805_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: alsl.d $r5, $r4, $r4, 1 ++; CHECK-NEXT: slli.d $r4, $r4, 63 ++; CHECK-NEXT: add.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i64 %a, -9223372036854775805 ++ ret i64 %mul ++} ++ ++define i128 @muln170141183460469231731687303715884105725_128(i128 signext %a) { ++; CHECK-LABEL: muln170141183460469231731687303715884105725_128: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: srli.d $r6, $r4, 63 ++; CHECK-NEXT: slli.d $r7, $r5, 1 ++; CHECK-NEXT: or $r6, $r7, $r6 ++; CHECK-NEXT: add.d $r5, $r6, $r5 ++; CHECK-NEXT: slli.d $r7, $r4, 1 ++; CHECK-NEXT: alsl.d $r6, $r4, $r4, 1 ++; CHECK-NEXT: sltu $r7, $r6, $r7 ++; CHECK-NEXT: bstrpick.d $r7, $r7, 31, 0 ++; CHECK-NEXT: add.d $r5, $r5, $r7 ++; CHECK-NEXT: slli.d $r4, $r4, 63 ++; CHECK-NEXT: add.d $r5, $r4, $r5 ++; CHECK-NEXT: move $r4, $r6 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i128 %a, -170141183460469231731687303715884105725 ++ ret i128 %mul ++} ++ ++define i128 @mul170141183460469231731687303715884105723_128(i128 signext %a) { ++; CHECK-LABEL: mul170141183460469231731687303715884105723_128: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: srli.d $r6, $r4, 62 ++; CHECK-NEXT: slli.d $r7, $r5, 2 ++; CHECK-NEXT: or $r6, $r7, $r6 ++; CHECK-NEXT: add.d $r5, $r6, $r5 ++; CHECK-NEXT: slli.d $r6, $r4, 2 ++; CHECK-NEXT: alsl.d $r7, $r4, $r4, 2 ++; CHECK-NEXT: sltu $r6, $r7, $r6 ++; CHECK-NEXT: bstrpick.d $r6, $r6, 31, 0 ++; CHECK-NEXT: add.d $r5, $r5, $r6 ++; CHECK-NEXT: slli.d $r4, $r4, 63 ++; CHECK-NEXT: sub.d $r4, $r4, $r5 ++; CHECK-NEXT: sltu $r5, $zero, $r7 ++; CHECK-NEXT: bstrpick.d $r5, $r5, 31, 0 ++; CHECK-NEXT: sub.d $r5, $r4, $r5 ++; CHECK-NEXT: addi.d $r4, $zero, 0 ++; CHECK-NEXT: sub.d $r4, $r4, $r7 ++; CHECK-NEXT: jr $ra ++entry: ++ %mul = mul nsw i128 %a, 170141183460469231731687303715884105723 ++ ret i128 %mul ++} ++ ++define i32 @mul42949673_32(i32 %a) { ++; CHECK-LABEL: mul42949673_32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r5, 10485 ++; CHECK-NEXT: ori $r5, $r5, 3113 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %b = mul i32 %a, 42949673 ++ ret i32 %b ++} ++ ++define i64 @mul42949673_64(i64 %a) { ++; CHECK-LABEL: mul42949673_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 10485 ++; CHECK-NEXT: ori $r5, $r5, 3113 ++; CHECK-NEXT: mul.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 42949673 ++ ret i64 %b ++} ++ ++define i32 @mul22224078_32(i32 %a) { ++; CHECK-LABEL: mul22224078_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5425 ++; CHECK-NEXT: ori $r5, $r5, 3278 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i32 %a, 22224078 ++ ret i32 %b ++} ++ ++define i64 @mul22224078_64(i64 %a) { ++; CHECK-LABEL: mul22224078_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5425 ++; CHECK-NEXT: ori $r5, $r5, 3278 ++; CHECK-NEXT: mul.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 22224078 ++ ret i64 %b ++} ++ ++define i32 @mul22245375_32(i32 %a) { ++; CHECK-LABEL: mul22245375_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5430 ++; CHECK-NEXT: ori $r5, $r5, 4095 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i32 %a, 22245375 ++ ret i32 %b ++} ++ ++define i64 @mul22245375_64(i64 %a) { ++; CHECK-LABEL: mul22245375_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5430 ++; CHECK-NEXT: ori $r5, $r5, 4095 ++; CHECK-NEXT: mul.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 22245375 ++ ret i64 %b ++} ++ ++define i32 @mul25165824_32(i32 %a) { ++; CHECK-LABEL: mul25165824_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5430 ++; CHECK-NEXT: ori $r5, $r5, 4095 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i32 %a, 22245375 ++ ret i32 %b ++} ++ ++define i64 @mul25165824_64(i64 %a) { ++; CHECK-LABEL: mul25165824_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.d $r5, $r4, 23 ++; CHECK-NEXT: slli.d $r4, $r4, 24 ++; CHECK-NEXT: add.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 25165824 ++ ret i64 %b ++} ++ ++define i32 @mul33554432_32(i32 %a) { ++; CHECK-LABEL: mul33554432_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r5, 5430 ++; CHECK-NEXT: ori $r5, $r5, 4095 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i32 %a, 22245375 ++ ret i32 %b ++} ++ ++define i64 @mul33554432_64(i64 %a) { ++; CHECK-LABEL: mul33554432_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.d $r4, $r4, 25 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 33554432 ++ ret i64 %b ++} ++ ++define i32 @mul2730_32(i32 %a) { ++; CHECK-LABEL: mul2730_32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: ori $r5, $zero, 2730 ++; CHECK-NEXT: mul.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i32 %a, 2730 ++ ret i32 %b ++} ++ ++define i64 @mul2730_64(i64 %a) { ++; CHECK-LABEL: mul2730_64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ori $r5, $zero, 2730 ++; CHECK-NEXT: mul.d $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = mul i64 %a, 2730 ++ ret i64 %b ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll +new file mode 100644 +index 000000000..586daca23 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/disable-tail-calls.ll +@@ -0,0 +1,94 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s \ ++; RUN: | FileCheck %s --check-prefixes=CHECK1 ++; RUN: llc -march=loongarch64 -relocation-model=pic -disable-tail-calls < %s \ ++; RUN: | FileCheck %s --check-prefixes=CHECK2 ++; RUN: llc -march=loongarch64 -relocation-model=pic -disable-tail-calls=false < %s \ ++; RUN: | FileCheck %s --check-prefixes=CHECK3 ++ ++; Function with attribute #0 = { "disable-tail-calls"="true" } ++define i32 @caller1(i32 %a) #0 { ++; CHECK1-LABEL: caller1: ++; CHECK1: # %bb.0: # %entry ++; CHECK1-NEXT: addi.d $sp, $sp, -16 ++; CHECK1-NEXT: .cfi_def_cfa_offset 16 ++; CHECK1-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK1-NEXT: .cfi_offset 1, -8 ++; CHECK1-NEXT: bl callee ++; CHECK1-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK1-NEXT: addi.d $sp, $sp, 16 ++; CHECK1-NEXT: jr $ra ++; ++; CHECK2-LABEL: caller1: ++; CHECK2: # %bb.0: # %entry ++; CHECK2-NEXT: addi.d $sp, $sp, -16 ++; CHECK2-NEXT: .cfi_def_cfa_offset 16 ++; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK2-NEXT: .cfi_offset 1, -8 ++; CHECK2-NEXT: bl callee ++; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK2-NEXT: addi.d $sp, $sp, 16 ++; CHECK2-NEXT: jr $ra ++; ++; CHECK3-LABEL: caller1: ++; CHECK3: # %bb.0: # %entry ++; CHECK3-NEXT: b callee ++entry: ++ %call = tail call i32 @callee(i32 %a) ++ ret i32 %call ++} ++ ++ ++; Function with attribute #1 = { "disable-tail-calls"="false" } ++define i32 @caller2(i32 %a) #1 { ++; CHECK1-LABEL: caller2: ++; CHECK1: # %bb.0: # %entry ++; CHECK1-NEXT: b callee ++; ++; CHECK2-LABEL: caller2: ++; CHECK2: # %bb.0: # %entry ++; CHECK2-NEXT: addi.d $sp, $sp, -16 ++; CHECK2-NEXT: .cfi_def_cfa_offset 16 ++; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK2-NEXT: .cfi_offset 1, -8 ++; CHECK2-NEXT: bl callee ++; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK2-NEXT: addi.d $sp, $sp, 16 ++; CHECK2-NEXT: jr $ra ++; ++; CHECK3-LABEL: caller2: ++; CHECK3: # %bb.0: # %entry ++; CHECK3-NEXT: b callee ++entry: ++ %call = tail call i32 @callee(i32 %a) ++ ret i32 %call ++} ++ ++define i32 @caller3(i32 %a) { ++; CHECK1-LABEL: caller3: ++; CHECK1: # %bb.0: # %entry ++; CHECK1-NEXT: b callee ++; ++; CHECK2-LABEL: caller3: ++; CHECK2: # %bb.0: # %entry ++; CHECK2-NEXT: addi.d $sp, $sp, -16 ++; CHECK2-NEXT: .cfi_def_cfa_offset 16 ++; CHECK2-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK2-NEXT: .cfi_offset 1, -8 ++; CHECK2-NEXT: bl callee ++; CHECK2-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK2-NEXT: addi.d $sp, $sp, 16 ++; CHECK2-NEXT: jr $ra ++; ++; CHECK3-LABEL: caller3: ++; CHECK3: # %bb.0: # %entry ++; CHECK3-NEXT: b callee ++entry: ++ %call = tail call i32 @callee(i32 %a) ++ ret i32 %call ++} ++ ++declare i32 @callee(i32) ++ ++attributes #0 = { "disable-tail-calls"="true" } ++attributes #1 = { "disable-tail-calls"="false" } +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll +new file mode 100644 +index 000000000..34293a83c +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/divrem.ll +@@ -0,0 +1,68 @@ ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s -check-prefixes=CHECK,CHECK-TRAP ++ ++; RUN: llc -march=loongarch64 -mnocheck-zero-division -relocation-model=pic < %s | FileCheck %s -check-prefixes=CHECK,NOCHECK ++ ++; FileCheck Prefixes: ++; CHECK-TRAP - trap ++; NOCHECK - Division by zero will not be detected ++ ++define i32 @sdiv1(i32 signext %a0, i32 signext %a1) nounwind readnone { ++entry: ++; CHECK-LABEL: sdiv1: ++ ++; CHECK: div.w $r4, $r4, $r5 ++; CHECK-TRAP: bne $r5, $zero, 8 ++; CHECK-TRAP: break 7 ++ ++; NOCHECK-NOT: bne ++; NOCHECK-NOT: break ++ ++ %div = sdiv i32 %a0, %a1 ++ ret i32 %div ++} ++ ++define i32 @srem1(i32 signext %a0, i32 signext %a1) nounwind readnone { ++entry: ++; CHECK-LABEL: srem1: ++ ++; CHECK: mod.w $r4, $r4, $r5 ++; CHECK-TRAP: bne $r5, $zero, 8 ++; CHECK-TRAP: break 7 ++ ++; NOCHECK-NOT: bne ++; NOCHECK-NOT: break ++ ++ %rem = srem i32 %a0, %a1 ++ ret i32 %rem ++} ++ ++define i32 @udiv1(i32 signext %a0, i32 signext %a1) nounwind readnone { ++entry: ++; CHECK-LABEL: udiv1: ++ ++; CHECK: div.wu $r4, $r4, $r5 ++; CHECK-TRAP: bne $r5, $zero, 8 ++; CHECK-TRAP: break 7 ++ ++; NOCHECK-NOT: bne ++; NOCHECK-NOT: break ++ ++ %div = udiv i32 %a0, %a1 ++ ret i32 %div ++} ++ ++define i32 @urem1(i32 signext %a0, i32 signext %a1) nounwind readnone { ++entry: ++; CHECK-LABEL: urem1: ++ ++ ++; CHECK: mod.wu $r4, $r4, $r5 ++; CHECK-TRAP: bne $r5, $zero, 8 ++; CHECK-TRAP: break 7 ++ ++; NOCHECK-NOT: bne ++; NOCHECK-NOT: break ++ ++ %rem = urem i32 %a0, %a1 ++ ret i32 %rem ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll +new file mode 100644 +index 000000000..cad67e98c +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/dup-tail.ll +@@ -0,0 +1,45 @@ ++; RUN: llc --mtriple=loongarch64 --relocation-model=pic -o - %s | FileCheck %s ++ ++;; Duplicate returns to enable tail call optimizations. ++declare i32 @test() ++declare i32 @test1() ++declare i32 @test2() ++declare i32 @test3() ++define i32 @duplicate_returns(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: duplicate_returns: ++; CHECK: b test2 ++; CHECK: b test ++; CHECK: b test1 ++; CHECK: b test3 ++entry: ++ %cmp = icmp eq i32 %a, 0 ++ br i1 %cmp, label %if.then, label %if.else ++ ++if.then: ; preds = %entry ++ %call = tail call i32 @test() ++ br label %return ++ ++if.else: ; preds = %entry ++ %cmp1 = icmp eq i32 %b, 0 ++ br i1 %cmp1, label %if.then2, label %if.else4 ++ ++if.then2: ; preds = %if.else ++ %call3 = tail call i32 @test1() ++ br label %return ++ ++if.else4: ; preds = %if.else ++ %cmp5 = icmp sgt i32 %a, %b ++ br i1 %cmp5, label %if.then6, label %if.else8 ++ ++if.then6: ; preds = %if.else4 ++ %call7 = tail call i32 @test2() ++ br label %return ++ ++if.else8: ; preds = %if.else4 ++ %call9 = tail call i32 @test3() ++ br label %return ++ ++return: ; preds = %if.else8, %if.then6, %if.then2, %if.then ++ %retval = phi i32 [ %call, %if.then ], [ %call3, %if.then2 ], [ %call7, %if.then6 ], [ %call9, %if.else8 ] ++ ret i32 %retval ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll +new file mode 100644 +index 000000000..0272c95bd +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/eliminateFI.ll +@@ -0,0 +1,106 @@ ++; Check whether LoongArchSERegisterInfo::eliminateFI works well ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define signext i32 @ldptr_w_unaligned() { ++; CHECK-LABEL: ldptr_w_unaligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 ++ %0 = bitcast i8* %arrayidx to i32* ++; the offset MUST be 0 ++; CHECK: ldptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, 0 ++ %1 = load i32, i32* %0, align 1 ++ ret i32 %1 ++} ++ ++define signext i32 @ldptr_w_aligned() { ++; CHECK-LABEL: ldptr_w_aligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 ++ %0 = bitcast i8* %arrayidx to i32* ++; the offset may not be 0, but MUST be 4-bytes aligned ++; CHECK: ldptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} ++ %1 = load i32, i32* %0, align 1 ++ ret i32 %1 ++} ++ ++define signext i64 @ldptr_d_unaligned() { ++; CHECK-LABEL: ldptr_d_unaligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 ++ %0 = bitcast i8* %arrayidx to i64* ++; the offset MUST be 0 ++; CHECK: ldptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, 0 ++ %1 = load i64, i64* %0, align 1 ++ ret i64 %1 ++} ++ ++define signext i64 @ldptr_d_aligned() { ++; CHECK-LABEL: ldptr_d_aligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 ++ %0 = bitcast i8* %arrayidx to i64* ++; the offset may not be 0, but MUST be 4-bytes aligned ++; CHECK: ldptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} ++ %1 = load i64, i64* %0, align 1 ++ ret i64 %1 ++} ++ ++define void @stptr_w_unaligned(i32 signext %val) { ++; CHECK-LABEL: stptr_w_unaligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 ++ %0 = bitcast i8* %arrayidx to i32* ++; the offset MUST be 0 ++; CHECK: stptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, 0 ++ store i32 %val, i32* %0, align 1 ++ ret void ++} ++ ++define void @stptr_w_aligned(i32 signext %val) { ++; CHECK-LABEL: stptr_w_aligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 ++ %0 = bitcast i8* %arrayidx to i32* ++; the offset may not be 0, but MUST be 4-bytes aligned ++; CHECK: stptr.w $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} ++ store i32 %val, i32* %0, align 1 ++ ret void ++} ++ ++define void @stptr_d_unaligned(i64 %val) { ++; CHECK-LABEL: stptr_d_unaligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5001 ++ %0 = bitcast i8* %arrayidx to i64* ++; the offset MUST be 0 ++; CHECK: stptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, 0 ++ store i64 %val, i64* %0, align 1 ++ ret void ++} ++ ++define void @stptr_d_aligned(i64 %val) { ++; CHECK-LABEL: stptr_d_aligned: ++; CHECK: # %bb.0: # %entry ++entry: ++ %array = alloca [6000 x i8], align 1 ++ %arrayidx = getelementptr inbounds [6000 x i8], [6000 x i8]* %array, i64 0, i64 5000 ++ %0 = bitcast i8* %arrayidx to i64* ++; the offset may not be 0, but MUST be 4-bytes aligned ++; CHECK: stptr.d $r{{[0-9]+}}, $r{{[0-9]+}}, {{[0-9]+}} ++ store i64 %val, i64* %0, align 1 ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll +new file mode 100644 +index 000000000..80fa7a855 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll +@@ -0,0 +1,103 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc --mtriple=loongarch64 -O0 < %s | FileCheck %s ++ ++@var = external global i32 ++ ++define void @func() { ++; CHECK-LABEL: func: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $sp, $sp, -2048 ++; CHECK-NEXT: addi.d $sp, $sp, -2048 ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 4112 ++; CHECK-NEXT: lu12i.w $r5, var ++; CHECK-NEXT: ori $r5, $r5, var ++; CHECK-NEXT: lu32i.d $r5, var ++; CHECK-NEXT: lu52i.d $r5, $r5, var ++; CHECK-NEXT: ld.w $r20, $r5, 0 ++; CHECK-NEXT: ld.w $r19, $r5, 0 ++; CHECK-NEXT: ld.w $r18, $r5, 0 ++; CHECK-NEXT: ld.w $r17, $r5, 0 ++; CHECK-NEXT: ld.w $r16, $r5, 0 ++; CHECK-NEXT: ld.w $r15, $r5, 0 ++; CHECK-NEXT: ld.w $r14, $r5, 0 ++; CHECK-NEXT: ld.w $r13, $r5, 0 ++; CHECK-NEXT: ld.w $r12, $r5, 0 ++; CHECK-NEXT: ld.w $r11, $r5, 0 ++; CHECK-NEXT: ld.w $r10, $r5, 0 ++; CHECK-NEXT: ld.w $r9, $r5, 0 ++; CHECK-NEXT: ld.w $r8, $r5, 0 ++; CHECK-NEXT: ld.w $r7, $r5, 0 ++; CHECK-NEXT: ld.w $r6, $r5, 0 ++; CHECK-NEXT: ld.w $r4, $r5, 0 ++; CHECK-NEXT: st.d $r23, $sp, 0 ++; CHECK-NEXT: lu12i.w $r23, 1 ++; CHECK-NEXT: ori $r23, $r23, 12 ++; CHECK-NEXT: add.d $r23, $sp, $r23 ++; CHECK-NEXT: st.w $r20, $r23, 0 ++; CHECK-NEXT: ld.d $r23, $sp, 0 ++; CHECK-NEXT: st.w $r20, $r5, 0 ++; CHECK-NEXT: st.w $r19, $r5, 0 ++; CHECK-NEXT: st.w $r18, $r5, 0 ++; CHECK-NEXT: st.w $r17, $r5, 0 ++; CHECK-NEXT: st.w $r16, $r5, 0 ++; CHECK-NEXT: st.w $r15, $r5, 0 ++; CHECK-NEXT: st.w $r14, $r5, 0 ++; CHECK-NEXT: st.w $r13, $r5, 0 ++; CHECK-NEXT: st.w $r12, $r5, 0 ++; CHECK-NEXT: st.w $r11, $r5, 0 ++; CHECK-NEXT: st.w $r10, $r5, 0 ++; CHECK-NEXT: st.w $r9, $r5, 0 ++; CHECK-NEXT: st.w $r8, $r5, 0 ++; CHECK-NEXT: st.w $r7, $r5, 0 ++; CHECK-NEXT: st.w $r6, $r5, 0 ++; CHECK-NEXT: st.w $r4, $r5, 0 ++; CHECK-NEXT: lu12i.w $r4, 1 ++; CHECK-NEXT: ori $r4, $r4, 16 ++; CHECK-NEXT: add.d $sp, $sp, $r4 ++; CHECK-NEXT: jr $ra ++ %space = alloca i32, align 4 ++ %stackspace = alloca[1024 x i32], align 4 ++ ++ ;; Load values to increase register pressure. ++ %v0 = load volatile i32, i32* @var ++ %v1 = load volatile i32, i32* @var ++ %v2 = load volatile i32, i32* @var ++ %v3 = load volatile i32, i32* @var ++ %v4 = load volatile i32, i32* @var ++ %v5 = load volatile i32, i32* @var ++ %v6 = load volatile i32, i32* @var ++ %v7 = load volatile i32, i32* @var ++ %v8 = load volatile i32, i32* @var ++ %v9 = load volatile i32, i32* @var ++ %v10 = load volatile i32, i32* @var ++ %v11 = load volatile i32, i32* @var ++ %v12 = load volatile i32, i32* @var ++ %v13 = load volatile i32, i32* @var ++ %v14 = load volatile i32, i32* @var ++ %v15 = load volatile i32, i32* @var ++ ++ ;; Computing a stack-relative values needs an additional register. ++ ;; We should get an emergency spill/reload for this. ++ store volatile i32 %v0, i32* %space ++ ++ ;; store values so they are used. ++ store volatile i32 %v0, i32* @var ++ store volatile i32 %v1, i32* @var ++ store volatile i32 %v2, i32* @var ++ store volatile i32 %v3, i32* @var ++ store volatile i32 %v4, i32* @var ++ store volatile i32 %v5, i32* @var ++ store volatile i32 %v6, i32* @var ++ store volatile i32 %v7, i32* @var ++ store volatile i32 %v8, i32* @var ++ store volatile i32 %v9, i32* @var ++ store volatile i32 %v10, i32* @var ++ store volatile i32 %v11, i32* @var ++ store volatile i32 %v12, i32* @var ++ store volatile i32 %v13, i32* @var ++ store volatile i32 %v14, i32* @var ++ store volatile i32 %v15, i32* @var ++ ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll +new file mode 100644 +index 000000000..c16413715 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/fcopysign.ll +@@ -0,0 +1,17 @@ ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define float @fcopysign_s(float %a, float %b) { ++; CHECK-LABEL: fcopysign_s: ++; CHECK: fcopysign.s $f0, $f0, $f1 ++ %ret = call float @llvm.copysign.f32(float %a, float %b) ++ ret float %ret ++} ++declare float @llvm.copysign.f32(float %a, float %b) ++ ++define double @fcopysign_d(double %a, double %b) { ++; CHECK-LABEL: fcopysign_d: ++; CHECK: fcopysign.d $f0, $f0, $f1 ++ %ret = call double @llvm.copysign.f64(double %a, double %b) ++ ret double %ret ++} ++declare double @llvm.copysign.f64(double %a, double %b) +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll +new file mode 100644 +index 000000000..eb4fc69fa +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/frame-info.ll +@@ -0,0 +1,132 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -relocation-model=pic -mtriple=loongarch64 -frame-pointer=all < %s | FileCheck %s ++ ++define void @trivial() { ++; CHECK-LABEL: trivial: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $r22, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 22, -8 ++; CHECK-NEXT: addi.d $r22, $sp, 16 ++; CHECK-NEXT: .cfi_def_cfa 22, 0 ++; CHECK-NEXT: ld.d $r22, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++ ret void ++} ++ ++define void @stack_alloc(i32 signext %size) { ++; CHECK-LABEL: stack_alloc: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -32 ++; CHECK-NEXT: .cfi_def_cfa_offset 32 ++; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill ++; CHECK-NEXT: st.d $r22, $sp, 16 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: .cfi_offset 22, -16 ++; CHECK-NEXT: addi.d $r22, $sp, 32 ++; CHECK-NEXT: .cfi_def_cfa 22, 0 ++; CHECK-NEXT: addi.w $r5, $zero, -16 ++; CHECK-NEXT: lu32i.d $r5, 1 ++; CHECK-NEXT: bstrpick.d $r4, $r4, 31, 0 ++; CHECK-NEXT: addi.d $r4, $r4, 15 ++; CHECK-NEXT: and $r4, $r4, $r5 ++; CHECK-NEXT: sub.d $r4, $sp, $r4 ++; CHECK-NEXT: move $sp, $r4 ++; CHECK-NEXT: bl callee_with_args ++; CHECK-NEXT: addi.d $sp, $r22, -32 ++; CHECK-NEXT: ld.d $r22, $sp, 16 # 8-byte Folded Reload ++; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 32 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = alloca i8, i32 %size, align 16 ++ call void @callee_with_args(i8* nonnull %0) ++ ret void ++} ++ ++define void @branch_and_tail_call(i1 %a) { ++; CHECK-LABEL: branch_and_tail_call: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andi $r4, $r4, 1 ++; CHECK-NEXT: beqz $r4, .LBB2_2 ++; CHECK-NEXT: # %bb.1: # %blue_pill ++; CHECK-NEXT: b callee1 ++; CHECK-NEXT: .LBB2_2: # %red_pill ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: st.d $r22, $sp, 0 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: .cfi_offset 22, -16 ++; CHECK-NEXT: addi.d $r22, $sp, 16 ++; CHECK-NEXT: .cfi_def_cfa 22, 0 ++; CHECK-NEXT: bl callee2 ++; CHECK-NEXT: ld.d $r22, $sp, 0 # 8-byte Folded Reload ++; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++ br i1 %a, label %blue_pill, label %red_pill ++blue_pill: ++ tail call void @callee1() ++ ret void ++red_pill: ++ call void @callee2() ++ ret void ++} ++ ++define void @big_frame() { ++; CHECK-LABEL: big_frame: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -2032 ++; CHECK-NEXT: .cfi_def_cfa_offset 2032 ++; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill ++; CHECK-NEXT: st.d $r22, $sp, 2016 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: .cfi_offset 22, -16 ++; CHECK-NEXT: addi.d $r22, $sp, 2032 ++; CHECK-NEXT: .cfi_def_cfa 22, 0 ++; CHECK-NEXT: addi.d $sp, $sp, -48 ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2016 ++; CHECK-NEXT: add.d $r4, $r22, $r4 ++; CHECK-NEXT: addi.d $r4, $r4, 0 ++; CHECK-NEXT: bl callee_with_args ++; CHECK-NEXT: addi.d $sp, $sp, 48 ++; CHECK-NEXT: ld.d $r22, $sp, 2016 # 8-byte Folded Reload ++; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 2032 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = alloca i8, i32 2048, align 16 ++ call void @callee_with_args(i8* nonnull %0) ++ ret void ++} ++ ++define void @varargs_frame(i32 %i, ...) { ++; CHECK-LABEL: varargs_frame: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $sp, $sp, -80 ++; CHECK-NEXT: .cfi_def_cfa_offset 80 ++; CHECK-NEXT: st.d $r22, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 22, -72 ++; CHECK-NEXT: addi.d $r22, $sp, 16 ++; CHECK-NEXT: .cfi_def_cfa 22, 64 ++; CHECK-NEXT: st.d $r11, $r22, 56 ++; CHECK-NEXT: st.d $r10, $r22, 48 ++; CHECK-NEXT: st.d $r9, $r22, 40 ++; CHECK-NEXT: st.d $r8, $r22, 32 ++; CHECK-NEXT: st.d $r7, $r22, 24 ++; CHECK-NEXT: st.d $r6, $r22, 16 ++; CHECK-NEXT: st.d $r5, $r22, 8 ++; CHECK-NEXT: ld.d $r22, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 80 ++; CHECK-NEXT: jr $ra ++ ret void ++} ++ ++declare void @callee1() ++declare void @callee2() ++declare void @callee_with_args(i8*) +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll +new file mode 100644 +index 000000000..f41ee08c0 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/fsel.ll +@@ -0,0 +1,47 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++ ++define double @olt_f64(double %a, double %b) { ++; CHECK-LABEL: olt_f64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: fcmp.clt.d $fcc0, $f0, $f1 ++; CHECK-NEXT: fsel $f0, $f1, $f0, $fcc0 ++; CHECK-NEXT: jr $ra ++ %cond = fcmp olt double %a, %b ++ %ret = select i1 %cond, double %a, double %b ++ ret double %ret ++} ++ ++define double @ogt_f64(double %a, double %b) { ++; CHECK-LABEL: ogt_f64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: fcmp.cule.d $fcc0, $f0, $f1 ++; CHECK-NEXT: fsel $f0, $f0, $f1, $fcc0 ++; CHECK-NEXT: jr $ra ++ %cond = fcmp ogt double %a, %b ++ %ret = select i1 %cond, double %a, double %b ++ ret double %ret ++} ++ ++define float @olt_f32(float %a, float %b) { ++; CHECK-LABEL: olt_f32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: fcmp.clt.s $fcc0, $f0, $f1 ++; CHECK-NEXT: fsel $f0, $f1, $f0, $fcc0 ++; CHECK-NEXT: jr $ra ++ %cond = fcmp olt float %a, %b ++ %ret = select i1 %cond, float %a, float %b ++ ret float %ret ++} ++ ++define float @ogt_f32(float %a, float %b) { ++; CHECK-LABEL: ogt_f32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: fcmp.cule.s $fcc0, $f0, $f1 ++; CHECK-NEXT: fsel $f0, $f0, $f1, $fcc0 ++; CHECK-NEXT: jr $ra ++ %cond = fcmp ogt float %a, %b ++ %ret = select i1 %cond, float %a, float %b ++ ret float %ret ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll +new file mode 100644 +index 000000000..1de3ef0fc +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/immediate.ll +@@ -0,0 +1,2542 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -mtriple=loongarch64 < %s | FileCheck %s ++define i64 @li0000000000000000() { ++; CHECK-LABEL: li0000000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r4, $zero, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 0 ++} ++ ++define i64 @li00000000000007ff() { ++; CHECK-LABEL: li00000000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r4, $zero, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 2047 ++} ++ ++define i64 @li0000000000000800() { ++; CHECK-LABEL: li0000000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: jr $ra ++ ret i64 2048 ++} ++ ++define i64 @li0000000000000fff() { ++; CHECK-LABEL: li0000000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: jr $ra ++ ret i64 4095 ++} ++ ++define i64 @li000000007ffff000() { ++; CHECK-LABEL: li000000007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2147479552 ++} ++ ++define i64 @li000000007ffff7ff() { ++; CHECK-LABEL: li000000007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 2147481599 ++} ++ ++define i64 @li000000007ffff800() { ++; CHECK-LABEL: li000000007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: jr $ra ++ ret i64 2147481600 ++} ++ ++define i64 @li000000007fffffff() { ++; CHECK-LABEL: li000000007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: jr $ra ++ ret i64 2147483647 ++} ++ ++define i64 @li0000000080000000() { ++; CHECK-LABEL: li0000000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2147483648 ++} ++ ++define i64 @li00000000800007ff() { ++; CHECK-LABEL: li00000000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2147485695 ++} ++ ++define i64 @li0000000080000800() { ++; CHECK-LABEL: li0000000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2147485696 ++} ++ ++define i64 @li0000000080000fff() { ++; CHECK-LABEL: li0000000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2147487743 ++} ++ ++define i64 @li00000000fffff000() { ++; CHECK-LABEL: li00000000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4294963200 ++} ++ ++define i64 @li00000000fffff7ff() { ++; CHECK-LABEL: li00000000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4294965247 ++} ++ ++define i64 @li00000000fffff800() { ++; CHECK-LABEL: li00000000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4294965248 ++} ++ ++define i64 @li00000000ffffffff() { ++; CHECK-LABEL: li00000000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4294967295 ++} ++ ++define i64 @li0007ffff00000000() { ++; CHECK-LABEL: li0007ffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251795518717952 ++} ++ ++define i64 @li0007ffff000007ff() { ++; CHECK-LABEL: li0007ffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251795518719999 ++} ++ ++define i64 @li0007ffff00000800() { ++; CHECK-LABEL: li0007ffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251795518720000 ++} ++ ++define i64 @li0007ffff00000fff() { ++; CHECK-LABEL: li0007ffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251795518722047 ++} ++ ++define i64 @li0007ffff7ffff000() { ++; CHECK-LABEL: li0007ffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666197504 ++} ++ ++define i64 @li0007ffff7ffff7ff() { ++; CHECK-LABEL: li0007ffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666199551 ++} ++ ++define i64 @li0007ffff7ffff800() { ++; CHECK-LABEL: li0007ffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666199552 ++} ++ ++define i64 @li0007ffff7fffffff() { ++; CHECK-LABEL: li0007ffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666201599 ++} ++ ++define i64 @li0007ffff80000000() { ++; CHECK-LABEL: li0007ffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666201600 ++} ++ ++define i64 @li0007ffff800007ff() { ++; CHECK-LABEL: li0007ffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666203647 ++} ++ ++define i64 @li0007ffff80000800() { ++; CHECK-LABEL: li0007ffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666203648 ++} ++ ++define i64 @li0007ffff80000fff() { ++; CHECK-LABEL: li0007ffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251797666205695 ++} ++ ++define i64 @li0007fffffffff000() { ++; CHECK-LABEL: li0007fffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813681152 ++} ++ ++define i64 @li0007fffffffff7ff() { ++; CHECK-LABEL: li0007fffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813683199 ++} ++ ++define i64 @li0007fffffffff800() { ++; CHECK-LABEL: li0007fffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813683200 ++} ++ ++define i64 @li0007ffffffffffff() { ++; CHECK-LABEL: li0007ffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813685247 ++} ++ ++define i64 @li0008000000000000() { ++; CHECK-LABEL: li0008000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813685248 ++} ++ ++define i64 @li00080000000007ff() { ++; CHECK-LABEL: li00080000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813687295 ++} ++ ++define i64 @li0008000000000800() { ++; CHECK-LABEL: li0008000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813687296 ++} ++ ++define i64 @li0008000000000fff() { ++; CHECK-LABEL: li0008000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251799813689343 ++} ++ ++define i64 @li000800007ffff000() { ++; CHECK-LABEL: li000800007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961164800 ++} ++ ++define i64 @li000800007ffff7ff() { ++; CHECK-LABEL: li000800007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961166847 ++} ++ ++define i64 @li000800007ffff800() { ++; CHECK-LABEL: li000800007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961166848 ++} ++ ++define i64 @li000800007fffffff() { ++; CHECK-LABEL: li000800007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961168895 ++} ++ ++define i64 @li0008000080000000() { ++; CHECK-LABEL: li0008000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961168896 ++} ++ ++define i64 @li00080000800007ff() { ++; CHECK-LABEL: li00080000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961170943 ++} ++ ++define i64 @li0008000080000800() { ++; CHECK-LABEL: li0008000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961170944 ++} ++ ++define i64 @li0008000080000fff() { ++; CHECK-LABEL: li0008000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251801961172991 ++} ++ ++define i64 @li00080000fffff000() { ++; CHECK-LABEL: li00080000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251804108648448 ++} ++ ++define i64 @li00080000fffff7ff() { ++; CHECK-LABEL: li00080000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251804108650495 ++} ++ ++define i64 @li00080000fffff800() { ++; CHECK-LABEL: li00080000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251804108650496 ++} ++ ++define i64 @li00080000ffffffff() { ++; CHECK-LABEL: li00080000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 2251804108652543 ++} ++ ++define i64 @li000fffff00000000() { ++; CHECK-LABEL: li000fffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503595332403200 ++} ++ ++define i64 @li000fffff000007ff() { ++; CHECK-LABEL: li000fffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503595332405247 ++} ++ ++define i64 @li000fffff00000800() { ++; CHECK-LABEL: li000fffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503595332405248 ++} ++ ++define i64 @li000fffff00000fff() { ++; CHECK-LABEL: li000fffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503595332407295 ++} ++ ++define i64 @li000fffff7ffff000() { ++; CHECK-LABEL: li000fffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479882752 ++} ++ ++define i64 @li000fffff7ffff7ff() { ++; CHECK-LABEL: li000fffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479884799 ++} ++ ++define i64 @li000fffff7ffff800() { ++; CHECK-LABEL: li000fffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479884800 ++} ++ ++define i64 @li000fffff7fffffff() { ++; CHECK-LABEL: li000fffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479886847 ++} ++ ++define i64 @li000fffff80000000() { ++; CHECK-LABEL: li000fffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479886848 ++} ++ ++define i64 @li000fffff800007ff() { ++; CHECK-LABEL: li000fffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479888895 ++} ++ ++define i64 @li000fffff80000800() { ++; CHECK-LABEL: li000fffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479888896 ++} ++ ++define i64 @li000fffff80000fff() { ++; CHECK-LABEL: li000fffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503597479890943 ++} ++ ++define i64 @li000ffffffffff000() { ++; CHECK-LABEL: li000ffffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503599627366400 ++} ++ ++define i64 @li000ffffffffff7ff() { ++; CHECK-LABEL: li000ffffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503599627368447 ++} ++ ++define i64 @li000ffffffffff800() { ++; CHECK-LABEL: li000ffffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503599627368448 ++} ++ ++define i64 @li000fffffffffffff() { ++; CHECK-LABEL: li000fffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i64 4503599627370495 ++} ++ ++define i64 @li7ff0000000000000() { ++; CHECK-LABEL: li7ff0000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu52i.d $r4, $zero, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868437227405312 ++} ++ ++define i64 @li7ff00000000007ff() { ++; CHECK-LABEL: li7ff00000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868437227407359 ++} ++ ++define i64 @li7ff0000000000800() { ++; CHECK-LABEL: li7ff0000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868437227407360 ++} ++ ++define i64 @li7ff0000000000fff() { ++; CHECK-LABEL: li7ff0000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868437227409407 ++} ++ ++define i64 @li7ff000007ffff000() { ++; CHECK-LABEL: li7ff000007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374884864 ++} ++ ++define i64 @li7ff000007ffff7ff() { ++; CHECK-LABEL: li7ff000007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374886911 ++} ++ ++define i64 @li7ff000007ffff800() { ++; CHECK-LABEL: li7ff000007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374886912 ++} ++ ++define i64 @li7ff000007fffffff() { ++; CHECK-LABEL: li7ff000007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374888959 ++} ++ ++define i64 @li7ff0000080000000() { ++; CHECK-LABEL: li7ff0000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374888960 ++} ++ ++define i64 @li7ff00000800007ff() { ++; CHECK-LABEL: li7ff00000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374891007 ++} ++ ++define i64 @li7ff0000080000800() { ++; CHECK-LABEL: li7ff0000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374891008 ++} ++ ++define i64 @li7ff0000080000fff() { ++; CHECK-LABEL: li7ff0000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868439374893055 ++} ++ ++define i64 @li7ff00000fffff000() { ++; CHECK-LABEL: li7ff00000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868441522368512 ++} ++ ++define i64 @li7ff00000fffff7ff() { ++; CHECK-LABEL: li7ff00000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868441522370559 ++} ++ ++define i64 @li7ff00000fffff800() { ++; CHECK-LABEL: li7ff00000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868441522370560 ++} ++ ++define i64 @li7ff00000ffffffff() { ++; CHECK-LABEL: li7ff00000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9218868441522372607 ++} ++ ++define i64 @li7ff7ffff00000000() { ++; CHECK-LABEL: li7ff7ffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120232746123264 ++} ++ ++define i64 @li7ff7ffff000007ff() { ++; CHECK-LABEL: li7ff7ffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120232746125311 ++} ++ ++define i64 @li7ff7ffff00000800() { ++; CHECK-LABEL: li7ff7ffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120232746125312 ++} ++ ++define i64 @li7ff7ffff00000fff() { ++; CHECK-LABEL: li7ff7ffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120232746127359 ++} ++ ++define i64 @li7ff7ffff7ffff000() { ++; CHECK-LABEL: li7ff7ffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893602816 ++} ++ ++define i64 @li7ff7ffff7ffff7ff() { ++; CHECK-LABEL: li7ff7ffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893604863 ++} ++ ++define i64 @li7ff7ffff7ffff800() { ++; CHECK-LABEL: li7ff7ffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893604864 ++} ++ ++define i64 @li7ff7ffff7fffffff() { ++; CHECK-LABEL: li7ff7ffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893606911 ++} ++ ++define i64 @li7ff7ffff80000000() { ++; CHECK-LABEL: li7ff7ffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893606912 ++} ++ ++define i64 @li7ff7ffff800007ff() { ++; CHECK-LABEL: li7ff7ffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893608959 ++} ++ ++define i64 @li7ff7ffff80000800() { ++; CHECK-LABEL: li7ff7ffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893608960 ++} ++ ++define i64 @li7ff7ffff80000fff() { ++; CHECK-LABEL: li7ff7ffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120234893611007 ++} ++ ++define i64 @li7ff7fffffffff000() { ++; CHECK-LABEL: li7ff7fffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041086464 ++} ++ ++define i64 @li7ff7fffffffff7ff() { ++; CHECK-LABEL: li7ff7fffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041088511 ++} ++ ++define i64 @li7ff7fffffffff800() { ++; CHECK-LABEL: li7ff7fffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041088512 ++} ++ ++define i64 @li7ff7ffffffffffff() { ++; CHECK-LABEL: li7ff7ffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041090559 ++} ++ ++define i64 @li7ff8000000000000() { ++; CHECK-LABEL: li7ff8000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041090560 ++} ++ ++define i64 @li7ff80000000007ff() { ++; CHECK-LABEL: li7ff80000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041092607 ++} ++ ++define i64 @li7ff8000000000800() { ++; CHECK-LABEL: li7ff8000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041092608 ++} ++ ++define i64 @li7ff8000000000fff() { ++; CHECK-LABEL: li7ff8000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120237041094655 ++} ++ ++define i64 @li7ff800007ffff000() { ++; CHECK-LABEL: li7ff800007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188570112 ++} ++ ++define i64 @li7ff800007ffff7ff() { ++; CHECK-LABEL: li7ff800007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188572159 ++} ++ ++define i64 @li7ff800007ffff800() { ++; CHECK-LABEL: li7ff800007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188572160 ++} ++ ++define i64 @li7ff800007fffffff() { ++; CHECK-LABEL: li7ff800007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188574207 ++} ++ ++define i64 @li7ff8000080000000() { ++; CHECK-LABEL: li7ff8000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188574208 ++} ++ ++define i64 @li7ff80000800007ff() { ++; CHECK-LABEL: li7ff80000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188576255 ++} ++ ++define i64 @li7ff8000080000800() { ++; CHECK-LABEL: li7ff8000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188576256 ++} ++ ++define i64 @li7ff8000080000fff() { ++; CHECK-LABEL: li7ff8000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120239188578303 ++} ++ ++define i64 @li7ff80000fffff000() { ++; CHECK-LABEL: li7ff80000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120241336053760 ++} ++ ++define i64 @li7ff80000fffff7ff() { ++; CHECK-LABEL: li7ff80000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120241336055807 ++} ++ ++define i64 @li7ff80000fffff800() { ++; CHECK-LABEL: li7ff80000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120241336055808 ++} ++ ++define i64 @li7ff80000ffffffff() { ++; CHECK-LABEL: li7ff80000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9221120241336057855 ++} ++ ++define i64 @li7fffffff00000000() { ++; CHECK-LABEL: li7fffffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372032559808512 ++} ++ ++define i64 @li7fffffff000007ff() { ++; CHECK-LABEL: li7fffffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372032559810559 ++} ++ ++define i64 @li7fffffff00000800() { ++; CHECK-LABEL: li7fffffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372032559810560 ++} ++ ++define i64 @li7fffffff00000fff() { ++; CHECK-LABEL: li7fffffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372032559812607 ++} ++ ++define i64 @li7fffffff7ffff000() { ++; CHECK-LABEL: li7fffffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707288064 ++} ++ ++define i64 @li7fffffff7ffff7ff() { ++; CHECK-LABEL: li7fffffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707290111 ++} ++ ++define i64 @li7fffffff7ffff800() { ++; CHECK-LABEL: li7fffffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707290112 ++} ++ ++define i64 @li7fffffff7fffffff() { ++; CHECK-LABEL: li7fffffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707292159 ++} ++ ++define i64 @li7fffffff80000000() { ++; CHECK-LABEL: li7fffffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707292160 ++} ++ ++define i64 @li7fffffff800007ff() { ++; CHECK-LABEL: li7fffffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707294207 ++} ++ ++define i64 @li7fffffff80000800() { ++; CHECK-LABEL: li7fffffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707294208 ++} ++ ++define i64 @li7fffffff80000fff() { ++; CHECK-LABEL: li7fffffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372034707296255 ++} ++ ++define i64 @li7ffffffffffff000() { ++; CHECK-LABEL: li7ffffffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372036854771712 ++} ++ ++define i64 @li7ffffffffffff7ff() { ++; CHECK-LABEL: li7ffffffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372036854773759 ++} ++ ++define i64 @li7ffffffffffff800() { ++; CHECK-LABEL: li7ffffffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372036854773760 ++} ++ ++define i64 @li7fffffffffffffff() { ++; CHECK-LABEL: li7fffffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 9223372036854775807 ++} ++ ++define i64 @li8000000000000000() { ++; CHECK-LABEL: li8000000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu52i.d $r4, $zero, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372036854775808 ++} ++ ++define i64 @li80000000000007ff() { ++; CHECK-LABEL: li80000000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372036854773761 ++} ++ ++define i64 @li8000000000000800() { ++; CHECK-LABEL: li8000000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372036854773760 ++} ++ ++define i64 @li8000000000000fff() { ++; CHECK-LABEL: li8000000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372036854771713 ++} ++ ++define i64 @li800000007ffff000() { ++; CHECK-LABEL: li800000007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707296256 ++} ++ ++define i64 @li800000007ffff7ff() { ++; CHECK-LABEL: li800000007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707294209 ++} ++ ++define i64 @li800000007ffff800() { ++; CHECK-LABEL: li800000007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707294208 ++} ++ ++define i64 @li800000007fffffff() { ++; CHECK-LABEL: li800000007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707292161 ++} ++ ++define i64 @li8000000080000000() { ++; CHECK-LABEL: li8000000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707292160 ++} ++ ++define i64 @li80000000800007ff() { ++; CHECK-LABEL: li80000000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707290113 ++} ++ ++define i64 @li8000000080000800() { ++; CHECK-LABEL: li8000000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707290112 ++} ++ ++define i64 @li8000000080000fff() { ++; CHECK-LABEL: li8000000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372034707288065 ++} ++ ++define i64 @li80000000fffff000() { ++; CHECK-LABEL: li80000000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372032559812608 ++} ++ ++define i64 @li80000000fffff7ff() { ++; CHECK-LABEL: li80000000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372032559810561 ++} ++ ++define i64 @li80000000fffff800() { ++; CHECK-LABEL: li80000000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372032559810560 ++} ++ ++define i64 @li80000000ffffffff() { ++; CHECK-LABEL: li80000000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9223372032559808513 ++} ++ ++define i64 @li8007ffff00000000() { ++; CHECK-LABEL: li8007ffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120241336057856 ++} ++ ++define i64 @li8007ffff000007ff() { ++; CHECK-LABEL: li8007ffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120241336055809 ++} ++ ++define i64 @li8007ffff00000800() { ++; CHECK-LABEL: li8007ffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120241336055808 ++} ++ ++define i64 @li8007ffff00000fff() { ++; CHECK-LABEL: li8007ffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120241336053761 ++} ++ ++define i64 @li8007ffff7ffff000() { ++; CHECK-LABEL: li8007ffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188578304 ++} ++ ++define i64 @li8007ffff7ffff7ff() { ++; CHECK-LABEL: li8007ffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188576257 ++} ++ ++define i64 @li8007ffff7ffff800() { ++; CHECK-LABEL: li8007ffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188576256 ++} ++ ++define i64 @li8007ffff7fffffff() { ++; CHECK-LABEL: li8007ffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188574209 ++} ++ ++define i64 @li8007ffff80000000() { ++; CHECK-LABEL: li8007ffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188574208 ++} ++ ++define i64 @li8007ffff800007ff() { ++; CHECK-LABEL: li8007ffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188572161 ++} ++ ++define i64 @li8007ffff80000800() { ++; CHECK-LABEL: li8007ffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188572160 ++} ++ ++define i64 @li8007ffff80000fff() { ++; CHECK-LABEL: li8007ffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120239188570113 ++} ++ ++define i64 @li8007fffffffff000() { ++; CHECK-LABEL: li8007fffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041094656 ++} ++ ++define i64 @li8007fffffffff7ff() { ++; CHECK-LABEL: li8007fffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041092609 ++} ++ ++define i64 @li8007fffffffff800() { ++; CHECK-LABEL: li8007fffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041092608 ++} ++ ++define i64 @li8007ffffffffffff() { ++; CHECK-LABEL: li8007ffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041090561 ++} ++ ++define i64 @li8008000000000000() { ++; CHECK-LABEL: li8008000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041090560 ++} ++ ++define i64 @li80080000000007ff() { ++; CHECK-LABEL: li80080000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041088513 ++} ++ ++define i64 @li8008000000000800() { ++; CHECK-LABEL: li8008000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041088512 ++} ++ ++define i64 @li8008000000000fff() { ++; CHECK-LABEL: li8008000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120237041086465 ++} ++ ++define i64 @li800800007ffff000() { ++; CHECK-LABEL: li800800007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893611008 ++} ++ ++define i64 @li800800007ffff7ff() { ++; CHECK-LABEL: li800800007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893608961 ++} ++ ++define i64 @li800800007ffff800() { ++; CHECK-LABEL: li800800007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893608960 ++} ++ ++define i64 @li800800007fffffff() { ++; CHECK-LABEL: li800800007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893606913 ++} ++ ++define i64 @li8008000080000000() { ++; CHECK-LABEL: li8008000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893606912 ++} ++ ++define i64 @li80080000800007ff() { ++; CHECK-LABEL: li80080000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893604865 ++} ++ ++define i64 @li8008000080000800() { ++; CHECK-LABEL: li8008000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893604864 ++} ++ ++define i64 @li8008000080000fff() { ++; CHECK-LABEL: li8008000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120234893602817 ++} ++ ++define i64 @li80080000fffff000() { ++; CHECK-LABEL: li80080000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120232746127360 ++} ++ ++define i64 @li80080000fffff7ff() { ++; CHECK-LABEL: li80080000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120232746125313 ++} ++ ++define i64 @li80080000fffff800() { ++; CHECK-LABEL: li80080000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120232746125312 ++} ++ ++define i64 @li80080000ffffffff() { ++; CHECK-LABEL: li80080000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9221120232746123265 ++} ++ ++define i64 @li800fffff00000000() { ++; CHECK-LABEL: li800fffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868441522372608 ++} ++ ++define i64 @li800fffff000007ff() { ++; CHECK-LABEL: li800fffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868441522370561 ++} ++ ++define i64 @li800fffff00000800() { ++; CHECK-LABEL: li800fffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868441522370560 ++} ++ ++define i64 @li800fffff00000fff() { ++; CHECK-LABEL: li800fffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868441522368513 ++} ++ ++define i64 @li800fffff7ffff000() { ++; CHECK-LABEL: li800fffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374893056 ++} ++ ++define i64 @li800fffff7ffff7ff() { ++; CHECK-LABEL: li800fffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374891009 ++} ++ ++define i64 @li800fffff7ffff800() { ++; CHECK-LABEL: li800fffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374891008 ++} ++ ++define i64 @li800fffff7fffffff() { ++; CHECK-LABEL: li800fffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374888961 ++} ++ ++define i64 @li800fffff80000000() { ++; CHECK-LABEL: li800fffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374888960 ++} ++ ++define i64 @li800fffff800007ff() { ++; CHECK-LABEL: li800fffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374886913 ++} ++ ++define i64 @li800fffff80000800() { ++; CHECK-LABEL: li800fffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374886912 ++} ++ ++define i64 @li800fffff80000fff() { ++; CHECK-LABEL: li800fffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868439374884865 ++} ++ ++define i64 @li800ffffffffff000() { ++; CHECK-LABEL: li800ffffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868437227409408 ++} ++ ++define i64 @li800ffffffffff7ff() { ++; CHECK-LABEL: li800ffffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868437227407361 ++} ++ ++define i64 @li800ffffffffff800() { ++; CHECK-LABEL: li800ffffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868437227407360 ++} ++ ++define i64 @li800fffffffffffff() { ++; CHECK-LABEL: li800fffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -9218868437227405313 ++} ++ ++define i64 @lifff0000000000000() { ++; CHECK-LABEL: lifff0000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu52i.d $r4, $zero, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503599627370496 ++} ++ ++define i64 @lifff00000000007ff() { ++; CHECK-LABEL: lifff00000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503599627368449 ++} ++ ++define i64 @lifff0000000000800() { ++; CHECK-LABEL: lifff0000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503599627368448 ++} ++ ++define i64 @lifff0000000000fff() { ++; CHECK-LABEL: lifff0000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503599627366401 ++} ++ ++define i64 @lifff000007ffff000() { ++; CHECK-LABEL: lifff000007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479890944 ++} ++ ++define i64 @lifff000007ffff7ff() { ++; CHECK-LABEL: lifff000007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479888897 ++} ++ ++define i64 @lifff000007ffff800() { ++; CHECK-LABEL: lifff000007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479888896 ++} ++ ++define i64 @lifff000007fffffff() { ++; CHECK-LABEL: lifff000007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479886849 ++} ++ ++define i64 @lifff0000080000000() { ++; CHECK-LABEL: lifff0000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479886848 ++} ++ ++define i64 @lifff00000800007ff() { ++; CHECK-LABEL: lifff00000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479884801 ++} ++ ++define i64 @lifff0000080000800() { ++; CHECK-LABEL: lifff0000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479884800 ++} ++ ++define i64 @lifff0000080000fff() { ++; CHECK-LABEL: lifff0000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503597479882753 ++} ++ ++define i64 @lifff00000fffff000() { ++; CHECK-LABEL: lifff00000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503595332407296 ++} ++ ++define i64 @lifff00000fffff7ff() { ++; CHECK-LABEL: lifff00000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503595332405249 ++} ++ ++define i64 @lifff00000fffff800() { ++; CHECK-LABEL: lifff00000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503595332405248 ++} ++ ++define i64 @lifff00000ffffffff() { ++; CHECK-LABEL: lifff00000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4503595332403201 ++} ++ ++define i64 @lifff7ffff00000000() { ++; CHECK-LABEL: lifff7ffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251804108652544 ++} ++ ++define i64 @lifff7ffff000007ff() { ++; CHECK-LABEL: lifff7ffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251804108650497 ++} ++ ++define i64 @lifff7ffff00000800() { ++; CHECK-LABEL: lifff7ffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251804108650496 ++} ++ ++define i64 @lifff7ffff00000fff() { ++; CHECK-LABEL: lifff7ffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251804108648449 ++} ++ ++define i64 @lifff7ffff7ffff000() { ++; CHECK-LABEL: lifff7ffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961172992 ++} ++ ++define i64 @lifff7ffff7ffff7ff() { ++; CHECK-LABEL: lifff7ffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961170945 ++} ++ ++define i64 @lifff7ffff7ffff800() { ++; CHECK-LABEL: lifff7ffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961170944 ++} ++ ++define i64 @lifff7ffff7fffffff() { ++; CHECK-LABEL: lifff7ffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961168897 ++} ++ ++define i64 @lifff7ffff80000000() { ++; CHECK-LABEL: lifff7ffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961168896 ++} ++ ++define i64 @lifff7ffff800007ff() { ++; CHECK-LABEL: lifff7ffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961166849 ++} ++ ++define i64 @lifff7ffff80000800() { ++; CHECK-LABEL: lifff7ffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961166848 ++} ++ ++define i64 @lifff7ffff80000fff() { ++; CHECK-LABEL: lifff7ffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251801961164801 ++} ++ ++define i64 @lifff7fffffffff000() { ++; CHECK-LABEL: lifff7fffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813689344 ++} ++ ++define i64 @lifff7fffffffff7ff() { ++; CHECK-LABEL: lifff7fffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813687297 ++} ++ ++define i64 @lifff7fffffffff800() { ++; CHECK-LABEL: lifff7fffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813687296 ++} ++ ++define i64 @lifff7ffffffffffff() { ++; CHECK-LABEL: lifff7ffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813685249 ++} ++ ++define i64 @lifff8000000000000() { ++; CHECK-LABEL: lifff8000000000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813685248 ++} ++ ++define i64 @lifff80000000007ff() { ++; CHECK-LABEL: lifff80000000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813683201 ++} ++ ++define i64 @lifff8000000000800() { ++; CHECK-LABEL: lifff8000000000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813683200 ++} ++ ++define i64 @lifff8000000000fff() { ++; CHECK-LABEL: lifff8000000000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251799813681153 ++} ++ ++define i64 @lifff800007ffff000() { ++; CHECK-LABEL: lifff800007ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666205696 ++} ++ ++define i64 @lifff800007ffff7ff() { ++; CHECK-LABEL: lifff800007ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666203649 ++} ++ ++define i64 @lifff800007ffff800() { ++; CHECK-LABEL: lifff800007ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666203648 ++} ++ ++define i64 @lifff800007fffffff() { ++; CHECK-LABEL: lifff800007fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666201601 ++} ++ ++define i64 @lifff8000080000000() { ++; CHECK-LABEL: lifff8000080000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666201600 ++} ++ ++define i64 @lifff80000800007ff() { ++; CHECK-LABEL: lifff80000800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666199553 ++} ++ ++define i64 @lifff8000080000800() { ++; CHECK-LABEL: lifff8000080000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666199552 ++} ++ ++define i64 @lifff8000080000fff() { ++; CHECK-LABEL: lifff8000080000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251797666197505 ++} ++ ++define i64 @lifff80000fffff000() { ++; CHECK-LABEL: lifff80000fffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251795518722048 ++} ++ ++define i64 @lifff80000fffff7ff() { ++; CHECK-LABEL: lifff80000fffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251795518720001 ++} ++ ++define i64 @lifff80000fffff800() { ++; CHECK-LABEL: lifff80000fffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251795518720000 ++} ++ ++define i64 @lifff80000ffffffff() { ++; CHECK-LABEL: lifff80000ffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2251795518717953 ++} ++ ++define i64 @liffffffff00000000() { ++; CHECK-LABEL: liffffffff00000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4294967296 ++} ++ ++define i64 @liffffffff000007ff() { ++; CHECK-LABEL: liffffffff000007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4294965249 ++} ++ ++define i64 @liffffffff00000800() { ++; CHECK-LABEL: liffffffff00000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4294965248 ++} ++ ++define i64 @liffffffff00000fff() { ++; CHECK-LABEL: liffffffff00000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4294963201 ++} ++ ++define i64 @liffffffff7ffff000() { ++; CHECK-LABEL: liffffffff7ffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147487744 ++} ++ ++define i64 @liffffffff7ffff7ff() { ++; CHECK-LABEL: liffffffff7ffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147485697 ++} ++ ++define i64 @liffffffff7ffff800() { ++; CHECK-LABEL: liffffffff7ffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147485696 ++} ++ ++define i64 @liffffffff7fffffff() { ++; CHECK-LABEL: liffffffff7fffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147483649 ++} ++ ++define i64 @liffffffff80000000() { ++; CHECK-LABEL: liffffffff80000000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147483648 ++} ++ ++define i64 @liffffffff800007ff() { ++; CHECK-LABEL: liffffffff800007ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147481601 ++} ++ ++define i64 @liffffffff80000800() { ++; CHECK-LABEL: liffffffff80000800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147481600 ++} ++ ++define i64 @liffffffff80000fff() { ++; CHECK-LABEL: liffffffff80000fff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 4095 ++; CHECK-NEXT: jr $ra ++ ret i64 -2147479553 ++} ++ ++define i64 @lifffffffffffff000() { ++; CHECK-LABEL: lifffffffffffff000: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -4096 ++} ++ ++define i64 @lifffffffffffff7ff() { ++; CHECK-LABEL: lifffffffffffff7ff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: jr $ra ++ ret i64 -2049 ++} ++ ++define i64 @lifffffffffffff800() { ++; CHECK-LABEL: lifffffffffffff800: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r4, $zero, -2048 ++; CHECK-NEXT: jr $ra ++ ret i64 -2048 ++} ++ ++define i64 @liffffffffffffffff() { ++; CHECK-LABEL: liffffffffffffffff: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.d $r4, $zero, -1 ++; CHECK-NEXT: jr $ra ++ ret i64 -1 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll +new file mode 100644 +index 000000000..986e27e2a +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/extra-code.ll +@@ -0,0 +1,8 @@ ++; RUN: llc -march=loongarch64 -no-integrated-as -o - %s | FileCheck %s ++ ++define i64 @test(i64 %a) { ++; CHECK: add.d $r4, $r4, $r0 ++entry: ++ %0 = tail call i64 asm sideeffect "add.d $0, $1, ${2:z} \0A", "=r,r,Jr"(i64 %a, i64 0) ++ ret i64 %0 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll +new file mode 100644 +index 000000000..94e330673 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll +@@ -0,0 +1,31 @@ ++; RUN: llc -march=loongarch64 -target-abi=lp64 -o - %s 2>&1 | FileCheck %s ++ ++;; Test that floating-point bits can be stored in GPR. ++ ++define void @reg_float(float %x) { ++; CHECK-LABEL: reg_float: ++; CHECK: movfr2gr.s $r{{[0-9]+}}, $f0 ++ call void asm "", "r"(float %x) ++ ret void ++} ++ ++define void @r10_float(float %x) { ++; CHECK-LABEL: r10_float: ++; CHECK: movfr2gr.s $r10, $f0 ++ call void asm "", "{$r10}"(float %x) ++ ret void ++} ++ ++define void @reg_double(double %x) { ++; CHECK-LABEL: reg_double: ++; CHECK: movfr2gr.d $r{{[0-9]+}}, $f0 ++ call void asm "", "r"(double %x) ++ ret void ++} ++ ++define void @r10_double(double %x) { ++; CHECK-LABEL: r10_double: ++; CHECK: movfr2gr.d $r10, $f0 ++ call void asm "", "{$r10}"(double %x) ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll +new file mode 100644 +index 000000000..7f58ea2ee +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll +@@ -0,0 +1,8 @@ ++; RUN: not llc -march=loongarch64 %s 2>&1 | FileCheck %s ++ ++define void @test_i128() { ++; CHECK: error: couldn't allocate input reg for constraint '{$r20}' ++start: ++ call void asm "", "{$r20}"(i128 5) ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll +new file mode 100644 +index 000000000..d18a184ab +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll +@@ -0,0 +1,42 @@ ++; RUN: llc -march=loongarch64 -o - %s 2>&1 | FileCheck %s ++ ++;; Test that non native value types can be parsed. ++ ++define void @test_i1() { ++; CHECK-LABEL: test_i1: ++; CHECK: ori $r6, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r6}"(i1 0) ++ ret void ++} ++ ++;; Note: non-simple values like `i3` are only allowed in newer llvm versions (>= 12). ++;; In older llvm versions (<= 11), SelectionDAGBuilder::visitInlineAsm asserts simple ++;; values must be used. For details, please see https://reviews.llvm.org/D91710. ++define void @test_i3() { ++; CHECK-LABEL: test_i3: ++; CHECK: ori $r7, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r7}"(i3 0) ++ ret void ++} ++ ++define void @test_i8() { ++; CHECK-LABEL: test_i8: ++; CHECK: ori $r5, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r5}"(i8 0) ++ ret void ++} ++ ++define void @test_i16() { ++; CHECK-LABEL: test_i16: ++; CHECK: ori $r20, $zero, 5 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r20}"(i16 5) ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll +new file mode 100644 +index 000000000..8dbbed99f +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/inlineasm/preld.ll +@@ -0,0 +1,8 @@ ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define void @preld(i32* %p) { ++entry: ++ ; CHECK: preld 10, $r4, 23 ++ tail call void asm sideeffect "preld 10, $0, 23 \0A\09", "r"(i32* %p) ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll +new file mode 100644 +index 000000000..70b588bea +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/jirl-verify.ll +@@ -0,0 +1,34 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -verify-machineinstrs -o - %s \ ++; RUN: | FileCheck %s --check-prefix=STATIC ++; RUN: llc -march=loongarch64 -verify-machineinstrs -relocation-model=pic --code-model=large -o - %s \ ++; RUN: | FileCheck %s --check-prefix=LARGE ++ ++define void @test() nounwind { ++; STATIC-LABEL: test: ++; STATIC: # %bb.0: ++; STATIC-NEXT: addi.d $sp, $sp, -16 ++; STATIC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; STATIC-NEXT: lu12i.w $ra, foo ++; STATIC-NEXT: ori $ra, $ra, foo ++; STATIC-NEXT: lu32i.d $ra, foo ++; STATIC-NEXT: lu52i.d $ra, $ra, foo ++; STATIC-NEXT: jirl $ra, $ra, 0 ++; STATIC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; STATIC-NEXT: addi.d $sp, $sp, 16 ++; STATIC-NEXT: jr $ra ++; ++; LARGE-LABEL: test: ++; LARGE: # %bb.0: ++; LARGE-NEXT: addi.d $sp, $sp, -16 ++; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; LARGE-NEXT: pcaddu18i $ra, foo ++; LARGE-NEXT: jirl $ra, $ra, foo ++; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; LARGE-NEXT: addi.d $sp, $sp, 16 ++; LARGE-NEXT: jr $ra ++ call void @foo() nounwind ++ ret void ++} ++ ++declare void @foo() +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll +new file mode 100644 +index 000000000..1b4b52c7a +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/VExtend.ll +@@ -0,0 +1,54 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @uvadd(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvadd: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvhaddw.du.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> ++ %1 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> ++ %2 = add <4 x i32> %0, %1 ++ %3 = zext <4 x i32> %2 to <4 x i64> ++ ret <4 x i64> %3 ++} ++ ++define <4 x i64> @svadd(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svadd: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvhaddw.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> ++ %1 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> ++ %2 = add nsw <4 x i32> %0, %1 ++ %3 = sext <4 x i32> %2 to <4 x i64> ++ ret <4 x i64> %3 ++} ++ ++define <4 x i64> @uvsub(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvsub: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvhsubw.du.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> ++ %1 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> ++ %2 = sub <4 x i32> %0, %1 ++ %3 = zext <4 x i32> %2 to <4 x i64> ++ ret <4 x i64> %3 ++} ++ ++define <4 x i64> @svsub(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svsub: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvhsubw.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = shufflevector <8 x i32> %b, <8 x i32> undef, <4 x i32> ++ %1 = shufflevector <8 x i32> %c, <8 x i32> undef, <4 x i32> ++ %2 = sub nsw <4 x i32> %0, %1 ++ %3 = sext <4 x i32> %2 to <4 x i64> ++ ret <4 x i64> %3 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll +new file mode 100644 +index 000000000..07b80895b +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/imm_vector_lasx.ll +@@ -0,0 +1,176 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @build_lasx0(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx0: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx1(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx1: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu52i.d $r4, $zero, 2047 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx2(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx2: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx3(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx3: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx4(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx4: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx5(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx5: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx6(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx6: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx7(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx7: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx8(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx9(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx9: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx10(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx10: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx11(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx11: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx12(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx12: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} ++ ++define <4 x i64> @build_lasx13(<4 x i64> %a) { ++; CHECK-LABEL: build_lasx13: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: xvreplgr2vr.d $xr1, $r4 ++; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %b = add <4 x i64> %a, ++ ret <4 x i64> %b ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll +new file mode 100644 +index 000000000..337632491 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll +@@ -0,0 +1,55 @@ ++; A basic inline assembly test ++ ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++@v4i64_r = global <4 x i64> zeroinitializer, align 32 ++@v8i32_r = global <8 x i32> zeroinitializer, align 32 ++ ++define void @test1() nounwind { ++entry: ++ ; CHECK-LABEL: test1: ++ %0 = call <4 x i64> asm "xvldi ${0:u}, 1", "=f"() ++ ; CHECK: xvldi $xr{{[1-3]?[0-9]}}, 1 ++ store <4 x i64> %0, <4 x i64>* @v4i64_r ++ ret void ++} ++ ++define void @test2() nounwind { ++entry: ++ ; CHECK-LABEL: test2: ++ %0 = load <8 x i32>, <8 x i32>* @v8i32_r ++ %1 = call <8 x i32> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(<8 x i32> %0) ++ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 ++ store <8 x i32> %1, <8 x i32>* @v8i32_r ++ ret void ++} ++ ++define void @test2_d() nounwind { ++entry: ++ ; CHECK-LABEL: test2_d: ++ %0 = load < 4 x i64>, < 4 x i64>* @v4i64_r ++ %1 = call < 4 x i64> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(< 4 x i64> %0) ++ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 ++ store < 4 x i64> %1, < 4 x i64>* @v4i64_r ++ ret void ++} ++ ++define void @test3() nounwind { ++entry: ++ ; CHECK-LABEL: test3: ++ %0 = load <8 x i32>, <8 x i32>* @v8i32_r ++ %1 = call <8 x i32> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<8 x i32> %0) ++ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 ++ store <8 x i32> %1, <8 x i32>* @v8i32_r ++ ret void ++} ++ ++define void @test3_d() nounwind { ++entry: ++ ; CHECK-LABEL: test3_d: ++ %0 = load <4 x i64>, <4 x i64>* @v4i64_r ++ %1 = call <4 x i64> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<4 x i64> %0) ++ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 ++ store <4 x i64> %1, <4 x i64>* @v4i64_r ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll +new file mode 100644 +index 000000000..51fa34606 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/insert-lasx.ll +@@ -0,0 +1,38 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <16 x i16> @lasxH(<16 x i16> %d, <8 x i16> %s1) { ++; CHECK-LABEL: lasxH: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 ++; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 ++; CHECK-NEXT: jr $ra ++entry: ++ %r1 = shufflevector <8 x i16> %s1, <8 x i16> poison, <16 x i32> ++ %r2 = shufflevector <16 x i16> %r1, <16 x i16> %d, <16 x i32> ++ ret <16 x i16> %r2 ++} ++ ++define <8 x i32> @lasxW(<8 x i32> %d, <4 x i32> %s1) { ++; CHECK-LABEL: lasxW: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 ++; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 ++; CHECK-NEXT: jr $ra ++entry: ++ %r1 = shufflevector <4 x i32> %s1, <4 x i32> poison, <8 x i32> ++ %r2 = shufflevector <8 x i32> %r1, <8 x i32> %d, <8 x i32> ++ ret <8 x i32> %r2 ++} ++ ++define <4 x i64> @lasxD(<4 x i64> %d, <2 x i64> %s1) { ++; CHECK-LABEL: lasxD: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: # kill: def $vr1 killed $vr1 def $xr1 ++; CHECK-NEXT: xvpermi.q $xr0, $xr1, 48 ++; CHECK-NEXT: jr $ra ++entry: ++ %r1 = shufflevector <2 x i64> %s1, <2 x i64> poison, <4 x i32> ++ %r2 = shufflevector <4 x i64> %r1, <4 x i64> %d, <4 x i32> ++ ret <4 x i64> %r2 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll +new file mode 100644 +index 000000000..05b720077 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/intrinsic-lasx.ll +@@ -0,0 +1,70 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++declare <32 x i8> @llvm.loongarch.lasx.xvrepli.b(i32) ++declare <16 x i16> @llvm.loongarch.lasx.xvrepli.h(i32) ++declare <8 x i32> @llvm.loongarch.lasx.xvrepli.w(i32) ++declare <4 x i64> @llvm.loongarch.lasx.xvrepli.d(i32) ++ ++declare <4 x double> @llvm.loongarch.lasx.xvpickve.d.f(<4 x double>, i32) ++declare <8 x float> @llvm.loongarch.lasx.xvpickve.w.f(<8 x float>, i32) ++ ++define <32 x i8> @lasx_xvrepli_b() { ++; CHECK-LABEL: lasx_xvrepli_b: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvldi $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <32 x i8> @llvm.loongarch.lasx.xvrepli.b(i32 2) ++ ret <32 x i8> %0 ++} ++ ++define <16 x i16> @lasx_xvrepli_h() { ++; CHECK-LABEL: lasx_xvrepli_h: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvldi $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <16 x i16> @llvm.loongarch.lasx.xvrepli.h(i32 2) ++ ret <16 x i16> %0 ++} ++ ++define <8 x i32> @lasx_xvrepli_w() { ++; CHECK-LABEL: lasx_xvrepli_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvldi $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <8 x i32> @llvm.loongarch.lasx.xvrepli.w(i32 2) ++ ret <8 x i32> %0 ++} ++ ++define <4 x i64> @lasx_xvrepli_d() { ++; CHECK-LABEL: lasx_xvrepli_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvldi $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <4 x i64> @llvm.loongarch.lasx.xvrepli.d(i32 2) ++ ret <4 x i64> %0 ++} ++ ++define <4 x double> @lasx_xvpickve_d_f(<4 x double> %a) { ++; CHECK-LABEL: lasx_xvpickve_d_f: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvpickve.d $xr0, $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <4 x double> @llvm.loongarch.lasx.xvpickve.d.f(<4 x double> %a, i32 2) ++ ret <4 x double> %0 ++} ++ ++define <8 x float> @lasx_xvpickve_w_f(<8 x float> %a) { ++; CHECK-LABEL: lasx_xvpickve_w_f: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvpickve.w $xr0, $xr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <8 x float> @llvm.loongarch.lasx.xvpickve.w.f(<8 x float> %a, i32 2) ++ ret <8 x float> %0 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll +new file mode 100644 +index 000000000..b40698104 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/lasxvclr.ll +@@ -0,0 +1,46 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <32 x i8> @clri8(<32 x i8> %0, <32 x i8> %1) { ++; CHECK-LABEL: clri8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitclr.b $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = shl <32 x i8> , %1 ++ %4 = xor <32 x i8> %3, ++ %5 = and <32 x i8> %4, %0 ++ ret <32 x i8> %5 ++} ++ ++define <16 x i16> @clri16(<16 x i16> %0, <16 x i16> %1) { ++; CHECK-LABEL: clri16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitclr.h $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = shl <16 x i16> , %1 ++ %4 = xor <16 x i16> %3, ++ %5 = and <16 x i16> %4, %0 ++ ret <16 x i16> %5 ++} ++ ++define <8 x i32> @clri32(<8 x i32> %0, <8 x i32> %1) { ++; CHECK-LABEL: clri32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitclr.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = shl <8 x i32> , %1 ++ %4 = xor <8 x i32> %3, ++ %5 = and <8 x i32> %4, %0 ++ ret <8 x i32> %5 ++} ++ ++define <4 x i64> @clri64(<4 x i64> %0, <4 x i64> %1) { ++; CHECK-LABEL: clri64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitclr.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = shl <4 x i64> , %1 ++ %4 = xor <4 x i64> %3, ++ %5 = and <4 x i64> %4, %0 ++ ret <4 x i64> %5 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll +new file mode 100644 +index 000000000..ff28569a1 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/logic-lasx.ll +@@ -0,0 +1,130 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @not_v4i64(<4 x i64> %a) { ++; CHECK-LABEL: not_v4i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i64> %a, ++ ret <4 x i64> %not ++} ++ ++define <8 x i32> @not_v8i32(<8 x i32> %a) { ++; CHECK-LABEL: not_v8i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i32> %a, ++ ret <8 x i32> %not ++} ++ ++define <16 x i16> @not_v16i16(<16 x i16> %a) { ++; CHECK-LABEL: not_v16i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvnor.v $xr0, $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i16> %a, ++ ret <16 x i16> %not ++} ++ ++define <32 x i8> @not_v32i8(<32 x i8> %a) { ++; CHECK-LABEL: not_v32i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvxori.b $xr0, $xr0, 255 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <32 x i8> %a, ++ ret <32 x i8> %not ++} ++ ++define <4 x i64> @andn_v4i64(<4 x i64> %a, <4 x i64> %b) { ++; CHECK-LABEL: andn_v4i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i64> %b, ++ %and = and <4 x i64> %not, %a ++ ret <4 x i64> %and ++} ++ ++define <8 x i32> @andn_v8i32(<8 x i32> %a, <8 x i32> %b) { ++; CHECK-LABEL: andn_v8i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i32> %b, ++ %and = and <8 x i32> %not, %a ++ ret <8 x i32> %and ++} ++ ++define <16 x i16> @andn_v16i16(<16 x i16> %a, <16 x i16> %b) { ++; CHECK-LABEL: andn_v16i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i16> %b, ++ %and = and <16 x i16> %not, %a ++ ret <16 x i16> %and ++} ++ ++define <32 x i8> @andn_v32i8(<32 x i8> %a, <32 x i8> %b) { ++; CHECK-LABEL: andn_v32i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvandn.v $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <32 x i8> %b, ++ %and = and <32 x i8> %not, %a ++ ret <32 x i8> %and ++} ++ ++define <4 x i64> @orn_v4i64(<4 x i64> %a, <4 x i64> %b) { ++; CHECK-LABEL: orn_v4i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i64> %b, ++ %or = or <4 x i64> %not, %a ++ ret <4 x i64> %or ++} ++ ++define <8 x i32> @orn_v8i32(<8 x i32> %a, <8 x i32> %b) { ++; CHECK-LABEL: orn_v8i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i32> %b, ++ %or = or <8 x i32> %not, %a ++ ret <8 x i32> %or ++} ++ ++define <16 x i16> @orn_v16i16(<16 x i16> %a, <16 x i16> %b) { ++; CHECK-LABEL: orn_v16i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i16> %b, ++ %or = or <16 x i16> %not, %a ++ ret <16 x i16> %or ++} ++ ++define <32 x i8> @orn_v32i8(<32 x i8> %a, <32 x i8> %b) { ++; CHECK-LABEL: orn_v32i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvorn.v $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <32 x i8> %b, ++ %or = or <32 x i8> %not, %a ++ ret <32 x i8> %or ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll +new file mode 100644 +index 000000000..443262eac +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/set-lasx.ll +@@ -0,0 +1,38 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <32 x i8> @seti8(<32 x i8>) { ++; CHECK-LABEL: seti8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitseti.b $xr0, $xr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <32 x i8> %0, ++ ret <32 x i8> %2 ++} ++ ++define <16 x i16> @seti16(<16 x i16>) { ++; CHECK-LABEL: seti16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitseti.h $xr0, $xr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <16 x i16> %0, ++ ret <16 x i16> %2 ++} ++ ++define <8 x i32> @seti32(<8 x i32>) { ++; CHECK-LABEL: seti32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitseti.w $xr0, $xr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <8 x i32> %0, ++ ret <8 x i32> %2 ++} ++ ++define <4 x i64> @seti64(<4 x i64>) { ++; CHECK-LABEL: seti64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvbitseti.d $xr0, $xr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <4 x i64> %0, ++ ret <4 x i64> %2 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll +new file mode 100644 +index 000000000..965cfe94c +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/shuffle_v4i64_1032.ll +@@ -0,0 +1,19 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @shuffle_v4i64_1032(<4 x i64> %vj, <4 x i64> %vk) { ++; CHECK-LABEL: shuffle_v4i64_1032: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvpickve2gr.d $r4, $xr0, 2 ++; CHECK-NEXT: xvpickve2gr.d $r5, $xr0, 3 ++; CHECK-NEXT: xvpickve2gr.d $r6, $xr0, 0 ++; CHECK-NEXT: xvpickve2gr.d $r7, $xr0, 1 ++; CHECK-NEXT: xvinsgr2vr.d $xr0, $r7, 0 ++; CHECK-NEXT: xvinsgr2vr.d $xr0, $r6, 1 ++; CHECK-NEXT: xvinsgr2vr.d $xr0, $r5, 2 ++; CHECK-NEXT: xvinsgr2vr.d $xr0, $r4, 3 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <4 x i64> %vj, <4 x i64> %vk, <4 x i32> ++ ret <4 x i64> %vd ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll +new file mode 100644 +index 000000000..7bd3dca73 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/vext2xv.ll +@@ -0,0 +1,65 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @s_v4i32_v4i64(<4 x i32> %a0) { ++; CHECK-LABEL: s_v4i32_v4i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.d.w $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ %1 = sext <4 x i32> %a0 to <4 x i64> ++ ret <4 x i64> %1 ++} ++ ++define <4 x i64> @z_v4i32_v4i64(<4 x i32> %a0) { ++; CHECK-LABEL: z_v4i32_v4i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ %1 = zext <4 x i32> %a0 to <4 x i64> ++ ret <4 x i64> %1 ++} ++ ++define <16 x i16> @s_v16i8_v16i16(<16 x i8> %A) { ++; CHECK-LABEL: s_v16i8_v16i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.h.b $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ entry: ++ %B = sext <16 x i8> %A to <16 x i16> ++ ret <16 x i16> %B ++} ++ ++define <16 x i16> @z_v16i8_v16i16(<16 x i8> %A) { ++; CHECK-LABEL: z_v16i8_v16i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ entry: ++ %B = zext <16 x i8> %A to <16 x i16> ++ ret <16 x i16> %B ++} ++ ++define <8 x i32> @s_v8i16_v8i32(<8 x i16> %x) { ++; CHECK-LABEL: s_v8i16_v8i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.w.h $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ %1 = sext <8 x i16> %x to <8 x i32> ++ ret <8 x i32> %1 ++} ++ ++define <8 x i32> @z_v8i16_v8i32(<8 x i16> %x) { ++; CHECK-LABEL: z_v8i16_v8i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: # kill: def $vr0 killed $vr0 def $xr0 ++; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0 ++; CHECK-NEXT: jr $ra ++ %1 = zext <8 x i16> %x to <8 x i32> ++ ret <8 x i32> %1 ++} ++ +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll +new file mode 100644 +index 000000000..a849fef3e +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvadda.ll +@@ -0,0 +1,62 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <32 x i8> @xvaddab(<32 x i8>, <32 x i8>) { ++; CHECK-LABEL: xvaddab: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvadda.b $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <32 x i8> %0, zeroinitializer ++ %4 = sub <32 x i8> zeroinitializer, %0 ++ %5 = select <32 x i1> %3, <32 x i8> %4, <32 x i8> %0 ++ %6 = icmp slt <32 x i8> %1, zeroinitializer ++ %7 = sub <32 x i8> zeroinitializer, %1 ++ %8 = select <32 x i1> %6, <32 x i8> %7, <32 x i8> %1 ++ %9 = add <32 x i8> %5, %8 ++ ret <32 x i8> %9 ++} ++ ++define <16 x i16> @xvaddah(<16 x i16>, <16 x i16>) { ++; CHECK-LABEL: xvaddah: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvadda.h $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <16 x i16> %0, zeroinitializer ++ %4 = sub <16 x i16> zeroinitializer, %0 ++ %5 = select <16 x i1> %3, <16 x i16> %4, <16 x i16> %0 ++ %6 = icmp slt <16 x i16> %1, zeroinitializer ++ %7 = sub <16 x i16> zeroinitializer, %1 ++ %8 = select <16 x i1> %6, <16 x i16> %7, <16 x i16> %1 ++ %9 = add <16 x i16> %5, %8 ++ ret <16 x i16> %9 ++} ++ ++define <8 x i32> @xvaddaw(<8 x i32>, <8 x i32>) { ++; CHECK-LABEL: xvaddaw: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvadda.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <8 x i32> %0, zeroinitializer ++ %4 = sub nsw <8 x i32> zeroinitializer, %0 ++ %5 = select <8 x i1> %3, <8 x i32> %4, <8 x i32> %0 ++ %6 = icmp slt <8 x i32> %1, zeroinitializer ++ %7 = sub nsw <8 x i32> zeroinitializer, %1 ++ %8 = select <8 x i1> %6, <8 x i32> %7, <8 x i32> %1 ++ %9 = add nuw nsw <8 x i32> %5, %8 ++ ret <8 x i32> %9 ++} ++ ++define <4 x i64> @xvaddad(<4 x i64>, <4 x i64>) { ++; CHECK-LABEL: xvaddad: ++; CHECK: # %bb.0: ++; CHECK-NEXT: xvadda.d $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <4 x i64> %0, zeroinitializer ++ %4 = sub nsw <4 x i64> zeroinitializer, %0 ++ %5 = select <4 x i1> %3, <4 x i64> %4, <4 x i64> %0 ++ %6 = icmp slt <4 x i64> %1, zeroinitializer ++ %7 = sub nsw <4 x i64> zeroinitializer, %1 ++ %8 = select <4 x i1> %6, <4 x i64> %7, <4 x i64> %1 ++ %9 = add nuw nsw <4 x i64> %5, %8 ++ ret <4 x i64> %9 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll +new file mode 100644 +index 000000000..eb2c493d2 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvaddsub.ll +@@ -0,0 +1,98 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @svaddev(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svaddev: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvaddwev.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = add nsw <8 x i32> %c, %b ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = sext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @uvaddev(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvaddev: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvaddwev.d.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = add <8 x i32> %c, %b ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = zext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @uvsubev(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvsubev: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvsubwev.d.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = sub <8 x i32> %b, %c ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = zext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @svsubev(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svsubev: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvsubwev.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = sub nsw <8 x i32> %b, %c ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = sext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @uvaddod(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvaddod: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvaddwod.d.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = add <8 x i32> %c, %b ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = zext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @svaddod(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svaddod: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvaddwod.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = add nsw <8 x i32> %c, %b ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = sext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @uvsubod(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: uvsubod: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvsubwod.d.wu $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = sub <8 x i32> %b, %c ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = zext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} ++ ++define <4 x i64> @svsubod(<8 x i32> %b, <8 x i32> %c) { ++; CHECK-LABEL: svsubod: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvsubwod.d.w $xr0, $xr0, $xr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = sub nsw <8 x i32> %b, %c ++ %1 = shufflevector <8 x i32> %0, <8 x i32> undef, <4 x i32> ++ %2 = sext <4 x i32> %1 to <4 x i64> ++ ret <4 x i64> %2 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll +new file mode 100644 +index 000000000..5b452c5eb +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvhadd.ll +@@ -0,0 +1,21 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <4 x i64> @mul(<4 x i64> %a, <8 x i32> %m, <8 x i32> %n) { ++; CHECK-LABEL: mul: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvhaddw.d.w $xr0, $xr1, $xr2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = shufflevector <8 x i32> %n, <8 x i32> undef, <2 x i32> ++ %1 = shufflevector <8 x i32> %m, <8 x i32> undef, <2 x i32> ++ %2 = add nsw <2 x i32> %0, %1 ++ %3 = sext <2 x i32> %2 to <2 x i64> ++ %4 = shufflevector <8 x i32> %n, <8 x i32> undef, <2 x i32> ++ %5 = shufflevector <8 x i32> %m, <8 x i32> undef, <2 x i32> ++ %6 = add nsw <2 x i32> %4, %5 ++ %7 = sext <2 x i32> %6 to <2 x i64> ++ %vecins16 = shufflevector <2 x i64> %3, <2 x i64> %7, <4 x i32> ++ ret <4 x i64> %vecins16 ++} ++ +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll +new file mode 100644 +index 000000000..11f96f435 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvh.ll +@@ -0,0 +1,32 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <32 x i8> @xvilvhb(<32 x i8> %vj, <32 x i8> %vk) { ++; CHECK-LABEL: xvilvhb: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvh.b $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <32 x i8> %vj, <32 x i8> %vk, <32 x i32> ++ ret <32 x i8> %vd ++} ++ ++define <16 x i16> @xvilvhh(<16 x i16> %vj, <16 x i16> %vk) { ++; CHECK-LABEL: xvilvhh: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvh.h $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <16 x i16> %vj, <16 x i16> %vk, <16 x i32> ++ ret <16 x i16> %vd ++} ++ ++define <8 x i32> @xvilvhw(<8 x i32> %vj, <8 x i32> %vk) { ++; CHECK-LABEL: xvilvhw: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvh.w $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <8 x i32> %vj, <8 x i32> %vk, <8 x i32> ++ ret <8 x i32> %vd ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll +new file mode 100644 +index 000000000..7249bc76c +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lasx/xvilvl.ll +@@ -0,0 +1,32 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s ++ ++define <32 x i8> @xvilvlb(<32 x i8> %vj, <32 x i8> %vk) { ++; CHECK-LABEL: xvilvlb: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvl.b $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <32 x i8> %vj, <32 x i8> %vk, <32 x i32> ++ ret <32 x i8> %vd ++} ++ ++define <16 x i16> @xvilvlh(<16 x i16> %vj, <16 x i16> %vk) { ++; CHECK-LABEL: xvilvlh: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvl.h $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <16 x i16> %vj, <16 x i16> %vk, <16 x i32> ++ ret <16 x i16> %vd ++} ++ ++define <8 x i32> @xvilvlw(<8 x i32> %vj, <8 x i32> %vk) { ++; CHECK-LABEL: xvilvlw: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xvilvl.w $xr0, $xr1, $xr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %vd = shufflevector <8 x i32> %vj, <8 x i32> %vk, <8 x i32> ++ ret <8 x i32> %vd ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll +new file mode 100644 +index 000000000..8395b264f +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/ldptr.ll +@@ -0,0 +1,70 @@ ++; Check whether ld.w/ld.d/ldptr.w/ldptr.d/ldx.w/ldx.d instructions are properly generated ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define signext i32 @ld_w(i32* %p) { ++; CHECK-LABEL: ld_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ld.w $r4, $r4, 2044 ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i32, i32* %p, i64 511 ++ %val = load i32, i32* %addr, align 4 ++ ret i32 %val ++} ++ ++define signext i32 @ldptr_w(i32* %p) { ++; CHECK-LABEL: ldptr_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ldptr.w $r4, $r4, 2048 ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i32, i32* %p, i64 512 ++ %val = load i32, i32* %addr, align 4 ++ ret i32 %val ++} ++ ++define signext i32 @ldx_w(i32* %p) { ++; CHECK-LABEL: ldx_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r[[REG:[0-9]+]], 8 ++; CHECK-NEXT: ldx.w $r4, $r4, $r[[REG:[0-9]+]] ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i32, i32* %p, i64 8192 ++ %val = load i32, i32* %addr, align 4 ++ ret i32 %val ++} ++ ++define i64 @ld_d(i64* %p) { ++; CHECK-LABEL: ld_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ld.d $r4, $r4, 2040 ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i64, i64* %p, i64 255 ++ %val = load i64, i64* %addr, align 8 ++ ret i64 %val ++} ++ ++define i64 @ldptr_d(i64* %p) { ++; CHECK-LABEL: ldptr_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ldptr.d $r4, $r4, 2048 ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i64, i64* %p, i64 256 ++ %val = load i64, i64* %addr, align 8 ++ ret i64 %val ++} ++ ++define i64 @ldx_d(i64* %p) { ++; CHECK-LABEL: ldx_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: lu12i.w $r[[REG:[0-9]+]], 8 ++; CHECK-NEXT: ldx.d $r4, $r4, $r[[REG:[0-9]+]] ++; CHECK-NEXT: jr $ra ++entry: ++ %addr = getelementptr inbounds i64, i64* %p, i64 4096 ++ %val = load i64, i64* %addr, align 8 ++ ret i64 %val ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg +index a54f5aeca..6223fc691 100644 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lit.local.cfg +@@ -1,13 +1,3 @@ +-import os +- +-config.suffixes = ['.ll', '.mir', '.test', '.txt'] +- +-extract_section_path = os.path.join(config.llvm_src_root, +- 'utils', 'extract-section.py') +- +-config.substitutions.append(('extract-section', +- "'%s' %s %s" % (config.python_executable, +- extract_section_path, '--bits-endian little'))) +- + if not 'LoongArch' in config.root.targets: + config.unsupported = True ++ +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll +new file mode 100644 +index 000000000..c1029c1ff +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/logic-op.ll +@@ -0,0 +1,171 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define signext i32 @foo32(i32 signext %a) { ++; CHECK-LABEL: foo32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: sltui $r4, $r4, 1 ++; CHECK-NEXT: jr $ra ++entry: ++ %tobool = icmp eq i32 %a, 0 ++ %conv = zext i1 %tobool to i32 ++ ret i32 %conv ++} ++ ++define i64 @foo(i64 %a) { ++; CHECK-LABEL: foo: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: sltui $r4, $r4, 1 ++; CHECK-NEXT: jr $ra ++entry: ++ %tobool = icmp eq i64 %a, 0 ++ %conv = zext i1 %tobool to i64 ++ ret i64 %conv ++} ++ ++define i64 @not(i64 %a) { ++; CHECK-LABEL: not: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i64 %a, -1 ++ ret i64 %not ++} ++ ++define i64 @and(i64 %a, i64 %b) { ++; CHECK-LABEL: and: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: and $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %and = and i64 %b, %a ++ ret i64 %and ++} ++ ++define i64 @or(i64 %a, i64 %b) { ++; CHECK-LABEL: or: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %or = or i64 %b, %a ++ ret i64 %or ++} ++ ++define i64 @xor(i64 %a, i64 %b) { ++; CHECK-LABEL: xor: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xor $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %xor = xor i64 %b, %a ++ ret i64 %xor ++} ++ ++define i64 @nor(i64 %a, i64 %b) { ++; CHECK-LABEL: nor: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: nor $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %or = or i64 %b, %a ++ %not = xor i64 %or, -1 ++ ret i64 %not ++} ++ ++define i64 @andn(i64 %a, i64 %b) { ++; CHECK-LABEL: andn: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i64 %b, -1 ++ %and = and i64 %not, %a ++ ret i64 %and ++} ++ ++define signext i32 @andn32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: andn32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i32 %b, -1 ++ %and = and i32 %not, %a ++ ret i32 %and ++} ++ ++define i64 @orn(i64 %a, i64 %b) { ++; CHECK-LABEL: orn: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: orn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i64 %b, -1 ++ %or = or i64 %not, %a ++ ret i64 %or ++} ++ ++define signext i32 @orn32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: orn32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: orn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i32 %b, -1 ++ %or = or i32 %not, %a ++ ret i32 %or ++} ++ ++define signext i32 @and32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: and32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: and $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %and = and i32 %b, %a ++ ret i32 %and ++} ++ ++define signext i32 @or32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: or32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %or = or i32 %b, %a ++ ret i32 %or ++} ++ ++define signext i32 @xor32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: xor32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: xor $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %xor = xor i32 %b, %a ++ ret i32 %xor ++} ++ ++define signext i32 @nor32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: nor32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: nor $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %or = or i32 %b, %a ++ %not = xor i32 %or, -1 ++ ret i32 %not ++} ++ ++define signext i32 @not32(i32 signext %a) { ++; CHECK-LABEL: not32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor i32 %a, -1 ++ ret i32 %not ++} ++ +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll +new file mode 100644 +index 000000000..54e4a5f2d +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lshr.ll +@@ -0,0 +1,12 @@ ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define signext i32 @foo(i32 %a) { ++; CHECK-LABEL: foo: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: bstrpick.d $r4, $r4, 31, 1 ++; CHECK-NEXT: jr $ra ++entry: ++ %b = lshr i32 %a, 1 ++ ret i32 %b ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll +new file mode 100644 +index 000000000..97b23be80 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/imm_vector_lsx.ll +@@ -0,0 +1,176 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++define <2 x i64> @build_lsx0(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx0: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -1 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx1(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx1: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu52i.d $r4, $zero, 2047 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx2(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx2: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 2048 ++; CHECK-NEXT: lu32i.d $r4, 524287 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx3(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx3: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu52i.d $r4, $r4, -1 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx4(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx4: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ori $r4, $zero, 4095 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx5(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx5: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx6(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx6: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx7(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx7: ++; CHECK: # %bb.0: ++; CHECK-NEXT: addi.w $r4, $zero, -2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx8(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx9(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx9: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -1 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx10(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx10: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: lu32i.d $r4, 0 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx11(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx11: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, 524287 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -1 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx12(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx12: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2047 ++; CHECK-NEXT: lu52i.d $r4, $r4, 2047 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} ++ ++define <2 x i64> @build_lsx13(<2 x i64> %a) { ++; CHECK-LABEL: build_lsx13: ++; CHECK: # %bb.0: ++; CHECK-NEXT: lu12i.w $r4, -524288 ++; CHECK-NEXT: ori $r4, $r4, 2048 ++; CHECK-NEXT: lu32i.d $r4, -524288 ++; CHECK-NEXT: lu52i.d $r4, $r4, 0 ++; CHECK-NEXT: vreplgr2vr.d $vr1, $r4 ++; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %b = add <2 x i64> %a, ++ ret <2 x i64> %b ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll +new file mode 100644 +index 000000000..37cb6dfc9 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll +@@ -0,0 +1,34 @@ ++; A basic inline assembly test ++ ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++@v2i64_r = global <2 x i64> zeroinitializer, align 16 ++ ++define void @test1() nounwind { ++entry: ++ ; CHECK-LABEL: test1: ++ %0 = call <2 x i64> asm "vldi ${0:w}, 1", "=f"() ++ ; CHECK: vldi $vr{{[1-3]?[0-9]}}, 1 ++ store <2 x i64> %0, <2 x i64>* @v2i64_r ++ ret void ++} ++ ++define void @test2() nounwind { ++entry: ++ ; CHECK-LABEL: test2: ++ %0 = load <2 x i64>, <2 x i64>* @v2i64_r ++ %1 = call <2 x i64> asm "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f"(<2 x i64> %0) ++ ; CHECK: vaddi.wu $vr{{[1-3]?[0-9]}}, $vr{{[1-3]?[0-9]}}, 1 ++ store <2 x i64> %1, <2 x i64>* @v2i64_r ++ ret void ++} ++ ++define void @test3() nounwind { ++entry: ++ ; CHECK-LABEL: test3: ++ %0 = load <2 x i64>, <2 x i64>* @v2i64_r ++ %1 = call <2 x i64> asm sideeffect "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f,~{$vr0}"(<2 x i64> %0) ++ ; CHECK: vaddi.wu $vr{{([1-9]|[1-3][0-9])}}, $vr{{([1-9]|[1-3][0-9])}}, 1 ++ store <2 x i64> %1, <2 x i64>* @v2i64_r ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll +new file mode 100644 +index 000000000..60ff93095 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/intrinsic-lsx.ll +@@ -0,0 +1,92 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++declare <16 x i8> @llvm.loongarch.lsx.vsrlrni.b.h(<16 x i8>, <16 x i8>, i32) ++declare <8 x i16> @llvm.loongarch.lsx.vsrlrni.h.w(<8 x i16>, <8 x i16>, i32) ++declare <4 x i32> @llvm.loongarch.lsx.vsrlrni.w.d(<4 x i32>, <4 x i32>, i32) ++declare <2 x i64> @llvm.loongarch.lsx.vsrlrni.d.q(<2 x i64>, <2 x i64>, i32) ++ ++declare <16 x i8> @llvm.loongarch.lsx.vrepli.b(i32) ++declare <8 x i16> @llvm.loongarch.lsx.vrepli.h(i32) ++declare <4 x i32> @llvm.loongarch.lsx.vrepli.w(i32) ++declare <2 x i64> @llvm.loongarch.lsx.vrepli.d(i32) ++ ++define <16 x i8> @lsx_vsrlrni_b_h(<16 x i8> %a, <16 x i8> %b) { ++; CHECK-LABEL: lsx_vsrlrni_b_h: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vsrlrni.b.h $vr0, $vr1, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <16 x i8> @llvm.loongarch.lsx.vsrlrni.b.h(<16 x i8> %a, <16 x i8> %b, i32 2) ++ ret <16 x i8> %0 ++} ++ ++define <8 x i16> @lsx_vsrlrni_h_w(<8 x i16> %a, <8 x i16> %b) { ++; CHECK-LABEL: lsx_vsrlrni_h_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vsrlrni.h.w $vr0, $vr1, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <8 x i16> @llvm.loongarch.lsx.vsrlrni.h.w(<8 x i16> %a, <8 x i16> %b, i32 2) ++ ret <8 x i16> %0 ++} ++ ++define <4 x i32> @lsx_vsrlrni_w_d(<4 x i32> %a, <4 x i32> %b) { ++; CHECK-LABEL: lsx_vsrlrni_w_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vsrlrni.w.d $vr0, $vr1, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <4 x i32> @llvm.loongarch.lsx.vsrlrni.w.d(<4 x i32> %a, <4 x i32> %b, i32 2) ++ ret <4 x i32> %0 ++} ++ ++define <2 x i64> @lsx_vsrlrni_d_q(<2 x i64> %a, <2 x i64> %b) { ++; CHECK-LABEL: lsx_vsrlrni_d_q: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vsrlrni.d.q $vr0, $vr1, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <2 x i64> @llvm.loongarch.lsx.vsrlrni.d.q(<2 x i64> %a, <2 x i64> %b, i32 2) ++ ret <2 x i64> %0 ++} ++ ++define <16 x i8> @lsx_vrepli_b() { ++; CHECK-LABEL: lsx_vrepli_b: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vldi $vr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <16 x i8> @llvm.loongarch.lsx.vrepli.b(i32 2) ++ ret <16 x i8> %0 ++} ++ ++define <8 x i16> @lsx_vrepli_h() { ++; CHECK-LABEL: lsx_vrepli_h: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vldi $vr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <8 x i16> @llvm.loongarch.lsx.vrepli.h(i32 2) ++ ret <8 x i16> %0 ++} ++ ++define <4 x i32> @lsx_vrepli_w() { ++; CHECK-LABEL: lsx_vrepli_w: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vldi $vr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <4 x i32> @llvm.loongarch.lsx.vrepli.w(i32 2) ++ ret <4 x i32> %0 ++} ++ ++define <2 x i64> @lsx_vrepli_d() { ++; CHECK-LABEL: lsx_vrepli_d: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vldi $vr0, 2 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = tail call <2 x i64> @llvm.loongarch.lsx.vrepli.d(i32 2) ++ ret <2 x i64> %0 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll +new file mode 100644 +index 000000000..0dd29b27e +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/logic-lsx.ll +@@ -0,0 +1,132 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++define <2 x i64> @not_v2i64(<2 x i64> %a) { ++; CHECK-LABEL: not_v2i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <2 x i64> %a, ++ ret <2 x i64> %not ++} ++ ++define <4 x i32> @not_v4i32(<4 x i32> %a) { ++; CHECK-LABEL: not_v4i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i32> %a, ++ ret <4 x i32> %not ++} ++ ++define <8 x i16> @not_v8i16(<8 x i16> %a) { ++; CHECK-LABEL: not_v8i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vnor.v $vr0, $vr0, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i16> %a, ++ ret <8 x i16> %not ++} ++ ++define <16 x i8> @not_v16i8(<16 x i8> %a) { ++; CHECK-LABEL: not_v16i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vxori.b $vr0, $vr0, 255 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i8> %a, ++ ret <16 x i8> %not ++} ++ ++ ++define <2 x i64> @andn_v2i64(<2 x i64> %a, <2 x i64> %b) { ++; CHECK-LABEL: andn_v2i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <2 x i64> %b, ++ %and = and <2 x i64> %not, %a ++ ret <2 x i64> %and ++} ++ ++define <4 x i32> @andn_v4i32(<4 x i32> %a, <4 x i32> %b) { ++; CHECK-LABEL: andn_v4i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i32> %b, ++ %and = and <4 x i32> %not, %a ++ ret <4 x i32> %and ++} ++ ++define <8 x i16> @andn_v8i16(<8 x i16> %a, <8 x i16> %b) { ++; CHECK-LABEL: andn_v8i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i16> %b, ++ %and = and <8 x i16> %not, %a ++ ret <8 x i16> %and ++} ++ ++define <16 x i8> @andn_v16i8(<16 x i8> %a, <16 x i8> %b) { ++; CHECK-LABEL: andn_v16i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vandn.v $vr0, $vr1, $vr0 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i8> %b, ++ %and = and <16 x i8> %not, %a ++ ret <16 x i8> %and ++} ++ ++ ++define <2 x i64> @orn_v2i64(<2 x i64> %a, <2 x i64> %b) { ++; CHECK-LABEL: orn_v2i64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <2 x i64> %b, ++ %or = or <2 x i64> %not, %a ++ ret <2 x i64> %or ++} ++ ++define <4 x i32> @orn_v4i32(<4 x i32> %a, <4 x i32> %b) { ++; CHECK-LABEL: orn_v4i32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <4 x i32> %b, ++ %or = or <4 x i32> %not, %a ++ ret <4 x i32> %or ++} ++ ++define <8 x i16> @orn_v8i16(<8 x i16> %a, <8 x i16> %b) { ++; CHECK-LABEL: orn_v8i16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <8 x i16> %b, ++ %or = or <8 x i16> %not, %a ++ ret <8 x i16> %or ++} ++ ++define <16 x i8> @orn_v16i8(<16 x i8> %a, <16 x i8> %b) { ++; CHECK-LABEL: orn_v16i8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vorn.v $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %not = xor <16 x i8> %b, ++ %or = or <16 x i8> %not, %a ++ ret <16 x i8> %or ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll +new file mode 100644 +index 000000000..951254baa +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/lsxvclr.ll +@@ -0,0 +1,50 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++define <16 x i8> @clri8(<16 x i8> %b, <16 x i8> %c) { ++; CHECK-LABEL: clri8: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vbitclr.b $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %shl = shl <16 x i8> , %c ++ %xor = xor <16 x i8> %shl, ++ %and = and <16 x i8> %xor, %b ++ ret <16 x i8> %and ++} ++ ++define <8 x i16> @clri16(<8 x i16> %b, <8 x i16> %c) { ++; CHECK-LABEL: clri16: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vbitclr.h $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %shl = shl <8 x i16> , %c ++ %xor = xor <8 x i16> %shl, ++ %and = and <8 x i16> %xor, %b ++ ret <8 x i16> %and ++} ++ ++define <4 x i32> @clri32(<4 x i32> %b, <4 x i32> %c) { ++; CHECK-LABEL: clri32: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vbitclr.w $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %shl = shl <4 x i32> , %c ++ %xor = xor <4 x i32> %shl, ++ %and = and <4 x i32> %xor, %b ++ ret <4 x i32> %and ++} ++ ++define <2 x i64> @clri64(<2 x i64> %b, <2 x i64> %c) { ++; CHECK-LABEL: clri64: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: vbitclr.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++entry: ++ %shl = shl <2 x i64> , %c ++ %xor = xor <2 x i64> %shl, ++ %and = and <2 x i64> %xor, %b ++ ret <2 x i64> %and ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll +new file mode 100644 +index 000000000..69f19297d +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/set-lsx.ll +@@ -0,0 +1,38 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++define <16 x i8> @seti8(<16 x i8>) { ++; CHECK-LABEL: seti8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vbitseti.b $vr0, $vr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <16 x i8> %0, ++ ret <16 x i8> %2 ++} ++ ++define <8 x i16> @seti16(<8 x i16>) { ++; CHECK-LABEL: seti16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vbitseti.h $vr0, $vr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <8 x i16> %0, ++ ret <8 x i16> %2 ++} ++ ++define <4 x i32> @seti32(<4 x i32>) { ++; CHECK-LABEL: seti32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vbitseti.w $vr0, $vr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <4 x i32> %0, ++ ret <4 x i32> %2 ++} ++ ++define <2 x i64> @seti64(<2 x i64>) { ++; CHECK-LABEL: seti64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vbitseti.d $vr0, $vr0, 6 ++; CHECK-NEXT: jr $ra ++ %2 = or <2 x i64> %0, ++ ret <2 x i64> %2 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll +new file mode 100644 +index 000000000..4c987fb1b +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lsx/vadda.ll +@@ -0,0 +1,62 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s ++ ++define <16 x i8> @vaddab(<16 x i8>, <16 x i8>) { ++; CHECK-LABEL: vaddab: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vadda.b $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <16 x i8> %0, zeroinitializer ++ %4 = sub <16 x i8> zeroinitializer, %0 ++ %5 = select <16 x i1> %3, <16 x i8> %4, <16 x i8> %0 ++ %6 = icmp slt <16 x i8> %1, zeroinitializer ++ %7 = sub <16 x i8> zeroinitializer, %1 ++ %8 = select <16 x i1> %6, <16 x i8> %7, <16 x i8> %1 ++ %9 = add <16 x i8> %5, %8 ++ ret <16 x i8> %9 ++} ++ ++define <8 x i16> @vaddah(<8 x i16>, <8 x i16>) { ++; CHECK-LABEL: vaddah: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vadda.h $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <8 x i16> %0, zeroinitializer ++ %4 = sub <8 x i16> zeroinitializer, %0 ++ %5 = select <8 x i1> %3, <8 x i16> %4, <8 x i16> %0 ++ %6 = icmp slt <8 x i16> %1, zeroinitializer ++ %7 = sub <8 x i16> zeroinitializer, %1 ++ %8 = select <8 x i1> %6, <8 x i16> %7, <8 x i16> %1 ++ %9 = add <8 x i16> %5, %8 ++ ret <8 x i16> %9 ++} ++ ++define <4 x i32> @vaddaw(<4 x i32>, <4 x i32>) { ++; CHECK-LABEL: vaddaw: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vadda.w $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <4 x i32> %0, zeroinitializer ++ %4 = sub nsw <4 x i32> zeroinitializer, %0 ++ %5 = select <4 x i1> %3, <4 x i32> %4, <4 x i32> %0 ++ %6 = icmp slt <4 x i32> %1, zeroinitializer ++ %7 = sub nsw <4 x i32> zeroinitializer, %1 ++ %8 = select <4 x i1> %6, <4 x i32> %7, <4 x i32> %1 ++ %9 = add nuw nsw <4 x i32> %5, %8 ++ ret <4 x i32> %9 ++} ++ ++define <2 x i64> @vaddad(<2 x i64>, <2 x i64>) { ++; CHECK-LABEL: vaddad: ++; CHECK: # %bb.0: ++; CHECK-NEXT: vadda.d $vr0, $vr0, $vr1 ++; CHECK-NEXT: jr $ra ++ %3 = icmp slt <2 x i64> %0, zeroinitializer ++ %4 = sub nsw <2 x i64> zeroinitializer, %0 ++ %5 = select <2 x i1> %3, <2 x i64> %4, <2 x i64> %0 ++ %6 = icmp slt <2 x i64> %1, zeroinitializer ++ %7 = sub nsw <2 x i64> zeroinitializer, %1 ++ %8 = select <2 x i1> %6, <2 x i64> %7, <2 x i64> %1 ++ %9 = add nuw nsw <2 x i64> %5, %8 ++ ret <2 x i64> %9 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll +new file mode 100644 +index 000000000..55fd40edd +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/lu12i.ll +@@ -0,0 +1,7 @@ ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define i32 @foo() { ++; CHECK: lu12i.w $r4, -1 ++entry: ++ ret i32 -4096 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll +new file mode 100644 +index 000000000..c0c782fea +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/mcpu_load.ll +@@ -0,0 +1,72 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -mcpu=la264 -o - %s | FileCheck -check-prefix=ALIGNED %s ++; RUN: llc -march=loongarch64 -mcpu=la364 -o - %s | FileCheck -check-prefix=ALIGNED %s ++; RUN: llc -march=loongarch64 -mcpu=la464 -o - %s | FileCheck -check-prefix=UNALIGNED %s ++ ++define i32 @i32_load(i32* %p) { ++; ALIGNED-LABEL: i32_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.w $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++; ++; UNALIGNED-LABEL: i32_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define signext i32 @i32_sextload(i32* %p) { ++; ALIGNED-LABEL: i32_sextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.h $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++; ++; UNALIGNED-LABEL: i32_sextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define zeroext i32 @i32_zextload(i32* %p) { ++; ALIGNED-LABEL: i32_zextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++; ++; UNALIGNED-LABEL: i32_zextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.wu $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define i64 @i64_load(i64* %p) { ++; ALIGNED-LABEL: i64_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.wu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.wu $r4, $r4, 4 ++; ALIGNED-NEXT: slli.d $r4, $r4, 32 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++; ++; UNALIGNED-LABEL: i64_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.d $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++ %tmp = load i64, i64* %p, align 4 ++ ret i64 %tmp ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir b/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir +deleted file mode 100644 +index 56793c583..000000000 +--- a/src/llvm-project/llvm/test/CodeGen/LoongArch/misc.mir ++++ /dev/null +@@ -1,200 +0,0 @@ +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ +-# RUN: | extract-section .text \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ENC +-# RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ +-# RUN: | FileCheck %s -check-prefix=CHECK-ASM +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: I15 +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------------+--------------------------------------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------------+--------------------------------------------- +-# opcode | imm15 +-# ---------------------------------------------------+--------------------------------------------- +- +---- +-# CHECK-LABEL: test_DBAR: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-# CHECK-ASM: dbar 0 +-name: test_DBAR +-body: | +- bb.0: +- DBAR 0 +-... +---- +-# CHECK-LABEL: test_IBAR: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-# CHECK-ASM: ibar 0 +-name: test_IBAR +-body: | +- bb.0: +- IBAR 0 +-... +---- +-# CHECK-LABEL: test_SYSCALL: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 +-# CHECK-ASM: syscall 100 +-name: test_SYSCALL +-body: | +- bb.0: +- SYSCALL 100 +-... +---- +-# CHECK-LABEL: test_BREAK: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 +-# CHECK-ASM: break 199 +-name: test_BREAK +-body: | +- bb.0: +- BREAK 199 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: I26 +-# ------------------------------------------------------------------------------------------------- +-# ------------------+-----------------------------------------------+------------------------------ +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------+-----------------------------------------------+------------------------------ +-# opcode | imm26{15-0} | imm26{25-16} +-# ------------------+-----------------------------------------------+------------------------------ +- +---- +-# CHECK-LABEL: test_B: +-# CHECK-ENC: 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +-# CHECK-ASM: b 80 +-name: test_B +-body: | +- bb.0: +- B 80 +-... +---- +-# CHECK-LABEL: test_BL: +-# CHECK-ENC: 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +-# CHECK-ASM: bl 136 +-name: test_BL +-body: | +- bb.0: +- BL 136 +-... +- +-# -------------------------------------------------------------------------------------------------------- +-# Encoding format: BSTR_W +-# -------------------------------------------------------------------------------------------------------- +-# ---------------------------------+--------------+---------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------+--------------+---------+--------------+--------------+--------------- +-# opcode{11-1} | msb |opcode{0}| lsb | rj | rd +-# ---------------------------------+--------------+---------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_BSTRINS_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bstrins.w $a0, $a1, 7, 2 +-name: test_BSTRINS_W +-body: | +- bb.0: +- $r4 = BSTRINS_W $r4, $r5, 7, 2 +-... +---- +-# CHECK-LABEL: test_BSTRPICK_W: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bstrpick.w $a0, $a1, 10, 4 +-name: test_BSTRPICK_W +-body: | +- bb.0: +- $r4 = BSTRPICK_W $r5, 10, 4 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: BSTR_D +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------+-----------------+-----------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------+-----------------+-----------------+--------------+--------------- +-# opcode | msb | lsb | rj | rd +-# ------------------------------+-----------------+-----------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_BSTRINS_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bstrins.d $a0, $a1, 7, 2 +-name: test_BSTRINS_D +-body: | +- bb.0: +- $r4 = BSTRINS_D $r4, $r5, 7, 2 +-... +---- +-# CHECK-LABEL: test_BSTRPICK_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 +-# CHECK-ASM: bstrpick.d $a0, $a1, 39, 22 +-name: test_BSTRPICK_D +-body: | +- bb.0: +- $r4 = BSTRPICK_D $r5, 39, 22 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: ASRT +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------------+--------------+--------------+--------------- +-# opcode | rk | rj | 0x0 +-# ---------------------------------------------------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_ASRTLE_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 +-# CHECK-ASM: asrtle.d $a0, $a1 +-name: test_ASRTLE_D +-body: | +- bb.0: +- ASRTLE_D $r4, $r5 +-... +---- +-# CHECK-LABEL: test_ASRTGT_D: +-# CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 +-# CHECK-ASM: asrtgt.d $a0, $a1 +-name: test_ASRTGT_D +-body: | +- bb.0: +- ASRTGT_D $r4, $r5 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: PRELD +-# ------------------------------------------------------------------------------------------------- +-# ------------------------------+-----------------------------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ------------------------------+-----------------------------------+--------------+--------------- +-# opcode | imm12 | rj | imm5 +-# ------------------------------+-----------------------------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_PRELD: +-# CHECK-ENC: 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 1 1 1 1 +-# CHECK-ASM: preld 15, $a0, 21 +-name: test_PRELD +-body: | +- bb.0: +- PRELD 15, $r4, 21 +-... +- +-# ------------------------------------------------------------------------------------------------- +-# Encoding format: PRELDX +-# ------------------------------------------------------------------------------------------------- +-# ---------------------------------------------------+--------------+--------------+--------------- +-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 +-# ---------------------------------------------------+--------------+--------------+--------------- +-# opcode | rk | rj | imm5 +-# ---------------------------------------------------+--------------+--------------+--------------- +- +---- +-# CHECK-LABEL: test_PRELDX: +-# CHECK-ENC: 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 1 0 1 1 +-# CHECK-ASM: preldx 11, $a0, $a1 +-name: test_PRELDX +-body: | +- bb.0: +- PRELDX 11, $r4, $r5 +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll +new file mode 100644 +index 000000000..0b0660fca +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/named-register.ll +@@ -0,0 +1,29 @@ ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define i64 @get_r2() { ++; CHECK-LABEL: get_r2: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: move $r4, $tp ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = call i64 @llvm.read_register.i64(metadata !0) ++ ret i64 %0 ++} ++ ++define i64 @get_r21() { ++; CHECK-LABEL: get_r21: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: move $r4, $r21 ++; CHECK-NEXT: jr $ra ++entry: ++ %0 = call i64 @llvm.read_register.i64(metadata !1) ++ ret i64 %0 ++} ++ ++declare i64 @llvm.read_register.i64(metadata) ++ ++!llvm.named.register.$r2 = !{!0} ++!llvm.named.register.$r21 = !{!1} ++ ++!0 = !{!"$r2"} ++!1 = !{!"$r21"} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll +new file mode 100644 +index 000000000..a8ce63225 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/nomerge.ll +@@ -0,0 +1,35 @@ ++; RUN: llc < %s -mtriple=loongarch64 -relocation-model=pic -o - | FileCheck %s ++ ++define void @foo(i32 %i) { ++entry: ++ switch i32 %i, label %if.end3 [ ++ i32 5, label %if.then ++ i32 7, label %if.then2 ++ ] ++ ++if.then: ++ tail call void @bar() #0 ++ br label %if.end3 ++ ++if.then2: ++ tail call void @bar() #0 ++ br label %if.end3 ++ ++if.end3: ++ tail call void @bar() #0 ++ ret void ++} ++ ++declare void @bar() ++ ++attributes #0 = { nomerge } ++ ++; CHECK-LABEL: foo: ++; CHECK: # %bb.0: # %entry ++; CHECK: .LBB0_1: # %entry ++; CHECK: .LBB0_2: # %if.then ++; CHECK-NEXT: bl bar ++; CHECK: .LBB0_3: # %if.then2 ++; CHECK-NEXT: bl bar ++; CHECK: .LBB0_4: # %if.end3 ++; CHECK: b bar +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll +new file mode 100644 +index 000000000..9aa8c4391 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/noti32.ll +@@ -0,0 +1,143 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define i8 @nor_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: nor_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i8 %a, %b ++ %neg = xor i8 %or, -1 ++ ret i8 %neg ++} ++ ++define i16 @nor_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: nor_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i16 %a, %b ++ %neg = xor i16 %or, -1 ++ ret i16 %neg ++} ++ ++define i32 @nor_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: nor_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i32 %a, %b ++ %neg = xor i32 %or, -1 ++ ret i32 %neg ++} ++ ++define i8 @nor_zero_i8(i8 %a) nounwind { ++; CHECK-LABEL: nor_zero_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %a, -1 ++ ret i8 %neg ++} ++ ++define i16 @nor_zero_i16(i16 %a) nounwind { ++; CHECK-LABEL: nor_zero_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %a, -1 ++ ret i16 %neg ++} ++ ++define i32 @nor_zero_i32(i32 %a) nounwind { ++; CHECK-LABEL: nor_zero_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %a, -1 ++ ret i32 %neg ++} ++ ++define i8 @orn_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: orn_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %b, -1 ++ %or = or i8 %neg, %a ++ ret i8 %or ++} ++ ++define i16 @orn_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: orn_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %b, -1 ++ %or = or i16 %neg, %a ++ ret i16 %or ++} ++ ++define i32 @orn_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: orn_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %b, -1 ++ %or = or i32 %neg, %a ++ ret i32 %or ++} ++ ++define i8 @andn_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: andn_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %b, -1 ++ %and = and i8 %neg, %a ++ ret i8 %and ++} ++ ++define i16 @andn_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: andn_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %b, -1 ++ %and = and i16 %neg, %a ++ ret i16 %and ++} ++ ++define i32 @andn_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: andn_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %b, -1 ++ %and = and i32 %neg, %a ++ ret i32 %and ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll +new file mode 100644 +index 000000000..541ea4256 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/peephole-load-store-addi.ll +@@ -0,0 +1,100 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s ++ ++define i8 @load_i8() nounwind { ++; CHECK-LABEL: load_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.bu $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 ++ ret i8 %a ++} ++define signext i8 @load_i8_sext() nounwind { ++; CHECK-LABEL: load_i8_sext: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.b $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 ++ ret i8 %a ++} ++ ++define i16 @load_i16() nounwind { ++; CHECK-LABEL: load_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.hu $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 ++ ret i16 %a ++} ++ ++define signext i16 @load_i16_sext() nounwind { ++; CHECK-LABEL: load_i16_sext: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.h $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 ++ ret i16 %a ++} ++ ++define i32 @load_i32() nounwind { ++; CHECK-LABEL: load_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.w $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 ++ ret i32 %a ++} ++ ++define signext i32 @load_i32_sext() nounwind { ++; CHECK-LABEL: load_i32_sext: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.w $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 ++ ret i32 %a ++} ++ ++define i64 @load_i64() nounwind { ++; CHECK-LABEL: load_i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: ld.d $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ %a = load i64, i64* inttoptr (i64 40 to i64*), align 8 ++ ret i64 %a ++} ++ ++define void @store_i8(i8 %v) nounwind { ++; CHECK-LABEL: store_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: st.b $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ store i8 %v, i8* inttoptr (i64 40 to i8*), align 8 ++ ret void ++} ++ ++define void @store_i16(i16 %v) nounwind { ++; CHECK-LABEL: store_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: st.h $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ store i16 %v, i16* inttoptr (i64 40 to i16*), align 8 ++ ret void ++} ++ ++define void @store_i32(i32 %v) nounwind { ++; CHECK-LABEL: store_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: st.w $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ store i32 %v, i32* inttoptr (i64 40 to i32*), align 8 ++ ret void ++} ++ ++define void @store_i64(i64 %v) nounwind { ++; CHECK-LABEL: store_i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: st.d $r4, $zero, 40 ++; CHECK-NEXT: jr $ra ++ store i64 %v, i64* inttoptr (i64 40 to i64*), align 8 ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll +new file mode 100644 +index 000000000..13c710d14 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/signext.ll +@@ -0,0 +1,37 @@ ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define i32 @foo(i32 signext %a) { ++; CHECK-LABEL: foo: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++ ret i32 %a ++} ++ ++define signext i32 @foo1() { ++; CHECK-LABEL: foo1: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: ori $r4, $zero, 0 ++; CHECK-NEXT: ori $r5, $zero, 896 ++; CHECK-NEXT: move $r6, $r4 ++; CHECK-NEXT: .LBB1_1: # %for.body ++; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ++; CHECK-NEXT: add.w $r4, $r4, $r6 ++; CHECK-NEXT: addi.w $r6, $r6, 1 ++; CHECK-NEXT: bne $r6, $r5, .LBB1_1 ++; CHECK-NEXT: # %bb.2: # %for.end ++; CHECK-NEXT: jr $ra ++entry: ++ br label %for.body ++ ++for.body: ++ %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ] ++ %i.010 = phi i32 [ 0, %entry ], [ %inc, %for.body ] ++ %add = add i32 %sum.013, %i.010 ++ %inc = add nuw nsw i32 %i.010, 1 ++ %exitcond = icmp eq i32 %inc, 896 ++ br i1 %exitcond, label %for.end, label %for.body ++ ++for.end: ++ ret i32 %add ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll +new file mode 100644 +index 000000000..0a54e0f8f +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/stptr.ll +@@ -0,0 +1,52 @@ ++; Check whether st.w/st.d/stptr.w/stptr.d/stx.w/stx.d instructions are properly generated ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define void @st_w(i32* %p, i32 signext %val) { ++; CHECK: st.w $r5, $r4, 2044 ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i32, i32* %p, i64 511 ++ store i32 %val, i32* %addr, align 4 ++ ret void ++} ++ ++define void @stptr_w(i32* %p, i32 signext %val) { ++; CHECK: stptr.w $r5, $r4, 2048 ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i32, i32* %p, i64 512 ++ store i32 %val, i32* %addr, align 4 ++ ret void ++} ++ ++define void @stx_w(i32* %p, i32 signext %val) { ++; CHECK: lu12i.w $r[[REG:[0-9]+]], 8 ++; CHECK: stx.w $r5, $r4, $r[[REG:[0-9]+]] ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i32, i32* %p, i64 8192 ++ store i32 %val, i32* %addr, align 4 ++ ret void ++} ++ ++define void @st_d(i64* %p, i64 %val) { ++; CHECK: st.d $r5, $r4, 2040 ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i64, i64* %p, i64 255 ++ store i64 %val, i64* %addr, align 8 ++ ret void ++} ++ ++define void @stptr_d(i64* %p, i64 %val) { ++; CHECK: stptr.d $r5, $r4, 2048 ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i64, i64* %p, i64 256 ++ store i64 %val, i64* %addr, align 8 ++ ret void ++} ++ ++define void @stx_d(i64* %p, i64 %val) { ++; CHECK: lu12i.w $r[[REG:[0-9]+]], 8 ++; CHECK: stx.d $r5, $r4, $r[[REG:[0-9]+]] ++; CHECK: jr $ra ++ %addr = getelementptr inbounds i64, i64* %p, i64 4096 ++ store i64 %val, i64* %addr, align 8 ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll +new file mode 100644 +index 000000000..2445e32ea +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-R.ll +@@ -0,0 +1,62 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s ++ ++@errors = external local_unnamed_addr global i32, align 4 ++ ++define signext i32 @compare(i8* %x, i8* %y) { ++; CHECK-LABEL: compare: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -32 ++; CHECK-NEXT: .cfi_def_cfa_offset 32 ++; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill ++; CHECK-NEXT: st.d $r23, $sp, 16 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: .cfi_offset 23, -16 ++; CHECK-NEXT: ld.w $r23, $r5, 0 ++; CHECK-NEXT: ld.d $r6, $r4, 8 ++; CHECK-NEXT: beqz $r23, .LBB0_3 ++; CHECK-NEXT: # %bb.1: # %land.lhs.true ++; CHECK-NEXT: ld.w $r4, $r4, 0 ++; CHECK-NEXT: st.d $r6, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: ld.d $r5, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: jirl $ra, $r5, 0 ++; CHECK-NEXT: ld.d $r6, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: beqz $r4, .LBB0_3 ++; CHECK-NEXT: # %bb.2: # %if.then ++; CHECK-NEXT: la.got $r4, errors ++; CHECK-NEXT: # la expanded slot ++; CHECK-NEXT: ld.w $r5, $r4, 0 ++; CHECK-NEXT: addi.w $r5, $r5, 1 ++; CHECK-NEXT: st.w $r5, $r4, 0 ++; CHECK-NEXT: .LBB0_3: # %if.end ++; CHECK-NEXT: move $r4, $r23 ++; CHECK-NEXT: ld.d $r23, $sp, 16 # 8-byte Folded Reload ++; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 32 ++; CHECK-NEXT: jr $r6 ++entry: ++ %compare = getelementptr inbounds i8, i8* %x, i64 8 ++ %0 = bitcast i8* %compare to i32 (i32)** ++ %1 = load i32 (i32)*, i32 (i32)** %0, align 8 ++ %elt = bitcast i8* %y to i32* ++ %2 = load i32, i32* %elt, align 8 ++ %cmp = icmp eq i32 %2, 0 ++ br i1 %cmp, label %if.end, label %land.lhs.true ++ ++land.lhs.true: ; preds = %entry ++ %elt3 = bitcast i8* %x to i32* ++ %3 = load i32, i32* %elt3, align 8 ++ %call4 = tail call signext i32 %1(i32 signext %3) ++ %cmp5 = icmp eq i32 %call4, 0 ++ br i1 %cmp5, label %if.end, label %if.then ++ ++if.then: ; preds = %land.lhs.true ++ %4 = load i32, i32* @errors, align 4 ++ %inc = add nsw i32 %4, 1 ++ store i32 %inc, i32* @errors, align 4 ++ br label %if.end ++ ++if.end: ; preds = %if.then, %land.lhs.true, %entry ++ %call6 = tail call signext i32 %1(i32 signext %2) ++ ret i32 %call6 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll +new file mode 100644 +index 000000000..2b5902d69 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-check.ll +@@ -0,0 +1,155 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s ++ ++; Perform tail call optimization for global address. ++declare i32 @callee_tail(i32 %i) ++define i32 @caller_tail(i32 %i) { ++; CHECK-LABEL: caller_tail: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: b callee_tail ++entry: ++ %r = tail call i32 @callee_tail(i32 %i) ++ ret i32 %r ++} ++ ++ ++; Do not tail call optimize functions with varargs. ++declare i32 @callee_varargs(i32, ...) ++define void @caller_varargs(i32 %a, i32 %b) { ++; CHECK-LABEL: caller_varargs: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: move $r6, $r5 ++; CHECK-NEXT: move $r7, $r4 ++; CHECK-NEXT: bl callee_varargs ++; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++entry: ++ %call = tail call i32 (i32, ...) @callee_varargs(i32 %a, i32 %b, i32 %b, i32 %a) ++ ret void ++} ++ ++ ++; Do not tail call optimize if stack is used to pass parameters. ++declare i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) ++define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) { ++; CHECK-LABEL: caller_args: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -64 ++; CHECK-NEXT: .cfi_def_cfa_offset 64 ++; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: ld.d $r12, $sp, 64 ++; CHECK-NEXT: ld.d $r13, $sp, 72 ++; CHECK-NEXT: ld.d $r14, $sp, 80 ++; CHECK-NEXT: ld.d $r15, $sp, 88 ++; CHECK-NEXT: ld.d $r16, $sp, 96 ++; CHECK-NEXT: ld.d $r17, $sp, 104 ++; CHECK-NEXT: st.d $r17, $sp, 40 ++; CHECK-NEXT: st.d $r16, $sp, 32 ++; CHECK-NEXT: st.d $r15, $sp, 24 ++; CHECK-NEXT: st.d $r14, $sp, 16 ++; CHECK-NEXT: st.d $r13, $sp, 8 ++; CHECK-NEXT: st.d $r12, $sp, 0 ++; CHECK-NEXT: bl callee_args ++; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 64 ++; CHECK-NEXT: jr $ra ++entry: ++ %r = tail call i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) ++ ret i32 %r ++} ++ ++ ++; Do not tail call optimize for exception-handling functions. ++declare void @callee_interrupt() ++define void @caller_interrupt() #0 { ++; CHECK-LABEL: caller_interrupt: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: bl callee_interrupt ++; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++entry: ++ tail call void @callee_interrupt() ++ ret void ++} ++attributes #0 = { "interrupt"="machine" } ++ ++ ++; Do not tail call optimize functions with byval parameters. ++declare i32 @callee_byval(i32** byval(i32*) %a) ++define i32 @caller_byval() { ++; CHECK-LABEL: caller_byval: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -32 ++; CHECK-NEXT: .cfi_def_cfa_offset 32 ++; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: ld.d $r4, $sp, 16 ++; CHECK-NEXT: st.d $r4, $sp, 0 ++; CHECK-NEXT: bl callee_byval ++; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 32 ++; CHECK-NEXT: jr $ra ++entry: ++ %a = alloca i32* ++ %r = tail call i32 @callee_byval(i32** byval(i32*) %a) ++ ret i32 %r ++} ++ ++ ++; Do not tail call optimize if callee uses structret semantics. ++%struct.A = type { i32 } ++@a = global %struct.A zeroinitializer ++ ++declare void @callee_struct(%struct.A* sret(%struct.A) %a) ++define void @caller_nostruct() { ++; CHECK-LABEL: caller_nostruct: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: la.got $r4, a ++; CHECK-NEXT: # la expanded slot ++; CHECK-NEXT: bl callee_struct ++; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++entry: ++ tail call void @callee_struct(%struct.A* sret(%struct.A) @a) ++ ret void ++} ++ ++ ++; Do not tail call optimize if caller uses structret semantics. ++declare void @callee_nostruct() ++define void @caller_struct(%struct.A* sret(%struct.A) %a) { ++; CHECK-LABEL: caller_struct: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: addi.d $sp, $sp, -16 ++; CHECK-NEXT: .cfi_def_cfa_offset 16 ++; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; CHECK-NEXT: st.d $r23, $sp, 0 # 8-byte Folded Spill ++; CHECK-NEXT: .cfi_offset 1, -8 ++; CHECK-NEXT: .cfi_offset 23, -16 ++; CHECK-NEXT: move $r23, $r4 ++; CHECK-NEXT: bl callee_nostruct ++; CHECK-NEXT: move $r4, $r23 ++; CHECK-NEXT: ld.d $r23, $sp, 0 # 8-byte Folded Reload ++; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; CHECK-NEXT: addi.d $sp, $sp, 16 ++; CHECK-NEXT: jr $ra ++entry: ++ tail call void @callee_nostruct() ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll +new file mode 100644 +index 000000000..68ddaa899 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall-mem.ll +@@ -0,0 +1,35 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s ++ ++ ++define void @tail_memcpy(i8* %p, i8* %q, i32 %n) { ++; CHECK-LABEL: tail_memcpy: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: b memcpy ++entry: ++ tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ++ ret void ++} ++ ++define void @tail_memmove(i8* %p, i8* %q, i32 %n) { ++; CHECK-LABEL: tail_memmove: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: b memmove ++entry: ++ tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ++ ret void ++} ++ ++define void @tail_memset(i8* %p, i8 %c, i32 %n) { ++; CHECK-LABEL: tail_memset: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: b memset ++entry: ++ tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i1 false) ++ ret void ++} ++ ++declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) ++declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) ++declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) ++ +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll +new file mode 100644 +index 000000000..984df2cb6 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/tailcall.ll +@@ -0,0 +1,13 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -relocation-model=pic < %s | FileCheck %s ++ ++define void @f() { ++; CHECK-LABEL: f: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: b foo ++entry: ++ tail call void bitcast (void (...)* @foo to void ()*)() ++ ret void ++} ++ ++declare void @foo(...) +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll +new file mode 100644 +index 000000000..06a5886c4 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/thread-pointer.ll +@@ -0,0 +1,9 @@ ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++declare i8* @llvm.thread.pointer() nounwind readnone ++ ++define i8* @thread_pointer() { ++; CHECK: move $r4, $tp ++ %1 = tail call i8* @llvm.thread.pointer() ++ ret i8* %1 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll +new file mode 100644 +index 000000000..d1b5a3a14 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/trunc.ll +@@ -0,0 +1,108 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define signext i32 @foo1(i64 %a, i64 %b) { ++; CHECK-LABEL: foo1: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: add.w $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %add = add nsw i32 %conv1, %conv ++ ret i32 %add ++} ++ ++define signext i32 @foo2(i64 %a, i64 %b) { ++; CHECK-LABEL: foo2: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: sub.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %sub = sub nsw i32 %conv, %conv1 ++ ret i32 %sub ++} ++ ++define signext i32 @foo3(i64 %a, i64 %b) { ++; CHECK-LABEL: foo3: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: sll.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %shl = shl i32 %conv, %conv1 ++ ret i32 %shl ++} ++ ++define signext i32 @foo4(i64 %a, i64 %b) { ++; CHECK-LABEL: foo4: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: srl.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %shr = lshr i32 %conv, %conv1 ++ ret i32 %shr ++} ++ ++define signext i32 @foo5(i64 %a, i64 %b) { ++; CHECK-LABEL: foo5: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: mul.w $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %mul = mul nsw i32 %conv1, %conv ++ ret i32 %mul ++} ++ ++define signext i32 @foo6(i64 %a, i64 %b) { ++; CHECK-LABEL: foo6: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: sra.w $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %shr = ashr i32 %conv, %conv1 ++ ret i32 %shr ++} ++ ++define signext i32 @sdiv(i64 %a, i64 %b) { ++; CHECK-LABEL: sdiv: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: div.w $r4, $r4, $r5 ++; CHECK-NEXT: bne $r5, $zero, 8 ++; CHECK-NEXT: break 7 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %div = sdiv i32 %conv, %conv1 ++ ret i32 %div ++} ++ ++define signext i32 @udiv(i64 %a, i64 %b) { ++; CHECK-LABEL: udiv: ++; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: div.wu $r4, $r4, $r5 ++; CHECK-NEXT: bne $r5, $zero, 8 ++; CHECK-NEXT: break 7 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: jr $ra ++entry: ++ %conv = trunc i64 %a to i32 ++ %conv1 = trunc i64 %b to i32 ++ %div = udiv i32 %conv, %conv1 ++ ret i32 %div ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll b/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll +new file mode 100644 +index 000000000..d468a361f +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/LoongArch/unalignment.ll +@@ -0,0 +1,72 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -o - %s | FileCheck -check-prefix=UNALIGNED %s ++; RUN: llc -march=loongarch64 -mattr=+unaligned-access -o - %s | FileCheck -check-prefix=UNALIGNED %s ++; RUN: llc -march=loongarch64 -mattr=-unaligned-access -o - %s | FileCheck -check-prefix=ALIGNED %s ++ ++define i32 @i32_load(i32* %p) { ++; UNALIGNED-LABEL: i32_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.w $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define signext i32 @i32_sextload(i32* %p) { ++; UNALIGNED-LABEL: i32_sextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_sextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.h $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define zeroext i32 @i32_zextload(i32* %p) { ++; UNALIGNED-LABEL: i32_zextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.wu $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_zextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define i64 @i64_load(i64* %p) { ++; UNALIGNED-LABEL: i64_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.d $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i64_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.wu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.wu $r4, $r4, 4 ++; ALIGNED-NEXT: slli.d $r4, $r4, 32 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i64, i64* %p, align 4 ++ ret i64 %tmp ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll b/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll +new file mode 100644 +index 000000000..cae3cb3bb +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll +@@ -0,0 +1,250 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -O0 < %s | FileCheck %s ++ ++; This test would previously crash in RegisterScavenging, or with assertions ++; enabled it would fail when RegAllocFast calls clearVirtRegs. This was due to ++; unhandled virt regs in cloned DBG_VALUE_LIST for spills, which are now skipped. ++; https://github.com/llvm/llvm-project/issues/59172 ++ ++target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" ++target triple = "powerpc64le-unknown-linux-gnu" ++ ++; Function Attrs: argmemonly nocallback nofree nounwind willreturn ++declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0 ++ ++; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) #1 ++ ++define void @read_to_end(i1 %0) personality ptr null { ++; CHECK-LABEL: read_to_end: ++; CHECK: # %bb.0: ++; CHECK-NEXT: mflr 0 ++; CHECK-NEXT: std 0, 16(1) ++; CHECK-NEXT: stdu 1, -80(1) ++; CHECK-NEXT: .cfi_def_cfa_offset 80 ++; CHECK-NEXT: .cfi_offset lr, 16 ++; CHECK-NEXT: andi. 3, 3, 1 ++; CHECK-NEXT: mfocrf 3, 128 ++; CHECK-NEXT: rlwinm 3, 3, 1, 0, 0 ++; CHECK-NEXT: stw 3, 60(1) ++; CHECK-NEXT: ld 3, 0(0) ++; CHECK-NEXT: std 3, 64(1) # 8-byte Folded Spill ++; CHECK-NEXT: li 3, 0 ++; CHECK-NEXT: std 3, 72(1) # 8-byte Folded Spill ++; CHECK-NEXT: #DEBUG_VALUE: spec_extend:iterator <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_constu 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment 64 64] undef, $x3 ++; CHECK-NEXT: creqv 20, 20, 20 ++; CHECK-NEXT: crxor 20, 1, 20 ++; CHECK-NEXT: bc 12, 20, .LBB0_2 ++; CHECK-NEXT: b .LBB0_1 ++; CHECK-NEXT: .LBB0_1: ++; CHECK-NEXT: addi 1, 1, 80 ++; CHECK-NEXT: ld 0, 16(1) ++; CHECK-NEXT: mtlr 0 ++; CHECK-NEXT: blr ++; CHECK-NEXT: .LBB0_2: ++; CHECK-NEXT: ld 5, 72(1) # 8-byte Folded Reload ++; CHECK-NEXT: ld 4, 64(1) # 8-byte Folded Reload ++; CHECK-NEXT: li 3, 0 ++; CHECK-NEXT: bl memcpy ++; CHECK-NEXT: nop ++; CHECK-NEXT: lwz 4, 60(1) ++; CHECK-NEXT: # implicit-def: $cr5lt ++; CHECK-NEXT: mfocrf 3, 4 ++; CHECK-NEXT: rlwimi 3, 4, 12, 20, 20 ++; CHECK-NEXT: mtocrf 4, 3 ++; CHECK-NEXT: bc 12, 20, .LBB0_4 ++; CHECK-NEXT: b .LBB0_3 ++; CHECK-NEXT: .LBB0_3: ++; CHECK-NEXT: b .LBB0_4 ++; CHECK-NEXT: .LBB0_4: ++; CHECK-NEXT: addi 1, 1, 80 ++; CHECK-NEXT: ld 0, 16(1) ++; CHECK-NEXT: mtlr 0 ++; CHECK-NEXT: blr ++ %2 = load ptr, ptr null, align 8 ++ %3 = sub i64 0, 0 ++ call void @llvm.dbg.value(metadata !DIArgList(ptr %2, i64 %3), metadata !129, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 64)), !dbg !140 ++ br i1 %0, label %4, label %5 ++ ++4: ; preds = %1 ++ ret void ++ ++5: ; preds = %1 ++ tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %2, i64 %3, i1 false) ++ br i1 %0, label %7, label %6 ++ ++6: ; preds = %5 ++ br label %7 ++ ++7: ; preds = %6, %5 ++ ret void ++} ++ ++attributes #0 = { argmemonly nocallback nofree nounwind willreturn } ++attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } ++ ++!llvm.module.flags = !{!0} ++!llvm.dbg.cu = !{!1} ++ ++!0 = !{i32 2, !"Debug Info Version", i32 3} ++!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.67.0-dev)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) ++!2 = !DIFile(filename: "library/std/src/lib.rs/@/std.ff910444-cgu.11", directory: "/home/jistone/rust") ++!3 = !{} ++!4 = !{!5, !12, !18, !23, !28, !34, !43, !49, !52, !58, !64, !68, !77, !81, !86, !90, !98, !102, !106, !111, !117, !124} ++!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) ++!6 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !8, isLocal: true, isDefinition: true) ++!7 = !DIFile(filename: "", directory: "") ++!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !9, templateParams: !3, identifier: "1ec913b2a90798f33a12cdc627a17d3d") ++!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "String", scope: !10, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "b616ccc9e18737e903266aae12eea82") ++!10 = !DINamespace(name: "string", scope: !11) ++!11 = !DINamespace(name: "alloc", scope: null) ++!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) ++!13 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !14, isLocal: true, isDefinition: true) ++!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !15, templateParams: !3, identifier: "7f09904511177108b2e94c43effbe403") ++!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "BorrowMutError", scope: !16, file: !7, align: 8, elements: !3, identifier: "acf9edd4524e0ff9a9398905d3ba31a6") ++!16 = !DINamespace(name: "cell", scope: !17) ++!17 = !DINamespace(name: "core", scope: null) ++!18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression()) ++!19 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !20, isLocal: true, isDefinition: true) ++!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !21, templateParams: !3, identifier: "84cb7e6d80fc4c532d8f45aaa75a7ae3") ++!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Error", scope: !22, file: !7, align: 8, elements: !3, identifier: "abcb9fb1fe4fda8598a8687b517935b") ++!22 = !DINamespace(name: "fmt", scope: !17) ++!23 = !DIGlobalVariableExpression(var: !24, expr: !DIExpression()) ++!24 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !25, isLocal: true, isDefinition: true) ++!25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !26, templateParams: !3, identifier: "bafa31943f8233dbf8d2de6a615f899") ++!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromSliceError", scope: !27, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "2dd7cf8d77337f63be7c7f5feb370b37") ++!27 = !DINamespace(name: "array", scope: !17) ++!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression()) ++!29 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !30, isLocal: true, isDefinition: true) ++!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !31, templateParams: !3, identifier: "3292395ea0f5a7e3e88f36db52eb440c") ++!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromIntError", scope: !32, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "5b131d57d001578fbf4fb83f2028eb12") ++!32 = !DINamespace(name: "error", scope: !33) ++!33 = !DINamespace(name: "num", scope: !17) ++!34 = !DIGlobalVariableExpression(var: !35, expr: !DIExpression()) ++!35 = distinct !DIGlobalVariable(name: "OUTPUT_CAPTURE_USED", linkageName: "_ZN3std2io5stdio19OUTPUT_CAPTURE_USED17h6bb564f9f9e20f1bE", scope: !36, file: !39, line: 38, type: !40, isLocal: true, isDefinition: true, align: 8) ++!36 = !DINamespace(name: "stdio", scope: !37) ++!37 = !DINamespace(name: "io", scope: !38) ++!38 = !DINamespace(name: "std", scope: null) ++!39 = !DIFile(filename: "library/std/src/io/stdio.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "6e6a519ce8370e29f07d850a34a413c1") ++!40 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicBool", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "c1cddf0305d4e6a98a8ddd4b6fdb5b91") ++!41 = !DINamespace(name: "atomic", scope: !42) ++!42 = !DINamespace(name: "sync", scope: !17) ++!43 = !DIGlobalVariableExpression(var: !44, expr: !DIExpression()) ++!44 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio5stdin8INSTANCE17h225ddf7c6608f4aaE", scope: !45, file: !39, line: 320, type: !46, isLocal: true, isDefinition: true, align: 64) ++!45 = !DINamespace(name: "stdin", scope: !36) ++!46 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>", scope: !47, file: !7, size: 448, align: 64, elements: !3, templateParams: !3, identifier: "2236c08b0846b8b2f33c235183822718") ++!47 = !DINamespace(name: "once_lock", scope: !48) ++!48 = !DINamespace(name: "sync", scope: !38) ++!49 = !DIGlobalVariableExpression(var: !50, expr: !DIExpression()) ++!50 = distinct !DIGlobalVariable(name: "STDOUT", linkageName: "_ZN3std2io5stdio6STDOUT17hd8472b9eb112f94aE", scope: !36, file: !39, line: 554, type: !51, isLocal: true, isDefinition: true, align: 64) ++!51 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>>", scope: !47, file: !7, size: 512, align: 64, elements: !3, templateParams: !3, identifier: "31535135376bcf9dc80438cb0beaa95") ++!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression()) ++!53 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio6stderr8INSTANCE17he81b75fda1609dccE", scope: !54, file: !39, line: 844, type: !55, isLocal: true, isDefinition: true, align: 64) ++!54 = !DINamespace(name: "stderr", scope: !36) ++!55 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ReentrantMutex>", scope: !56, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "5c48123cbde8afbfd832b70e8bb014b") ++!56 = !DINamespace(name: "remutex", scope: !57) ++!57 = !DINamespace(name: "sys_common", scope: !38) ++!58 = !DIGlobalVariableExpression(var: !59, expr: !DIExpression()) ++!59 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !60, isLocal: true, isDefinition: true) ++!60 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !61, templateParams: !3, identifier: "43681bec3eba7b0defb75fd847230ef3") ++!61 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "eda3cd8f60f00feb7019a3d90d2413dd") ++!62 = !DINamespace(name: "write_fmt", scope: !63) ++!63 = !DINamespace(name: "Write", scope: !37) ++!64 = !DIGlobalVariableExpression(var: !65, expr: !DIExpression()) ++!65 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !66, isLocal: true, isDefinition: true) ++!66 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !67, templateParams: !3, identifier: "2235adf22355a080446df25ada963d8f") ++!67 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "50f418463bae1beffe989359452b170a") ++!68 = !DIGlobalVariableExpression(var: !69, expr: !DIExpression()) ++!69 = distinct !DIGlobalVariable(name: "__KEY", linkageName: "_ZN3std2io5stdio14OUTPUT_CAPTURE7__getit5__KEY17h82ea5b0c4e81236dE", scope: !70, file: !72, line: 331, type: !73, isLocal: true, isDefinition: true, align: 64) ++!70 = !DINamespace(name: "__getit", scope: !71) ++!71 = !DINamespace(name: "OUTPUT_CAPTURE", scope: !36) ++!72 = !DIFile(filename: "library/std/src/thread/local.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "e3766fd5751a888dc2040f63031e944e") ++!73 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Key>>>>>", scope: !74, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "4d1514f685cbd010d7b86d2eef080b6c") ++!74 = !DINamespace(name: "fast", scope: !75) ++!75 = !DINamespace(name: "local", scope: !76) ++!76 = !DINamespace(name: "thread", scope: !38) ++!77 = !DIGlobalVariableExpression(var: !78, expr: !DIExpression()) ++!78 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !79, isLocal: true, isDefinition: true) ++!79 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !80, templateParams: !3, identifier: "1a7c0806435616633a284f48de1194c5") ++!80 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) ++!81 = !DIGlobalVariableExpression(var: !82, expr: !DIExpression()) ++!82 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !83, isLocal: true, isDefinition: true) ++!83 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !84, templateParams: !3, identifier: "8e82e7dafb168f2995a6711175975a8") ++!84 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "PathBuf", scope: !85, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "85bd755ad2187534379df2cc01ef53a0") ++!85 = !DINamespace(name: "path", scope: !38) ++!86 = !DIGlobalVariableExpression(var: !87, expr: !DIExpression()) ++!87 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !88, isLocal: true, isDefinition: true) ++!88 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !89, templateParams: !3, identifier: "a8f7c32dd1df279746df60c6d46ce35e") ++!89 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) ++!90 = !DIGlobalVariableExpression(var: !91, expr: !DIExpression()) ++!91 = distinct !DIGlobalVariable(name: "STATX_STATE", linkageName: "_ZN3std3sys4unix2fs9try_statx11STATX_STATE17h465ade0d62262837E", scope: !92, file: !96, line: 157, type: !97, isLocal: true, isDefinition: true, align: 8) ++!92 = !DINamespace(name: "try_statx", scope: !93) ++!93 = !DINamespace(name: "fs", scope: !94) ++!94 = !DINamespace(name: "unix", scope: !95) ++!95 = !DINamespace(name: "sys", scope: !38) ++!96 = !DIFile(filename: "library/std/src/sys/unix/fs.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "594559328c68ee77afe955cd571273ee") ++!97 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicU8", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "dda3b691bea8e1b5292414dd97926af2") ++!98 = !DIGlobalVariableExpression(var: !99, expr: !DIExpression()) ++!99 = distinct !DIGlobalVariable(name: "<&bool as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !100, isLocal: true, isDefinition: true) ++!100 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&bool as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !101, templateParams: !3, identifier: "5e8d2c48c9cc79c318e2bd28b03e141a") ++!101 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&bool", baseType: !89, size: 64, align: 64, dwarfAddressSpace: 0) ++!102 = !DIGlobalVariableExpression(var: !103, expr: !DIExpression()) ++!103 = distinct !DIGlobalVariable(name: "<&i32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !104, isLocal: true, isDefinition: true) ++!104 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&i32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !105, templateParams: !3, identifier: "d4029746615b6a868ffbc67515d99878") ++!105 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&i32", baseType: !80, size: 64, align: 64, dwarfAddressSpace: 0) ++!106 = !DIGlobalVariableExpression(var: !107, expr: !DIExpression()) ++!107 = distinct !DIGlobalVariable(name: "<&u32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !108, isLocal: true, isDefinition: true) ++!108 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&u32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !109, templateParams: !3, identifier: "178e0e76b9d9178d686381b2d05a7777") ++!109 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u32", baseType: !110, size: 64, align: 64, dwarfAddressSpace: 0) ++!110 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) ++!111 = !DIGlobalVariableExpression(var: !112, expr: !DIExpression()) ++!112 = distinct !DIGlobalVariable(name: "<&core::option::Option as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !113, isLocal: true, isDefinition: true) ++!113 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&core::option::Option as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !114, templateParams: !3, identifier: "7ca8386b4d420d719587fa3255329a7a") ++!114 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&core::option::Option", baseType: !115, size: 64, align: 64, dwarfAddressSpace: 0) ++!115 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Option", scope: !116, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "ad8474e495013fa1e3af4a6b53a05f4b") ++!116 = !DINamespace(name: "option", scope: !17) ++!117 = !DIGlobalVariableExpression(var: !118, expr: !DIExpression()) ++!118 = distinct !DIGlobalVariable(name: "HAS_CLONE3", linkageName: "_ZN3std3sys4unix7process13process_inner66_$LT$impl$u20$std..sys..unix..process..process_common..Command$GT$7do_fork10HAS_CLONE317h7d23eb353ae1c9a8E", scope: !119, file: !123, line: 148, type: !40, isLocal: true, isDefinition: true, align: 8) ++!119 = !DINamespace(name: "do_fork", scope: !120) ++!120 = !DINamespace(name: "{impl#0}", scope: !121) ++!121 = !DINamespace(name: "process_inner", scope: !122) ++!122 = !DINamespace(name: "process", scope: !94) ++!123 = !DIFile(filename: "library/std/src/sys/unix/process/process_unix.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "91761d638041a5dd66c0a64d968debe6") ++!124 = !DIGlobalVariableExpression(var: !125, expr: !DIExpression()) ++!125 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !126, isLocal: true, isDefinition: true) ++!126 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !127, templateParams: !3, identifier: "13903f30d26ee5869ef7a3fc63a2e03d") ++!127 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonZeroI32", scope: !128, file: !7, size: 32, align: 32, elements: !3, templateParams: !3, identifier: "e292f11a32f1ce5cf3b26864e4a0f5e5") ++!128 = !DINamespace(name: "nonzero", scope: !33) ++!129 = !DILocalVariable(name: "iterator", arg: 2, scope: !130, file: !131, line: 83, type: !137) ++!130 = distinct !DISubprogram(name: "spec_extend", linkageName: "_ZN132_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$alloc..vec..spec_extend..SpecExtend$LT$$RF$T$C$core..slice..iter..Iter$LT$T$GT$$GT$$GT$11spec_extend17hb56b69f474ec1e6dE", scope: !132, file: !131, line: 83, type: !135, scopeLine: 83, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) ++!131 = !DIFile(filename: "library/alloc/src/vec/spec_extend.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0614d5dabe9e343254af1b3fa1ec7315") ++!132 = !DINamespace(name: "{impl#4}", scope: !133) ++!133 = !DINamespace(name: "spec_extend", scope: !134) ++!134 = !DINamespace(name: "vec", scope: !11) ++!135 = distinct !DISubroutineType(types: !136) ++!136 = !{null} ++!137 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Iter", scope: !138, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "c31ab6f02ccece1f1a6e93425acabaa1") ++!138 = !DINamespace(name: "iter", scope: !139) ++!139 = !DINamespace(name: "slice", scope: !17) ++!140 = !DILocation(line: 0, scope: !130, inlinedAt: !141) ++!141 = distinct !DILocation(line: 2392, column: 9, scope: !142, inlinedAt: !146) ++!142 = distinct !DISubprogram(name: "extend_from_slice", linkageName: "_ZN5alloc3vec16Vec$LT$T$C$A$GT$17extend_from_slice17hbc8d29f2694fd768E", scope: !144, file: !143, line: 2391, type: !145, scopeLine: 2391, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) ++!143 = !DIFile(filename: "library/alloc/src/vec/mod.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0d69d0c0c11b3e47364cf6be0d07c829") ++!144 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Vec", scope: !134, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "f970dea4d30c1daf847db520fef9390d") ++!145 = distinct !DISubroutineType(types: !136) ++!146 = distinct !DILocation(line: 330, column: 9, scope: !147, inlinedAt: !154) ++!147 = distinct !DILexicalBlock(scope: !149, file: !148, line: 329, column: 9) ++!148 = !DIFile(filename: "library/std/src/io/buffered/bufreader.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "5375e06de487f85ee2f6d21c8a84ce7d") ++!149 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN82_$LT$std..io..buffered..bufreader..BufReader$LT$R$GT$$u20$as$u20$std..io..Read$GT$11read_to_end17h9f09720ee76e6db9E", scope: !150, file: !148, line: 328, type: !153, scopeLine: 328, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) ++!150 = !DINamespace(name: "{impl#3}", scope: !151) ++!151 = !DINamespace(name: "bufreader", scope: !152) ++!152 = !DINamespace(name: "buffered", scope: !37) ++!153 = distinct !DISubroutineType(types: !3) ++!154 = distinct !DILocation(line: 464, column: 9, scope: !155, inlinedAt: !158) ++!155 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN59_$LT$std..io..stdio..StdinLock$u20$as$u20$std..io..Read$GT$11read_to_end17h38999a681cc6c5b5E", scope: !156, file: !39, line: 463, type: !157, scopeLine: 463, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) ++!156 = !DINamespace(name: "{impl#7}", scope: !36) ++!157 = distinct !DISubroutineType(types: !3) ++!158 = distinct !DILocation(line: 430, column: 9, scope: !159) ++!159 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN55_$LT$std..io..stdio..Stdin$u20$as$u20$std..io..Read$GT$11read_to_end17haba70a09681d41d3E", scope: !160, file: !39, line: 429, type: !161, scopeLine: 429, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) ++!160 = !DINamespace(name: "{impl#5}", scope: !36) ++!161 = !DISubroutineType(types: !3) +diff --git a/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll b/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll +new file mode 100644 +index 000000000..25b4eeeca +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll +@@ -0,0 +1,254 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc < %s -mtriple=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC %s ++; RUN: llc < %s -mtriple=sparc64 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC64 %s ++ ++;; Structs up to six registers in size can be returned in registers. ++;; Note that the maximum return size and member placement is NOT ++;; compatible with the C ABI - see SparcCallingConv.td. ++define { i32, i32 } @ret_i32_pair(i32 %a0, i32 %a1, i32* %p, i32* %q) { ++; SPARC-LABEL: ret_i32_pair: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -96, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: ld [%i2], %i0 ++; SPARC-NEXT: st %g0, [%i2] ++; SPARC-NEXT: ld [%i3], %i1 ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: ret_i32_pair: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -128, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: ld [%i2], %i0 ++; SPARC64-NEXT: st %g0, [%i2] ++; SPARC64-NEXT: ld [%i3], %i1 ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %r1 = load i32, i32* %p ++ %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 0 ++ store i32 0, i32* %p ++ %r2 = load i32, i32* %q ++ %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 1 ++ ret { i32, i32 } %rv2 ++} ++ ++define void @call_ret_i32_pair(i32* %i0) { ++; SPARC-LABEL: call_ret_i32_pair: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -96, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: call ret_i32_pair ++; SPARC-NEXT: nop ++; SPARC-NEXT: st %o0, [%i0] ++; SPARC-NEXT: st %o1, [%i0] ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: call_ret_i32_pair: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -176, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: call ret_i32_pair ++; SPARC64-NEXT: nop ++; SPARC64-NEXT: st %o0, [%i0] ++; SPARC64-NEXT: st %o1, [%i0] ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %rv = call { i32, i32 } @ret_i32_pair(i32 undef, i32 undef, ++ i32* undef, i32* undef) ++ %e0 = extractvalue { i32, i32 } %rv, 0 ++ store volatile i32 %e0, i32* %i0 ++ %e1 = extractvalue { i32, i32 } %rv, 1 ++ store i32 %e1, i32* %i0 ++ ret void ++} ++ ++;; Functions returning structs more than six registers' worth of space ++;; should be automatically treated as an sret function. ++declare { [16 x i32] } @ret_i32_arr(i32 %input) ++ ++define i32 @call_ret_i32_arr(i32 %0) { ++; SPARC-LABEL: call_ret_i32_arr: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -160, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: add %fp, -64, %i1 ++; SPARC-NEXT: st %i1, [%sp+64] ++; SPARC-NEXT: mov %i0, %o0 ++; SPARC-NEXT: call ret_i32_arr ++; SPARC-NEXT: nop ++; SPARC-NEXT: unimp 64 ++; SPARC-NEXT: ld [%fp+-4], %i0 ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: call_ret_i32_arr: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -240, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: add %fp, 1983, %o0 ++; SPARC64-NEXT: mov %i0, %o1 ++; SPARC64-NEXT: call ret_i32_arr ++; SPARC64-NEXT: nop ++; SPARC64-NEXT: ld [%fp+2043], %i0 ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %2 = call { [16 x i32] } @ret_i32_arr(i32 %0) ++ %3 = extractvalue { [16 x i32] } %2, 0 ++ %4 = extractvalue [16 x i32] %3, 15 ++ ret i32 %4 ++} ++ ++;; Structs up to six registers in size can be returned in registers. ++;; Note that the maximum return size and member placement is NOT ++;; compatible with the C ABI - see SparcCallingConv.td. ++define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) { ++; SPARC-LABEL: ret_i64_pair: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -96, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: mov %g0, %i4 ++; SPARC-NEXT: ldd [%i2], %i0 ++; SPARC-NEXT: mov %i4, %i5 ++; SPARC-NEXT: std %i4, [%i2] ++; SPARC-NEXT: ldd [%i3], %i2 ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: ret_i64_pair: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -128, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: ldx [%i2], %i0 ++; SPARC64-NEXT: stx %g0, [%i2] ++; SPARC64-NEXT: ldx [%i3], %i1 ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %r1 = load i64, i64* %p ++ %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0 ++ store i64 0, i64* %p ++ %r2 = load i64, i64* %q ++ %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1 ++ ret { i64, i64 } %rv2 ++} ++ ++define void @call_ret_i64_pair(i64* %i0) { ++; SPARC-LABEL: call_ret_i64_pair: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -96, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: call ret_i64_pair ++; SPARC-NEXT: nop ++; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1 ++; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3 ++; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1 ++; SPARC-NEXT: std %o0, [%i0] ++; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3 ++; SPARC-NEXT: std %o2, [%i0] ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: call_ret_i64_pair: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -176, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: call ret_i64_pair ++; SPARC64-NEXT: nop ++; SPARC64-NEXT: stx %o0, [%i0] ++; SPARC64-NEXT: stx %o1, [%i0] ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef, ++ i64* undef, i64* undef) ++ %e0 = extractvalue { i64, i64 } %rv, 0 ++ store volatile i64 %e0, i64* %i0 ++ %e1 = extractvalue { i64, i64 } %rv, 1 ++ store i64 %e1, i64* %i0 ++ ret void ++} ++ ++;; Functions returning structs more than six registers' worth of space ++;; should be automatically treated as an sret function. ++declare { [16 x i64] } @ret_i64_arr(i64 %input) ++ ++define i64 @call_ret_i64_arr(i64 %0) { ++; SPARC-LABEL: call_ret_i64_arr: ++; SPARC: .cfi_startproc ++; SPARC-NEXT: ! %bb.0: ++; SPARC-NEXT: save %sp, -224, %sp ++; SPARC-NEXT: .cfi_def_cfa_register %fp ++; SPARC-NEXT: .cfi_window_save ++; SPARC-NEXT: .cfi_register %o7, %i7 ++; SPARC-NEXT: add %fp, -128, %i2 ++; SPARC-NEXT: st %i2, [%sp+64] ++; SPARC-NEXT: mov %i0, %o0 ++; SPARC-NEXT: mov %i1, %o1 ++; SPARC-NEXT: call ret_i64_arr ++; SPARC-NEXT: nop ++; SPARC-NEXT: unimp 128 ++; SPARC-NEXT: ldd [%fp+-8], %i0 ++; SPARC-NEXT: restore ++; SPARC-NEXT: retl ++; SPARC-NEXT: nop ++; ++; SPARC64-LABEL: call_ret_i64_arr: ++; SPARC64: .cfi_startproc ++; SPARC64-NEXT: ! %bb.0: ++; SPARC64-NEXT: save %sp, -304, %sp ++; SPARC64-NEXT: .cfi_def_cfa_register %fp ++; SPARC64-NEXT: .cfi_window_save ++; SPARC64-NEXT: .cfi_register %o7, %i7 ++; SPARC64-NEXT: add %fp, 1919, %o0 ++; SPARC64-NEXT: mov %i0, %o1 ++; SPARC64-NEXT: call ret_i64_arr ++; SPARC64-NEXT: nop ++; SPARC64-NEXT: ldx [%fp+2039], %i0 ++; SPARC64-NEXT: restore ++; SPARC64-NEXT: retl ++; SPARC64-NEXT: nop ++ %2 = call { [16 x i64] } @ret_i64_arr(i64 %0) ++ %3 = extractvalue { [16 x i64] } %2, 0 ++ %4 = extractvalue [16 x i64] %3, 15 ++ ret i64 %4 ++} +diff --git a/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll b/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll +new file mode 100644 +index 000000000..33e501ca8 +--- /dev/null ++++ b/src/llvm-project/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll +@@ -0,0 +1,112 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -opaque-pointers | FileCheck %s --check-prefix=I386 ++; ++; Make sure we don't zero out %eax when both %ah and %al are used. ++; ++; PR1766: https://github.com/ClangBuiltLinux/linux/issues/1766 ++ ++%struct.maple_subtree_state = type { ptr } ++ ++@mas_data_end_type = dso_local local_unnamed_addr global i32 0, align 4 ++@ma_meta_end_mn_0_0_0_0_0_0 = dso_local local_unnamed_addr global i8 0, align 1 ++@mt_pivots_0 = dso_local local_unnamed_addr global i8 0, align 1 ++@mas_data_end___trans_tmp_2 = dso_local local_unnamed_addr global ptr null, align 4 ++@mt_slots_0 = dso_local local_unnamed_addr global i8 0, align 1 ++ ++define dso_local zeroext i1 @test1(ptr nocapture noundef readonly %0) local_unnamed_addr "zero-call-used-regs"="used-gpr" nounwind { ++; I386-LABEL: test1: ++; I386: # %bb.0: ++; I386-NEXT: pushl %ebx ++; I386-NEXT: subl $24, %esp ++; I386-NEXT: movl {{[0-9]+}}(%esp), %eax ++; I386-NEXT: movl (%eax), %eax ++; I386-NEXT: movzbl (%eax), %ebx ++; I386-NEXT: calll bar ++; I386-NEXT: testb %al, %al ++; I386-NEXT: # implicit-def: $al ++; I386-NEXT: # kill: killed $al ++; I386-NEXT: je .LBB0_6 ++; I386-NEXT: # %bb.1: ++; I386-NEXT: cmpl $0, mas_data_end_type ++; I386-NEXT: je .LBB0_3 ++; I386-NEXT: # %bb.2: ++; I386-NEXT: movzbl ma_meta_end_mn_0_0_0_0_0_0, %eax ++; I386-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ++; I386-NEXT: jmp .LBB0_6 ++; I386-NEXT: .LBB0_3: ++; I386-NEXT: movb mt_pivots_0, %ah ++; I386-NEXT: movb %ah, %al ++; I386-NEXT: decb %al ++; I386-NEXT: movl mas_data_end___trans_tmp_2, %ecx ++; I386-NEXT: movsbl %al, %edx ++; I386-NEXT: cmpl $0, (%ecx,%edx,4) ++; I386-NEXT: je .LBB0_5 ++; I386-NEXT: # %bb.4: ++; I386-NEXT: movb %al, %ah ++; I386-NEXT: .LBB0_5: ++; I386-NEXT: movb %ah, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ++; I386-NEXT: .LBB0_6: ++; I386-NEXT: movb mt_slots_0, %bh ++; I386-NEXT: leal {{[0-9]+}}(%esp), %eax ++; I386-NEXT: movl %eax, (%esp) ++; I386-NEXT: calll baz ++; I386-NEXT: subl $4, %esp ++; I386-NEXT: cmpb %bh, %bl ++; I386-NEXT: jae .LBB0_8 ++; I386-NEXT: # %bb.7: ++; I386-NEXT: movsbl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 1-byte Folded Reload ++; I386-NEXT: movl %eax, (%esp) ++; I386-NEXT: calll gaz ++; I386-NEXT: .LBB0_8: ++; I386-NEXT: movb $1, %al ++; I386-NEXT: addl $24, %esp ++; I386-NEXT: popl %ebx ++; I386-NEXT: xorl %ecx, %ecx ++; I386-NEXT: xorl %edx, %edx ++; I386-NEXT: retl ++ %2 = alloca %struct.maple_subtree_state, align 4 ++ %3 = load ptr, ptr %0, align 4 ++ %4 = load i8, ptr %3, align 1 ++ %5 = tail call zeroext i1 @bar() ++ br i1 %5, label %6, label %20 ++ ++6: ; preds = %1 ++ %7 = load i32, ptr @mas_data_end_type, align 4 ++ %8 = icmp eq i32 %7, 0 ++ br i1 %8, label %11, label %9 ++ ++9: ; preds = %6 ++ %10 = load i8, ptr @ma_meta_end_mn_0_0_0_0_0_0, align 1 ++ br label %20 ++ ++11: ; preds = %6 ++ %12 = load i8, ptr @mt_pivots_0, align 1 ++ %13 = add i8 %12, -1 ++ %14 = load ptr, ptr @mas_data_end___trans_tmp_2, align 4 ++ %15 = sext i8 %13 to i32 ++ %16 = getelementptr inbounds [1 x i32], ptr %14, i32 0, i32 %15 ++ %17 = load i32, ptr %16, align 4 ++ %18 = icmp eq i32 %17, 0 ++ %19 = select i1 %18, i8 %12, i8 %13 ++ br label %20 ++ ++20: ; preds = %11, %9, %1 ++ %21 = phi i8 [ undef, %1 ], [ %10, %9 ], [ %19, %11 ] ++ %22 = load i8, ptr @mt_slots_0, align 1 ++ call void @baz(ptr nonnull sret(%struct.maple_subtree_state) align 4 %2) ++ %23 = icmp ult i8 %4, %22 ++ br i1 %23, label %24, label %25 ++ ++24: ; preds = %20 ++ call void @gaz(i8 noundef signext %21) ++ br label %25 ++ ++25: ; preds = %20, %24 ++ ret i1 true ++} ++ ++declare dso_local zeroext i1 @bar(...) local_unnamed_addr ++ ++declare dso_local void @baz(ptr sret(%struct.maple_subtree_state) align 4, ...) local_unnamed_addr ++ ++declare dso_local void @gaz(i8 noundef signext) local_unnamed_addr +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s b/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s +new file mode 100644 +index 000000000..2ef26ac4b +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/aligned-nops.s +@@ -0,0 +1,25 @@ ++# RUN: llvm-mc -filetype=obj -triple loongarch64 < %s \ ++# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s ++ ++# alpha and main are 8 byte alignment ++# but the alpha function's size is 4 ++# So assembler will insert a nop to make sure 8 byte alignment. ++ ++ .text ++ .p2align 3 ++ .type alpha,@function ++alpha: ++# BB#0: ++ addi.d $sp, $sp, -16 ++# CHECK-INST: nop ++.Lfunc_end0: ++ .size alpha, .Lfunc_end0-alpha ++ # -- End function ++ .globl main ++ .p2align 3 ++ .type main,@function ++main: # @main ++# BB#0: ++.Lfunc_end1: ++ .size main, .Lfunc_end1-main ++ # -- End function +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s b/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s +new file mode 100644 +index 000000000..7e61a5ba5 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/atomic-error.s +@@ -0,0 +1,7 @@ ++# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 | FileCheck %s ++ ++# CHECK: error: expected memory with constant 0 offset ++amadd_db.d $a1, $t5, $s6, 1 ++ ++# CHECK: error: unexpected token in argument list ++amadd_db.d $a1, $t5, $s6, a +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/atomic.s b/src/llvm-project/llvm/test/MC/LoongArch/atomic.s +new file mode 100644 +index 000000000..10a406550 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/atomic.s +@@ -0,0 +1,12 @@ ++# RUN: llvm-mc %s --triple=loongarch64 --show-encoding | \ ++# RUN: FileCheck --check-prefixes=ASM,ASM-AND-OBJ %s ++# RUN: llvm-mc %s --triple=loongarch64 --filetype=obj | llvm-objdump -d - | \ ++# RUN: FileCheck --check-prefixes=ASM-AND-OBJ %s ++ ++# ASM-AND-OBJ: amadd_db.d $r5, $r17, $r29, 0 ++# ASM: encoding: [0xa5,0xc7,0x6a,0x38] ++amadd_db.d $a1, $t5, $s6, 0 ++ ++# ASM-AND-OBJ: amadd_db.d $r5, $r17, $r29, 0 ++# ASM: encoding: [0xa5,0xc7,0x6a,0x38] ++amadd_db.d $a1, $t5, $s6 +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s b/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s +new file mode 100644 +index 000000000..d35fe7e77 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/fixups-expr.s +@@ -0,0 +1,40 @@ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s \ ++# RUN: | llvm-readobj -r - | FileCheck %s ++ ++# Check that subtraction expressions are emitted as two relocations ++ ++.globl G1 ++.globl G2 ++.L1: ++G1: ++nop ++.L2: ++G2: ++ ++.data ++.8byte .L2-.L1 # CHECK: 0x0 R_LARCH_ADD64 .L2 0x0 ++ # CHECK: 0x0 R_LARCH_SUB64 .L1 0x0 ++.8byte G2-G1 # CHECK: 0x8 R_LARCH_ADD64 G2 0x0 ++ # CHECK: 0x8 R_LARCH_SUB64 G1 0x0 ++.4byte .L2-.L1 # CHECK: 0x10 R_LARCH_ADD32 .L2 0x0 ++ # CHECK: 0x10 R_LARCH_SUB32 .L1 0x0 ++.4byte G2-G1 # CHECK: 0x14 R_LARCH_ADD32 G2 0x0 ++ # CHECK: 0x14 R_LARCH_SUB32 G1 0x0 ++.2byte .L2-.L1 # CHECK: 0x18 R_LARCH_ADD16 .L2 0x0 ++ # CHECK: 0x18 R_LARCH_SUB16 .L1 0x0 ++.2byte G2-G1 # CHECK: 0x1A R_LARCH_ADD16 G2 0x0 ++ # CHECK: 0x1A R_LARCH_SUB16 G1 0x0 ++.byte .L2-.L1 # CHECK: 0x1C R_LARCH_ADD8 .L2 0x0 ++ # CHECK: 0x1C R_LARCH_SUB8 .L1 0x0 ++.byte G2-G1 # CHECK: 0x1D R_LARCH_ADD8 G2 0x0 ++ # CHECK: 0x1D R_LARCH_SUB8 G1 0x0 ++ ++.section .rodata.str.1 ++.L.str: ++.asciz "string" ++ ++.rodata ++.Lreltable: ++.word .L.str-.Lreltable # CHECK: 0x0 R_LARCH_ADD32 .L.str 0x0 ++ # CHECK: 0x0 R_LARCH_SUB32 .Lreltable 0x0 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/invalid.s b/src/llvm-project/llvm/test/MC/LoongArch/invalid.s +new file mode 100644 +index 000000000..e0fc7ce4b +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/invalid.s +@@ -0,0 +1,50 @@ ++# RUN: not llvm-mc %s -triple=loongarch64-unknown-linux-gnu 2>&1 | FileCheck %s ++.text ++csrxchg $r6, $r0, 214 # CHECK: :[[@LINE]]:1: error: invalid operand ($zero) for instruction ++csrxchg $r6, $r1, 214 # CHECK: :[[@LINE]]:1: error: invalid operand ($r1) for instruction ++ ++## out-of-bound immediate ++### simm16 << 2 ++beq $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++beq $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bne $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bne $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++blt $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++blt $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bge $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bge $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bltu $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bltu $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bgeu $r10, $r7, -0x20000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bgeu $r10, $r7, 0x1FFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++### simm21 << 2 ++beqz $r9, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++beqz $r9, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bnez $r9, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bnez $r9, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bceqz $fcc6, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bceqz $fcc6, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bcnez $fcc6, -0x400000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bcnez $fcc6, 0x3FFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++### simm26 << 2 ++b -0x8000000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++b 0x7FFFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bl -0x8000000-4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++bl 0x7FFFFFC+4 # CHECK: :[[@LINE]]:1: error: branch target out of range ++ ++## unaligned immediate ++### simm16 << 2 ++beq $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bne $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++blt $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bge $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bltu $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bgeu $r10, $r7, 0x1FFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++### simm21 << 2 ++beqz $r9, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bnez $r9, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bceqz $fcc6, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bcnez $fcc6, 0x3FFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++### simm26 << 2 ++b 0x7FFFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address ++bl 0x7FFFFFC+1 # CHECK: :[[@LINE]]:1: error: branch to misaligned address +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg +index 2b5a4893e..6223fc691 100644 +--- a/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg ++++ b/src/llvm-project/llvm/test/MC/LoongArch/lit.local.cfg +@@ -1,2 +1,3 @@ + if not 'LoongArch' in config.root.targets: + config.unsupported = True ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s b/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s +new file mode 100644 +index 000000000..eca76ac69 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/macro-la.s +@@ -0,0 +1,168 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: la.pcrel $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: (symbol)+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] ++# CHECK: # fixup A - offset: 0, value: (symbol)+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: (symbol)+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup C - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup E - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup G - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.local $a0, symbol ++ ++# CHECK: la.got $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.global $a0, symbol ++ ++# CHECK: la.pcrel $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: (symbol)+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] ++# CHECK: # fixup A - offset: 0, value: (symbol)+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: (symbol)+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup C - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup E - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup G - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.pcrel $a0, symbol ++ ++# CHECK: la.got $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_GPREL ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.got $a0, symbol ++ ++# CHECK: la.tls.le $r4, symbol # encoding: [0x04,0x00,0x00,0x14] ++# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL ++# CHECK: # fixup B - offset: 0, value: 32, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup D - offset: 0, value: 44, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0x80,0x03] ++# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL ++# CHECK: # fixup B - offset: 0, value: 4095, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_AND ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_U_10_12 ++# CHECK: # la expanded slot # encoding: [0x04,0x00,0x00,0x16] ++# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL ++# CHECK: # fixup B - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup D - offset: 0, value: 44, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0x00,0x03] ++# CHECK: # fixup A - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_TPREL ++# CHECK: # fixup B - offset: 0, value: 52, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup D - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.tls.le $a0, symbol ++ ++# CHECK: la.tls.ie $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x28] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GOT ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.tls.ie $a0, symbol ++ ++# CHECK: la.tls.gd $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.tls.ld $a0, symbol ++ ++# CHECK: la.tls.gd $r4, symbol # encoding: [0x04,0x00,0x00,0x1c] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2048, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup E - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_5_20 ++# CHECK: # la expanded slot # encoding: [0x84,0x00,0xc0,0x02] ++# CHECK: # fixup A - offset: 0, value: _GLOBAL_OFFSET_TABLE_+4, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup B - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup C - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup D - offset: 0, value: _GLOBAL_OFFSET_TABLE_+2052, kind: fixup_LARCH_SOP_PUSH_PCREL ++# CHECK: # fixup E - offset: 0, value: symbol, kind: fixup_LARCH_SOP_PUSH_TLS_GD ++# CHECK: # fixup F - offset: 0, value: 0, kind: fixup_LARCH_SOP_ADD ++# CHECK: # fixup G - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup H - offset: 0, value: 0, kind: fixup_LARCH_SOP_SR ++# CHECK: # fixup I - offset: 0, value: 12, kind: fixup_LARCH_SOP_PUSH_ABSOLUTE ++# CHECK: # fixup J - offset: 0, value: 0, kind: fixup_LARCH_SOP_SL ++# CHECK: # fixup K - offset: 0, value: 0, kind: fixup_LARCH_SOP_SUB ++# CHECK: # fixup L - offset: 0, value: 0, kind: fixup_LARCH_SOP_POP_32_S_10_12 ++la.tls.gd $a0, symbol +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s b/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s +new file mode 100644 +index 000000000..b1a7c58ba +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/macro-li.s +@@ -0,0 +1,773 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu | FileCheck %s ++li.w $a0, 0x00000000 # CHECK: ori $r4, $zero, 0 ++li.w $a0, 0x000007ff # CHECK: ori $r4, $zero, 2047 ++li.w $a0, 0x00000800 # CHECK: ori $r4, $zero, 2048 ++li.w $a0, 0x00000fff # CHECK: ori $r4, $zero, 4095 ++li.w $a0, 0x7ffff000 # CHECK: lu12i.w $r4, 524287 ++li.w $a0, 0x7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++li.w $a0, 0x7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++li.w $a0, 0x7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++li.w $a0, 0x80000000 # CHECK: lu12i.w $r4, -524288 ++li.w $a0, 0x800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++li.w $a0, 0x80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++li.w $a0, 0x80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++li.w $a0, 0xfffff000 # CHECK: lu12i.w $r4, -1 ++li.w $a0, 0xfffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++li.w $a0, 0xfffff800 # CHECK: addi.w $r4, $zero, -2048 ++li.w $a0, 0xffffffff # CHECK: addi.w $r4, $zero, -1 ++li.d $a0, 0x0000000000000000 # CHECK: addi.d $r4, $zero, 0 ++li.d $a0, 0x00000000000007ff # CHECK: addi.d $r4, $zero, 2047 ++li.d $a0, 0x0000000000000800 # CHECK: ori $r4, $zero, 2048 ++li.d $a0, 0x0000000000000fff # CHECK: ori $r4, $zero, 4095 ++li.d $a0, 0x000000007ffff000 # CHECK: lu12i.w $r4, 524287 ++li.d $a0, 0x000000007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++li.d $a0, 0x000000007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++li.d $a0, 0x000000007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++li.d $a0, 0x0000000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x00000000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x0000000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x0000000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x00000000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x00000000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x00000000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x00000000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 0 ++li.d $a0, 0x0007ffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007fffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007fffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007fffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0007ffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 524287 ++li.d $a0, 0x0008000000000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x0008000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x0008000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000800007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000800007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000800007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000800007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x0008000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x0008000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x0008000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x00080000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000ffffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000ffffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000ffffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x000fffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu52i.d $r4, $r4, 0 ++li.d $a0, 0x7ff0000000000000 # CHECK: lu52i.d $r4, $zero, 2047 ++li.d $a0, 0x7ff00000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff0000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff0000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff000007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff000007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff000007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff000007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff0000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff00000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff0000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff0000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff00000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff00000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff00000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff00000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7fffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7fffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7fffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff7ffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000000000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff800007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff800007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff800007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff800007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff8000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ff80000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ffffffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ffffffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7ffffffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x7fffffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu52i.d $r4, $r4, 2047 ++li.d $a0, 0x8000000000000000 # CHECK: lu52i.d $r4, $zero, -2048 ++li.d $a0, 0x80000000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8000000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8000000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800000007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800000007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800000007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800000007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8000000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80000000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8000000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8000000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80000000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80000000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80000000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80000000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007fffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007fffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007fffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8007ffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000000000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800800007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800800007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800800007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800800007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x8008000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x80080000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800ffffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800ffffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800ffffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0x800fffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu52i.d $r4, $r4, -2048 ++li.d $a0, 0xfff0000000000000 # CHECK: lu52i.d $r4, $zero, -1 ++li.d $a0, 0xfff00000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff0000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff0000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff000007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff000007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff000007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff000007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff0000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff00000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff0000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff0000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff00000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff00000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff00000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff00000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 0 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff80000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7fffffffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7fffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7fffffffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff7ffffffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, 524287 ++ # CHECK: lu52i.d $r4, $r4, -1 ++li.d $a0, 0xfff8000000000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff8000000000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff8000000000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff800007ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff800007ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff800007ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff800007fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff8000080000000 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff8000080000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff8000080000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000fffff000 # CHECK: lu12i.w $r4, -1 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000fffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000fffff800 # CHECK: addi.w $r4, $zero, -2048 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xfff80000ffffffff # CHECK: addi.w $r4, $zero, -1 ++ # CHECK: lu32i.d $r4, -524288 ++li.d $a0, 0xffffffff00000000 # CHECK: ori $r4, $zero, 0 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff000007ff # CHECK: ori $r4, $zero, 2047 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff00000800 # CHECK: ori $r4, $zero, 2048 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff00000fff # CHECK: ori $r4, $zero, 4095 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff7ffff000 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff7ffff7ff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2047 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff7ffff800 # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 2048 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff7fffffff # CHECK: lu12i.w $r4, 524287 ++ # CHECK: ori $r4, $r4, 4095 ++ # CHECK: lu32i.d $r4, -1 ++li.d $a0, 0xffffffff80000000 # CHECK: lu12i.w $r4, -524288 ++li.d $a0, 0xffffffff800007ff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2047 ++li.d $a0, 0xffffffff80000800 # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 2048 ++li.d $a0, 0xffffffff80000fff # CHECK: lu12i.w $r4, -524288 ++ # CHECK: ori $r4, $r4, 4095 ++li.d $a0, 0xfffffffffffff000 # CHECK: lu12i.w $r4, -1 ++li.d $a0, 0xfffffffffffff7ff # CHECK: lu12i.w $r4, -1 ++ # CHECK: ori $r4, $r4, 2047 ++li.d $a0, 0xfffffffffffff800 # CHECK: addi.d $r4, $zero, -2048 ++li.d $a0, 0xffffffffffffffff # CHECK: addi.d $r4, $zero, -1 +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s +new file mode 100644 +index 000000000..ed44180bf +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_12imm.s +@@ -0,0 +1,33 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: slti $r27, $ra, 235 ++# CHECK: encoding: [0x3b,0xac,0x03,0x02] ++slti $r27, $ra, 235 ++ ++# CHECK: sltui $zero, $r8, 162 ++# CHECK: encoding: [0x00,0x89,0x42,0x02] ++sltui $zero, $r8, 162 ++ ++# CHECK: addi.w $r5, $r7, 246 ++# CHECK: encoding: [0xe5,0xd8,0x83,0x02] ++addi.w $r5, $r7, 246 ++ ++# CHECK: addi.d $r28, $r6, 75 ++# CHECK: encoding: [0xdc,0x2c,0xc1,0x02] ++addi.d $r28, $r6, 75 ++ ++# CHECK: lu52i.d $r13, $r4, 195 ++# CHECK: encoding: [0x8d,0x0c,0x03,0x03] ++lu52i.d $r13, $r4, 195 ++ ++# CHECK: andi $r25, $zero, 106 ++# CHECK: encoding: [0x19,0xa8,0x41,0x03] ++andi $r25, $zero, 106 ++ ++# CHECK: ori $r17, $r5, 47 ++# CHECK: encoding: [0xb1,0xbc,0x80,0x03] ++ori $r17, $r5, 47 ++ ++# CHECK: xori $r18, $r23, 99 ++# CHECK: encoding: [0xf2,0x8e,0xc1,0x03] ++xori $r18, $r23, 99 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s +new file mode 100644 +index 000000000..1418bb677 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_4operands.s +@@ -0,0 +1,53 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: fmadd.s $f3, $f16, $f3, $f15 ++# CHECK: encoding: [0x03,0x8e,0x17,0x08] ++fmadd.s $f3, $f16, $f3, $f15 ++ ++# CHECK: fmadd.d $f21, $f24, $f28, $f24 ++# CHECK: encoding: [0x15,0x73,0x2c,0x08] ++fmadd.d $f21, $f24, $f28, $f24 ++ ++# CHECK: fmsub.s $f23, $f11, $f21, $f4 ++# CHECK: encoding: [0x77,0x55,0x52,0x08] ++fmsub.s $f23, $f11, $f21, $f4 ++ ++# CHECK: fmsub.d $f6, $f18, $f20, $f27 ++# CHECK: encoding: [0x46,0xd2,0x6d,0x08] ++fmsub.d $f6, $f18, $f20, $f27 ++ ++# CHECK: fnmadd.s $f29, $f1, $f24, $f20 ++# CHECK: encoding: [0x3d,0x60,0x9a,0x08] ++fnmadd.s $f29, $f1, $f24, $f20 ++ ++# CHECK: fnmadd.d $f25, $f13, $f19, $f30 ++# CHECK: encoding: [0xb9,0x4d,0xaf,0x08] ++fnmadd.d $f25, $f13, $f19, $f30 ++ ++# CHECK: fnmsub.s $f8, $f4, $f24, $f25 ++# CHECK: encoding: [0x88,0xe0,0xdc,0x08] ++fnmsub.s $f8, $f4, $f24, $f25 ++ ++# CHECK: fnmsub.d $f30, $f26, $f7, $f24 ++# CHECK: encoding: [0x5e,0x1f,0xec,0x08] ++fnmsub.d $f30, $f26, $f7, $f24 ++ ++# CHECK: fcmp.ceq.s $fcc7, $f17, $f29 ++# CHECK: encoding: [0x27,0x76,0x12,0x0c] ++fcmp.ceq.s $fcc7, $f17, $f29 ++ ++# CHECK: fcmp.ceq.d $fcc4, $f12, $f9 ++# CHECK: encoding: [0x84,0x25,0x22,0x0c] ++fcmp.ceq.d $fcc4, $f12, $f9 ++ ++# CHECK: fcmp.cult.s $fcc0, $f0, $f1 ++# CHECK: encoding: [0x00,0x04,0x15,0x0c] ++fcmp.cult.s $fcc0, $f0, $f1 ++ ++# CHECK: fcmp.cult.d $fcc2, $f3, $f4 ++# CHECK: encoding: [0x62,0x10,0x25,0x0c] ++fcmp.cult.d $fcc2, $f3, $f4 ++ ++# CHECK: fsel $f18, $f20, $f21, $fcc4 ++# CHECK: encoding: [0x92,0x56,0x02,0x0d] ++fsel $f18, $f20, $f21, $fcc4 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s +new file mode 100644 +index 000000000..d7b3bbb7d +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_bigimm.s +@@ -0,0 +1,33 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: addu16i.d $r9, $r23, 23 ++# CHECK: encoding: [0xe9,0x5e,0x00,0x10] ++addu16i.d $r9, $r23, 23 ++ ++# CHECK: lu12i.w $r16, 49 ++# CHECK: encoding: [0x30,0x06,0x00,0x14] ++lu12i.w $r16, 49 ++ ++# CHECK: lu12i.w $r4, -1 ++# CHECK: encoding: [0xe4,0xff,0xff,0x15] ++lu12i.w $r4, -1 ++ ++# CHECK: lu32i.d $sp, 196 ++# CHECK: encoding: [0x83,0x18,0x00,0x16] ++lu32i.d $sp, 196 ++ ++# CHECK: pcaddi $r9, 187 ++# CHECK: encoding: [0x69,0x17,0x00,0x18] ++pcaddi $r9, 187 ++ ++# CHECK: pcalau12i $r10, 89 ++# CHECK: encoding: [0x2a,0x0b,0x00,0x1a] ++pcalau12i $r10, 89 ++ ++# CHECK: pcaddu12i $zero, 37 ++# CHECK: encoding: [0xa0,0x04,0x00,0x1c] ++pcaddu12i $zero, 37 ++ ++# CHECK: pcaddu18i $r12, 26 ++# CHECK: encoding: [0x4c,0x03,0x00,0x1e] ++pcaddu18i $r12, 26 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s +new file mode 100644 +index 000000000..256e70b6d +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_branch.s +@@ -0,0 +1,155 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding \ ++# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ,CHECK-ASM %s ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -filetype=obj \ ++# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-ASM-AND-OBJ %s ++ ++## random operands ++# CHECK-ASM-AND-OBJ: beqz $r9, 96 ++# CHECK-ASM: encoding: [0x20,0x61,0x00,0x40] ++beqz $r9, 96 ++ ++# CHECK-ASM-AND-OBJ: bnez $sp, 212 ++# CHECK-ASM: encoding: [0x60,0xd4,0x00,0x44] ++bnez $sp, 212 ++ ++# CHECK-ASM-AND-OBJ: bceqz $fcc6, 12 ++# CHECK-ASM: encoding: [0xc0,0x0c,0x00,0x48] ++bceqz $fcc6, 12 ++ ++# CHECK-ASM-AND-OBJ: bcnez $fcc6, 72 ++# CHECK-ASM: encoding: [0xc0,0x49,0x00,0x48] ++bcnez $fcc6, 72 ++ ++# CHECK-ASM-AND-OBJ: b 248 ++# CHECK-ASM: encoding: [0x00,0xf8,0x00,0x50] ++b 248 ++ ++# CHECK-ASM-AND-OBJ: bl 236 ++# CHECK-ASM: encoding: [0x00,0xec,0x00,0x54] ++bl 236 ++ ++# CHECK-ASM-AND-OBJ: beq $r10, $r7, 176 ++# CHECK-ASM: encoding: [0x47,0xb1,0x00,0x58] ++beq $r10, $r7, 176 ++ ++# CHECK-ASM-AND-OBJ: bne $r25, $ra, 136 ++# CHECK-ASM: encoding: [0x21,0x8b,0x00,0x5c] ++bne $r25, $ra, 136 ++ ++# CHECK-ASM-AND-OBJ: blt $r15, $r30, 168 ++# CHECK-ASM: encoding: [0xfe,0xa9,0x00,0x60] ++blt $r15, $r30, 168 ++ ++# CHECK-ASM-AND-OBJ: bge $r12, $r15, 148 ++# CHECK-ASM: encoding: [0x8f,0x95,0x00,0x64] ++bge $r12, $r15, 148 ++ ++# CHECK-ASM-AND-OBJ: bltu $r17, $r5, 4 ++# CHECK-ASM: encoding: [0x25,0x06,0x00,0x68] ++bltu $r17, $r5, 4 ++ ++# CHECK-ASM-AND-OBJ: bgeu $r6, $r23, 140 ++# CHECK-ASM: encoding: [0xd7,0x8c,0x00,0x6c] ++bgeu $r6, $r23, 140 ++ ++ ++## immediate lower/upper boundary ++### simm16 << 2 ++# CHECK-ASM-AND-OBJ: beq $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x5a] ++beq $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: beq $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x59] ++beq $r10, $r7, 0x1FFFC ++ ++# CHECK-ASM-AND-OBJ: bne $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x5e] ++bne $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: bne $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x5d] ++bne $r10, $r7, 0x1FFFC ++ ++# CHECK-ASM-AND-OBJ: blt $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x62] ++blt $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: blt $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x61] ++blt $r10, $r7, 0x1FFFC ++ ++# CHECK-ASM-AND-OBJ: bge $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x66] ++bge $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: bge $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x65] ++bge $r10, $r7, 0x1FFFC ++ ++# CHECK-ASM-AND-OBJ: bltu $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x6a] ++bltu $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: bltu $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x69] ++bltu $r10, $r7, 0x1FFFC ++ ++# CHECK-ASM-AND-OBJ: bgeu $r10, $r7, -131072 ++# CHECK-ASM: encoding: [0x47,0x01,0x00,0x6e] ++bgeu $r10, $r7, -0x20000 ++ ++# CHECK-ASM-AND-OBJ: bgeu $r10, $r7, 131068 ++# CHECK-ASM: encoding: [0x47,0xfd,0xff,0x6d] ++bgeu $r10, $r7, 0x1FFFC ++ ++### simm21 << 2 ++# CHECK-ASM-AND-OBJ: beqz $r9, -4194304 ++# CHECK-ASM: encoding: [0x30,0x01,0x00,0x40] ++beqz $r9, -0x400000 ++ ++# CHECK-ASM-AND-OBJ: beqz $r9, 4194300 ++# CHECK-ASM: encoding: [0x2f,0xfd,0xff,0x43] ++beqz $r9, 0x3FFFFC ++ ++# CHECK-ASM-AND-OBJ: bnez $r9, -4194304 ++# CHECK-ASM: encoding: [0x30,0x01,0x00,0x44] ++bnez $r9, -0x400000 ++ ++# CHECK-ASM-AND-OBJ: bnez $r9, 4194300 ++# CHECK-ASM: encoding: [0x2f,0xfd,0xff,0x47] ++bnez $r9, 0x3FFFFC ++ ++# CHECK-ASM-AND-OBJ: bceqz $fcc6, -4194304 ++# CHECK-ASM: encoding: [0xd0,0x00,0x00,0x48] ++bceqz $fcc6, -0x400000 ++ ++# CHECK-ASM-AND-OBJ: bceqz $fcc6, 4194300 ++# CHECK-ASM: encoding: [0xcf,0xfc,0xff,0x4b] ++bceqz $fcc6, 0x3FFFFC ++ ++# CHECK-ASM-AND-OBJ: bcnez $fcc6, -4194304 ++# CHECK-ASM: encoding: [0xd0,0x01,0x00,0x48] ++bcnez $fcc6, -0x400000 ++ ++# CHECK-ASM-AND-OBJ: bcnez $fcc6, 4194300 ++# CHECK-ASM: encoding: [0xcf,0xfd,0xff,0x4b] ++bcnez $fcc6, 0x3FFFFC ++ ++### simm26 << 2 ++# CHECK-ASM-AND-OBJ: b -134217728 ++# CHECK-ASM: encoding: [0x00,0x02,0x00,0x50] ++b -0x8000000 ++ ++# CHECK-ASM-AND-OBJ: b 134217724 ++# CHECK-ASM: encoding: [0xff,0xfd,0xff,0x53] ++b 0x7FFFFFC ++ ++# CHECK-ASM-AND-OBJ: bl -134217728 ++# CHECK-ASM: encoding: [0x00,0x02,0x00,0x54] ++bl -0x8000000 ++ ++# CHECK-ASM-AND-OBJ: bl 134217724 ++# CHECK-ASM: encoding: [0xff,0xfd,0xff,0x57] ++bl 0x7FFFFFC ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s +new file mode 100644 +index 000000000..05ecefdc1 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_float.s +@@ -0,0 +1,297 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: fadd.s $f29, $f15, $f25 ++# CHECK: encoding: [0xfd,0xe5,0x00,0x01] ++fadd.s $f29, $f15, $f25 ++ ++# CHECK: fadd.d $f25, $f7, $f13 ++# CHECK: encoding: [0xf9,0x34,0x01,0x01] ++fadd.d $f25, $f7, $f13 ++ ++# CHECK: fsub.s $f14, $f6, $f31 ++# CHECK: encoding: [0xce,0xfc,0x02,0x01] ++fsub.s $f14, $f6, $f31 ++ ++# CHECK: fsub.d $f29, $f1, $f18 ++# CHECK: encoding: [0x3d,0x48,0x03,0x01] ++fsub.d $f29, $f1, $f18 ++ ++# CHECK: fmul.s $f0, $f7, $f17 ++# CHECK: encoding: [0xe0,0xc4,0x04,0x01] ++fmul.s $f0, $f7, $f17 ++ ++# CHECK: fmul.d $f4, $f30, $f7 ++# CHECK: encoding: [0xc4,0x1f,0x05,0x01] ++fmul.d $f4, $f30, $f7 ++ ++# CHECK: fdiv.s $f20, $f24, $f19 ++# CHECK: encoding: [0x14,0xcf,0x06,0x01] ++fdiv.s $f20, $f24, $f19 ++ ++# CHECK: fdiv.d $f3, $f25, $f28 ++# CHECK: encoding: [0x23,0x73,0x07,0x01] ++fdiv.d $f3, $f25, $f28 ++ ++# CHECK: fmax.s $f22, $f6, $f27 ++# CHECK: encoding: [0xd6,0xec,0x08,0x01] ++fmax.s $f22, $f6, $f27 ++ ++# CHECK: fmax.d $f11, $f26, $f13 ++# CHECK: encoding: [0x4b,0x37,0x09,0x01] ++fmax.d $f11, $f26, $f13 ++ ++# CHECK: fmin.s $f14, $f10, $f19 ++# CHECK: encoding: [0x4e,0xcd,0x0a,0x01] ++fmin.s $f14, $f10, $f19 ++ ++# CHECK: fmin.d $f1, $f13, $f27 ++# CHECK: encoding: [0xa1,0x6d,0x0b,0x01] ++fmin.d $f1, $f13, $f27 ++ ++# CHECK: fmaxa.s $f9, $f27, $f31 ++# CHECK: encoding: [0x69,0xff,0x0c,0x01] ++fmaxa.s $f9, $f27, $f31 ++ ++# CHECK: fmaxa.d $f24, $f13, $f4 ++# CHECK: encoding: [0xb8,0x11,0x0d,0x01] ++fmaxa.d $f24, $f13, $f4 ++ ++# CHECK: fmina.s $f15, $f18, $f1 ++# CHECK: encoding: [0x4f,0x86,0x0e,0x01] ++fmina.s $f15, $f18, $f1 ++ ++# CHECK: fmina.d $f18, $f10, $f0 ++# CHECK: encoding: [0x52,0x01,0x0f,0x01] ++fmina.d $f18, $f10, $f0 ++ ++# CHECK: fscaleb.s $f21, $f23, $f6 ++# CHECK: encoding: [0xf5,0x9a,0x10,0x01] ++fscaleb.s $f21, $f23, $f6 ++ ++# CHECK: fscaleb.d $f12, $f14, $f26 ++# CHECK: encoding: [0xcc,0x69,0x11,0x01] ++fscaleb.d $f12, $f14, $f26 ++ ++# CHECK: fcopysign.s $f13, $f24, $f23 ++# CHECK: encoding: [0x0d,0xdf,0x12,0x01] ++fcopysign.s $f13, $f24, $f23 ++ ++# CHECK: fcopysign.d $f16, $f26, $f6 ++# CHECK: encoding: [0x50,0x1b,0x13,0x01] ++fcopysign.d $f16, $f26, $f6 ++ ++# CHECK: fabs.s $f28, $f12 ++# CHECK: encoding: [0x9c,0x05,0x14,0x01] ++fabs.s $f28, $f12 ++ ++# CHECK: fabs.d $f23, $f3 ++# CHECK: encoding: [0x77,0x08,0x14,0x01] ++fabs.d $f23, $f3 ++ ++# CHECK: fneg.s $f21, $f24 ++# CHECK: encoding: [0x15,0x17,0x14,0x01] ++fneg.s $f21, $f24 ++ ++# CHECK: fneg.d $f11, $f26 ++# CHECK: encoding: [0x4b,0x1b,0x14,0x01] ++fneg.d $f11, $f26 ++ ++# CHECK: flogb.s $f31, $f23 ++# CHECK: encoding: [0xff,0x26,0x14,0x01] ++flogb.s $f31, $f23 ++ ++# CHECK: flogb.d $f21, $f29 ++# CHECK: encoding: [0xb5,0x2b,0x14,0x01] ++flogb.d $f21, $f29 ++ ++# CHECK: fclass.s $f20, $f9 ++# CHECK: encoding: [0x34,0x35,0x14,0x01] ++fclass.s $f20, $f9 ++ ++# CHECK: fclass.d $f19, $f2 ++# CHECK: encoding: [0x53,0x38,0x14,0x01] ++fclass.d $f19, $f2 ++ ++# CHECK: fsqrt.s $f27, $f18 ++# CHECK: encoding: [0x5b,0x46,0x14,0x01] ++fsqrt.s $f27, $f18 ++ ++# CHECK: fsqrt.d $f2, $f11 ++# CHECK: encoding: [0x62,0x49,0x14,0x01] ++fsqrt.d $f2, $f11 ++ ++# CHECK: frecip.s $f17, $f27 ++# CHECK: encoding: [0x71,0x57,0x14,0x01] ++frecip.s $f17, $f27 ++ ++# CHECK: frecip.d $f27, $f27 ++# CHECK: encoding: [0x7b,0x5b,0x14,0x01] ++frecip.d $f27, $f27 ++ ++# CHECK: frsqrt.s $f25, $f12 ++# CHECK: encoding: [0x99,0x65,0x14,0x01] ++frsqrt.s $f25, $f12 ++ ++# CHECK: frsqrt.d $f22, $f3 ++# CHECK: encoding: [0x76,0x68,0x14,0x01] ++frsqrt.d $f22, $f3 ++ ++# CHECK: fmov.s $f13, $f23 ++# CHECK: encoding: [0xed,0x96,0x14,0x01] ++fmov.s $f13, $f23 ++ ++# CHECK: fmov.d $f30, $f9 ++# CHECK: encoding: [0x3e,0x99,0x14,0x01] ++fmov.d $f30, $f9 ++ ++# CHECK: movgr2fr.w $f6, $tp ++# CHECK: encoding: [0x46,0xa4,0x14,0x01] ++movgr2fr.w $f6, $tp ++ ++# CHECK: movgr2fr.d $f30, $r11 ++# CHECK: encoding: [0x7e,0xa9,0x14,0x01] ++movgr2fr.d $f30, $r11 ++ ++# CHECK: movgr2frh.w $f23, $r26 ++# CHECK: encoding: [0x57,0xaf,0x14,0x01] ++movgr2frh.w $f23, $r26 ++ ++# CHECK: movfr2gr.s $r10, $f22 ++# CHECK: encoding: [0xca,0xb6,0x14,0x01] ++movfr2gr.s $r10, $f22 ++ ++# CHECK: movfr2gr.d $r26, $f17 ++# CHECK: encoding: [0x3a,0xba,0x14,0x01] ++movfr2gr.d $r26, $f17 ++ ++# CHECK: movfrh2gr.s $sp, $f26 ++# CHECK: encoding: [0x43,0xbf,0x14,0x01] ++movfrh2gr.s $sp, $f26 ++ ++# CHECK: movfr2cf $fcc4, $f11 ++# CHECK: encoding: [0x64,0xd1,0x14,0x01] ++movfr2cf $fcc4, $f11 ++ ++# CHECK: movcf2fr $f16, $fcc0 ++# CHECK: encoding: [0x10,0xd4,0x14,0x01] ++movcf2fr $f16, $fcc0 ++ ++# CHECK: movgr2cf $fcc5, $ra ++# CHECK: encoding: [0x25,0xd8,0x14,0x01] ++movgr2cf $fcc5, $ra ++ ++# CHECK: movcf2gr $r21, $fcc7 ++# CHECK: encoding: [0xf5,0xdc,0x14,0x01] ++movcf2gr $r21, $fcc7 ++ ++# CHECK: fcvt.s.d $f12, $f19 ++# CHECK: encoding: [0x6c,0x1a,0x19,0x01] ++fcvt.s.d $f12, $f19 ++ ++# CHECK: fcvt.d.s $f10, $f6 ++# CHECK: encoding: [0xca,0x24,0x19,0x01] ++fcvt.d.s $f10, $f6 ++ ++# CHECK: ftintrm.w.s $f16, $f16 ++# CHECK: encoding: [0x10,0x06,0x1a,0x01] ++ftintrm.w.s $f16, $f16 ++ ++# CHECK: ftintrm.w.d $f7, $f8 ++# CHECK: encoding: [0x07,0x09,0x1a,0x01] ++ftintrm.w.d $f7, $f8 ++ ++# CHECK: ftintrm.l.s $f24, $f10 ++# CHECK: encoding: [0x58,0x25,0x1a,0x01] ++ftintrm.l.s $f24, $f10 ++ ++# CHECK: ftintrm.l.d $f9, $f9 ++# CHECK: encoding: [0x29,0x29,0x1a,0x01] ++ftintrm.l.d $f9, $f9 ++ ++# CHECK: ftintrp.w.s $f14, $f31 ++# CHECK: encoding: [0xee,0x47,0x1a,0x01] ++ftintrp.w.s $f14, $f31 ++ ++# CHECK: ftintrp.w.d $f12, $f3 ++# CHECK: encoding: [0x6c,0x48,0x1a,0x01] ++ftintrp.w.d $f12, $f3 ++ ++# CHECK: ftintrp.l.s $f0, $f16 ++# CHECK: encoding: [0x00,0x66,0x1a,0x01] ++ftintrp.l.s $f0, $f16 ++ ++# CHECK: ftintrp.l.d $f4, $f29 ++# CHECK: encoding: [0xa4,0x6b,0x1a,0x01] ++ftintrp.l.d $f4, $f29 ++ ++# CHECK: ftintrz.w.s $f4, $f29 ++# CHECK: encoding: [0xa4,0x87,0x1a,0x01] ++ftintrz.w.s $f4, $f29 ++ ++# CHECK: ftintrz.w.d $f25, $f24 ++# CHECK: encoding: [0x19,0x8b,0x1a,0x01] ++ftintrz.w.d $f25, $f24 ++ ++# CHECK: ftintrz.l.s $f23, $f5 ++# CHECK: encoding: [0xb7,0xa4,0x1a,0x01] ++ftintrz.l.s $f23, $f5 ++ ++# CHECK: ftintrz.l.d $f3, $f10 ++# CHECK: encoding: [0x43,0xa9,0x1a,0x01] ++ftintrz.l.d $f3, $f10 ++ ++# CHECK: ftintrne.w.s $f4, $f17 ++# CHECK: encoding: [0x24,0xc6,0x1a,0x01] ++ftintrne.w.s $f4, $f17 ++ ++# CHECK: ftintrne.w.d $f31, $f12 ++# CHECK: encoding: [0x9f,0xc9,0x1a,0x01] ++ftintrne.w.d $f31, $f12 ++ ++# CHECK: ftintrne.l.s $f22, $f27 ++# CHECK: encoding: [0x76,0xe7,0x1a,0x01] ++ftintrne.l.s $f22, $f27 ++ ++# CHECK: ftintrne.l.d $f28, $f6 ++# CHECK: encoding: [0xdc,0xe8,0x1a,0x01] ++ftintrne.l.d $f28, $f6 ++ ++# CHECK: ftint.w.s $f21, $f13 ++# CHECK: encoding: [0xb5,0x05,0x1b,0x01] ++ftint.w.s $f21, $f13 ++ ++# CHECK: ftint.w.d $f3, $f14 ++# CHECK: encoding: [0xc3,0x09,0x1b,0x01] ++ftint.w.d $f3, $f14 ++ ++# CHECK: ftint.l.s $f31, $f24 ++# CHECK: encoding: [0x1f,0x27,0x1b,0x01] ++ftint.l.s $f31, $f24 ++ ++# CHECK: ftint.l.d $f16, $f24 ++# CHECK: encoding: [0x10,0x2b,0x1b,0x01] ++ftint.l.d $f16, $f24 ++ ++# CHECK: ffint.s.w $f30, $f5 ++# CHECK: encoding: [0xbe,0x10,0x1d,0x01] ++ffint.s.w $f30, $f5 ++ ++# CHECK: ffint.s.l $f6, $f5 ++# CHECK: encoding: [0xa6,0x18,0x1d,0x01] ++ffint.s.l $f6, $f5 ++ ++# CHECK: ffint.d.w $f24, $f18 ++# CHECK: encoding: [0x58,0x22,0x1d,0x01] ++ffint.d.w $f24, $f18 ++ ++# CHECK: ffint.d.l $f23, $f26 ++# CHECK: encoding: [0x57,0x2b,0x1d,0x01] ++ffint.d.l $f23, $f26 ++ ++# CHECK: frint.s $f5, $f17 ++# CHECK: encoding: [0x25,0x46,0x1e,0x01] ++frint.s $f5, $f17 ++ ++# CHECK: frint.d $f29, $f2 ++# CHECK: encoding: [0x5d,0x48,0x1e,0x01] ++frint.d $f29, $f2 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s +new file mode 100644 +index 000000000..cc78662d5 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_integer.s +@@ -0,0 +1,369 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: clo.w $ra, $sp ++# CHECK: encoding: [0x61,0x10,0x00,0x00] ++clo.w $ra, $sp ++ ++# CHECK: clz.w $r7, $r10 ++# CHECK: encoding: [0x47,0x15,0x00,0x00] ++clz.w $r7, $r10 ++ ++# CHECK: cto.w $tp, $r6 ++# CHECK: encoding: [0xc2,0x18,0x00,0x00] ++cto.w $tp, $r6 ++ ++# CHECK: ctz.w $r5, $r22 ++# CHECK: encoding: [0xc5,0x1e,0x00,0x00] ++ctz.w $r5, $r22 ++ ++# CHECK: clo.d $r29, $ra ++# CHECK: encoding: [0x3d,0x20,0x00,0x00] ++clo.d $r29, $ra ++ ++# CHECK: clz.d $r26, $r26 ++# CHECK: encoding: [0x5a,0x27,0x00,0x00] ++clz.d $r26, $r26 ++ ++# CHECK: cto.d $r18, $r20 ++# CHECK: encoding: [0x92,0x2a,0x00,0x00] ++cto.d $r18, $r20 ++ ++# CHECK: ctz.d $r17, $r10 ++# CHECK: encoding: [0x51,0x2d,0x00,0x00] ++ctz.d $r17, $r10 ++ ++# CHECK: revb.2h $r20, $r11 ++# CHECK: encoding: [0x74,0x31,0x00,0x00] ++revb.2h $r20, $r11 ++ ++# CHECK: revb.4h $r13, $r19 ++# CHECK: encoding: [0x6d,0x36,0x00,0x00] ++revb.4h $r13, $r19 ++ ++# CHECK: revb.2w $r28, $r27 ++# CHECK: encoding: [0x7c,0x3b,0x00,0x00] ++revb.2w $r28, $r27 ++ ++# CHECK: revb.d $zero, $r23 ++# CHECK: encoding: [0xe0,0x3e,0x00,0x00] ++revb.d $zero, $r23 ++ ++# CHECK: revh.2w $r28, $r10 ++# CHECK: encoding: [0x5c,0x41,0x00,0x00] ++revh.2w $r28, $r10 ++ ++# CHECK: revh.d $r9, $r7 ++# CHECK: encoding: [0xe9,0x44,0x00,0x00] ++revh.d $r9, $r7 ++ ++# CHECK: bitrev.4b $r21, $r27 ++# CHECK: encoding: [0x75,0x4b,0x00,0x00] ++bitrev.4b $r21, $r27 ++ ++# CHECK: bitrev.8b $r13, $r25 ++# CHECK: encoding: [0x2d,0x4f,0x00,0x00] ++bitrev.8b $r13, $r25 ++ ++# CHECK: bitrev.w $r25, $r5 ++# CHECK: encoding: [0xb9,0x50,0x00,0x00] ++bitrev.w $r25, $r5 ++ ++# CHECK: bitrev.d $r19, $r23 ++# CHECK: encoding: [0xf3,0x56,0x00,0x00] ++bitrev.d $r19, $r23 ++ ++# CHECK: ext.w.h $r23, $r23 ++# CHECK: encoding: [0xf7,0x5a,0x00,0x00] ++ext.w.h $r23, $r23 ++ ++# CHECK: ext.w.b $r20, $r18 ++# CHECK: encoding: [0x54,0x5e,0x00,0x00] ++ext.w.b $r20, $r18 ++ ++# CHECK: rdtimel.w $r24, $r4 ++# CHECK: encoding: [0x98,0x60,0x00,0x00] ++rdtimel.w $r24, $r4 ++ ++# CHECK: rdtimeh.w $r11, $r5 ++# CHECK: encoding: [0xab,0x64,0x00,0x00] ++rdtimeh.w $r11, $r5 ++ ++# CHECK: rdtime.d $tp, $ra ++# CHECK: encoding: [0x22,0x68,0x00,0x00] ++rdtime.d $tp, $ra ++ ++# CHECK: cpucfg $sp, $ra ++# CHECK: encoding: [0x23,0x6c,0x00,0x00] ++cpucfg $sp, $ra ++ ++# CHECK: asrtle.d $r21, $r19 ++# CHECK: encoding: [0xa0,0x4e,0x01,0x00] ++asrtle.d $r21, $r19 ++ ++# CHECK: asrtgt.d $ra, $r19 ++# CHECK: encoding: [0x20,0xcc,0x01,0x00] ++asrtgt.d $ra, $r19 ++ ++# CHECK: alsl.w $tp, $r17, $tp, 4 ++# CHECK: encoding: [0x22,0x8a,0x05,0x00] ++alsl.w $tp, $r17, $tp, 4 ++ ++# CHECK: bytepick.w $r29, $zero, $r16, 0 ++# CHECK: encoding: [0x1d,0x40,0x08,0x00] ++bytepick.w $r29, $zero, $r16, 0 ++ ++# CHECK: bytepick.d $r15, $r17, $r20, 4 ++# CHECK: encoding: [0x2f,0x52,0x0e,0x00] ++bytepick.d $r15, $r17, $r20, 4 ++ ++# CHECK: add.w $r9, $ra, $r31 ++# CHECK: encoding: [0x29,0x7c,0x10,0x00] ++add.w $r9, $ra, $r31 ++ ++# CHECK: add.d $tp, $r18, $r27 ++# CHECK: encoding: [0x42,0xee,0x10,0x00] ++add.d $tp, $r18, $r27 ++ ++# CHECK: sub.w $r21, $r25, $r19 ++# CHECK: encoding: [0x35,0x4f,0x11,0x00] ++sub.w $r21, $r25, $r19 ++ ++# CHECK: sub.d $r7, $r12, $r7 ++# CHECK: encoding: [0x87,0x9d,0x11,0x00] ++sub.d $r7, $r12, $r7 ++ ++# CHECK: slt $r29, $r26, $tp ++# CHECK: encoding: [0x5d,0x0b,0x12,0x00] ++slt $r29, $r26, $tp ++ ++# CHECK: sltu $r11, $r21, $r29 ++# CHECK: encoding: [0xab,0xf6,0x12,0x00] ++sltu $r11, $r21, $r29 ++ ++# CHECK: maskeqz $r20, $r11, $r18 ++# CHECK: encoding: [0x74,0x49,0x13,0x00] ++maskeqz $r20, $r11, $r18 ++ ++# CHECK: masknez $r20, $r13, $r26 ++# CHECK: encoding: [0xb4,0xe9,0x13,0x00] ++masknez $r20, $r13, $r26 ++ ++# CHECK: nor $r5, $r18, $r5 ++# CHECK: encoding: [0x45,0x16,0x14,0x00] ++nor $r5, $r18, $r5 ++ ++# CHECK: and $r19, $r31, $ra ++# CHECK: encoding: [0xf3,0x87,0x14,0x00] ++and $r19, $r31, $ra ++ ++# CHECK: or $r17, $r16, $r30 ++# CHECK: encoding: [0x11,0x7a,0x15,0x00] ++or $r17, $r16, $r30 ++ ++# CHECK: xor $r15, $r19, $r8 ++# CHECK: encoding: [0x6f,0xa2,0x15,0x00] ++xor $r15, $r19, $r8 ++ ++# CHECK: orn $tp, $sp, $r25 ++# CHECK: encoding: [0x62,0x64,0x16,0x00] ++orn $tp, $sp, $r25 ++ ++# CHECK: andn $r28, $r25, $r5 ++# CHECK: encoding: [0x3c,0x97,0x16,0x00] ++andn $r28, $r25, $r5 ++ ++# CHECK: sll.w $r24, $r27, $r23 ++# CHECK: encoding: [0x78,0x5f,0x17,0x00] ++sll.w $r24, $r27, $r23 ++ ++# CHECK: srl.w $r31, $r17, $r7 ++# CHECK: encoding: [0x3f,0x9e,0x17,0x00] ++srl.w $r31, $r17, $r7 ++ ++# CHECK: sra.w $r12, $r28, $r10 ++# CHECK: encoding: [0x8c,0x2b,0x18,0x00] ++sra.w $r12, $r28, $r10 ++ ++# CHECK: sll.d $r20, $r15, $sp ++# CHECK: encoding: [0xf4,0x8d,0x18,0x00] ++sll.d $r20, $r15, $sp ++ ++# CHECK: srl.d $r14, $r25, $zero ++# CHECK: encoding: [0x2e,0x03,0x19,0x00] ++srl.d $r14, $r25, $zero ++ ++# CHECK: sra.d $r7, $r22, $r31 ++# CHECK: encoding: [0xc7,0xfe,0x19,0x00] ++sra.d $r7, $r22, $r31 ++ ++# CHECK: rotr.w $ra, $r26, $r18 ++# CHECK: encoding: [0x41,0x4b,0x1b,0x00] ++rotr.w $ra, $r26, $r18 ++ ++# CHECK: rotr.d $r31, $sp, $ra ++# CHECK: encoding: [0x7f,0x84,0x1b,0x00] ++rotr.d $r31, $sp, $ra ++ ++# CHECK: mul.w $r4, $r18, $sp ++# CHECK: encoding: [0x44,0x0e,0x1c,0x00] ++mul.w $r4, $r18, $sp ++ ++# CHECK: mulh.w $r27, $r23, $zero ++# CHECK: encoding: [0xfb,0x82,0x1c,0x00] ++mulh.w $r27, $r23, $zero ++ ++# CHECK: mulh.wu $r10, $r17, $r24 ++# CHECK: encoding: [0x2a,0x62,0x1d,0x00] ++mulh.wu $r10, $r17, $r24 ++ ++# CHECK: mul.d $ra, $r14, $r24 ++# CHECK: encoding: [0xc1,0xe1,0x1d,0x00] ++mul.d $ra, $r14, $r24 ++ ++# CHECK: mulh.d $r28, $ra, $r27 ++# CHECK: encoding: [0x3c,0x6c,0x1e,0x00] ++mulh.d $r28, $ra, $r27 ++ ++# CHECK: mulh.du $r13, $r27, $r29 ++# CHECK: encoding: [0x6d,0xf7,0x1e,0x00] ++mulh.du $r13, $r27, $r29 ++ ++# CHECK: mulw.d.w $r27, $r6, $r17 ++# CHECK: encoding: [0xdb,0x44,0x1f,0x00] ++mulw.d.w $r27, $r6, $r17 ++ ++# CHECK: mulw.d.wu $r17, $r22, $r30 ++# CHECK: encoding: [0xd1,0xfa,0x1f,0x00] ++mulw.d.wu $r17, $r22, $r30 ++ ++# CHECK: div.w $r30, $r13, $r25 ++# CHECK: encoding: [0xbe,0x65,0x20,0x00] ++div.w $r30, $r13, $r25 ++ ++# CHECK: mod.w $ra, $r26, $r10 ++# CHECK: encoding: [0x41,0xab,0x20,0x00] ++mod.w $ra, $r26, $r10 ++ ++# CHECK: div.wu $r19, $r23, $zero ++# CHECK: encoding: [0xf3,0x02,0x21,0x00] ++div.wu $r19, $r23, $zero ++ ++# CHECK: mod.wu $r27, $r9, $r17 ++# CHECK: encoding: [0x3b,0xc5,0x21,0x00] ++mod.wu $r27, $r9, $r17 ++ ++# CHECK: div.d $r23, $r6, $r21 ++# CHECK: encoding: [0xd7,0x54,0x22,0x00] ++div.d $r23, $r6, $r21 ++ ++# CHECK: mod.d $r16, $sp, $r15 ++# CHECK: encoding: [0x70,0xbc,0x22,0x00] ++mod.d $r16, $sp, $r15 ++ ++# CHECK: div.du $r31, $r24, $r14 ++# CHECK: encoding: [0x1f,0x3b,0x23,0x00] ++div.du $r31, $r24, $r14 ++ ++# CHECK: mod.du $r25, $r23, $r24 ++# CHECK: encoding: [0xf9,0xe2,0x23,0x00] ++mod.du $r25, $r23, $r24 ++ ++# CHECK: crc.w.b.w $r24, $r7, $tp ++# CHECK: encoding: [0xf8,0x08,0x24,0x00] ++crc.w.b.w $r24, $r7, $tp ++ ++# CHECK: crc.w.h.w $r31, $r10, $r18 ++# CHECK: encoding: [0x5f,0xc9,0x24,0x00] ++crc.w.h.w $r31, $r10, $r18 ++ ++# CHECK: crc.w.w.w $r28, $r6, $r10 ++# CHECK: encoding: [0xdc,0x28,0x25,0x00] ++crc.w.w.w $r28, $r6, $r10 ++ ++# CHECK: crc.w.d.w $r28, $r11, $r31 ++# CHECK: encoding: [0x7c,0xfd,0x25,0x00] ++crc.w.d.w $r28, $r11, $r31 ++ ++# CHECK: crcc.w.b.w $r15, $r18, $sp ++# CHECK: encoding: [0x4f,0x0e,0x26,0x00] ++crcc.w.b.w $r15, $r18, $sp ++ ++# CHECK: crcc.w.h.w $r21, $r29, $r18 ++# CHECK: encoding: [0xb5,0xcb,0x26,0x00] ++crcc.w.h.w $r21, $r29, $r18 ++ ++# CHECK: crcc.w.w.w $r17, $r14, $r13 ++# CHECK: encoding: [0xd1,0x35,0x27,0x00] ++crcc.w.w.w $r17, $r14, $r13 ++ ++# CHECK: crcc.w.d.w $r30, $r21, $r27 ++# CHECK: encoding: [0xbe,0xee,0x27,0x00] ++crcc.w.d.w $r30, $r21, $r27 ++ ++# CHECK: break 23 ++# CHECK: encoding: [0x17,0x00,0x2a,0x00] ++break 23 ++ ++# CHECK: syscall 2 ++# CHECK: encoding: [0x02,0x00,0x2b,0x00] ++syscall 2 ++ ++# CHECK: alsl.d $r17, $r11, $r5, 3 ++# CHECK: encoding: [0x71,0x15,0x2d,0x00] ++alsl.d $r17, $r11, $r5, 3 ++ ++# CHECK: slli.w $r26, $r18, 0 ++# CHECK: encoding: [0x5a,0x82,0x40,0x00] ++slli.w $r26, $r18, 0 ++ ++# CHECK: slli.d $r10, $r31, 39 ++# CHECK: encoding: [0xea,0x9f,0x41,0x00] ++slli.d $r10, $r31, 39 ++ ++# CHECK: srli.w $r10, $r14, 30 ++# CHECK: encoding: [0xca,0xf9,0x44,0x00] ++srli.w $r10, $r14, 30 ++ ++# CHECK: srli.d $r31, $r22, 38 ++# CHECK: encoding: [0xdf,0x9a,0x45,0x00] ++srli.d $r31, $r22, 38 ++ ++# CHECK: srai.w $r8, $r17, 24 ++# CHECK: encoding: [0x28,0xe2,0x48,0x00] ++srai.w $r8, $r17, 24 ++ ++# CHECK: srai.d $r9, $r21, 27 ++# CHECK: encoding: [0xa9,0x6e,0x49,0x00] ++srai.d $r9, $r21, 27 ++ ++# CHECK: rotri.w $r23, $r20, 23 ++# CHECK: encoding: [0x97,0xde,0x4c,0x00] ++rotri.w $r23, $r20, 23 ++ ++# CHECK: rotri.d $r29, $zero, 7 ++# CHECK: encoding: [0x1d,0x1c,0x4d,0x00] ++rotri.d $r29, $zero, 7 ++ ++# CHECK: bstrins.w $r8, $r11, 7, 2 ++# CHECK: encoding: [0x68,0x09,0x67,0x00] ++bstrins.w $r8, $r11, 7, 2 ++ ++# CHECK: bstrins.d $r8, $r11, 7, 2 ++# CHECK: encoding: [0x68,0x09,0x87,0x00] ++bstrins.d $r8, $r11, 7, 2 ++ ++# CHECK: bstrpick.w $ra, $r9, 10, 4 ++# CHECK: encoding: [0x21,0x91,0x6a,0x00] ++bstrpick.w $ra, $r9, 10, 4 ++ ++# CHECK: bstrpick.d $r31, $r27, 39, 22 ++# CHECK: encoding: [0x7f,0x5b,0xe7,0x00] ++bstrpick.d $r31, $r27, 39, 22 ++ ++# CHECK: cpucfg $sp, $r8 ++# CHECK: encoding: [0x03,0x6d,0x00,0x00] ++cpucfg $sp, $r8 ++ ++# CHECK: alsl.wu $r19, $r8, $r25, 1 ++# CHECK: encoding: [0x13,0x65,0x06,0x00] ++alsl.wu $r19, $r8, $r25, 1 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s +new file mode 100644 +index 000000000..30ea88c99 +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_memory.s +@@ -0,0 +1,405 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: dbar 0 ++# CHECK: encoding: [0x00,0x00,0x72,0x38] ++dbar 0 ++ ++# CHECK: ibar 0 ++# CHECK: encoding: [0x00,0x80,0x72,0x38] ++ibar 0 ++ ++# CHECK: ll.w $tp, $r27, 220 ++# CHECK: encoding: [0x62,0xdf,0x00,0x20] ++ll.w $tp, $r27, 220 ++ ++# CHECK: sc.w $r19, $r14, 56 ++# CHECK: encoding: [0xd3,0x39,0x00,0x21] ++sc.w $r19, $r14, 56 ++ ++# CHECK: ll.d $r25, $r27, 16 ++# CHECK: encoding: [0x79,0x13,0x00,0x22] ++ll.d $r25, $r27, 16 ++ ++# CHECK: sc.d $r17, $r17, 244 ++# CHECK: encoding: [0x31,0xf6,0x00,0x23] ++sc.d $r17, $r17, 244 ++ ++# CHECK: ldptr.w $r26, $r6, 60 ++# CHECK: encoding: [0xda,0x3c,0x00,0x24] ++ldptr.w $r26, $r6, 60 ++ ++# CHECK: stptr.w $r28, $r5, 216 ++# CHECK: encoding: [0xbc,0xd8,0x00,0x25] ++stptr.w $r28, $r5, 216 ++ ++# CHECK: ldptr.d $r5, $r29, 244 ++# CHECK: encoding: [0xa5,0xf7,0x00,0x26] ++ldptr.d $r5, $r29, 244 ++ ++# CHECK: stptr.d $r14, $r24, 196 ++# CHECK: encoding: [0x0e,0xc7,0x00,0x27] ++stptr.d $r14, $r24, 196 ++ ++# CHECK: ld.b $r24, $r8, 21 ++# CHECK: encoding: [0x18,0x55,0x00,0x28] ++ld.b $r24, $r8, 21 ++ ++# CHECK: ld.h $r7, $r18, 80 ++# CHECK: encoding: [0x47,0x42,0x41,0x28] ++ld.h $r7, $r18, 80 ++ ++# CHECK: ld.w $r18, $r26, 92 ++# CHECK: encoding: [0x52,0x73,0x81,0x28] ++ld.w $r18, $r26, 92 ++ ++# CHECK: ld.d $r18, $r20, 159 ++# CHECK: encoding: [0x92,0x7e,0xc2,0x28] ++ld.d $r18, $r20, 159 ++ ++# CHECK: st.b $sp, $r7, 95 ++# CHECK: encoding: [0xe3,0x7c,0x01,0x29] ++st.b $sp, $r7, 95 ++ ++# CHECK: st.h $r25, $r16, 122 ++# CHECK: encoding: [0x19,0xea,0x41,0x29] ++st.h $r25, $r16, 122 ++ ++# CHECK: st.w $r13, $r13, 175 ++# CHECK: encoding: [0xad,0xbd,0x82,0x29] ++st.w $r13, $r13, 175 ++ ++# CHECK: st.d $r30, $r30, 60 ++# CHECK: encoding: [0xde,0xf3,0xc0,0x29] ++st.d $r30, $r30, 60 ++ ++# CHECK: ld.bu $r13, $r13, 150 ++# CHECK: encoding: [0xad,0x59,0x02,0x2a] ++ld.bu $r13, $r13, 150 ++ ++# CHECK: ld.hu $r18, $r29, 198 ++# CHECK: encoding: [0xb2,0x1b,0x43,0x2a] ++ld.hu $r18, $r29, 198 ++ ++# CHECK: ld.wu $r14, $r19, 31 ++# CHECK: encoding: [0x6e,0x7e,0x80,0x2a] ++ld.wu $r14, $r19, 31 ++ ++# CHECK: fld.s $f23, $r15, 250 ++# CHECK: encoding: [0xf7,0xe9,0x03,0x2b] ++fld.s $f23, $r15, 250 ++ ++# CHECK: fst.s $f30, $r19, 230 ++# CHECK: encoding: [0x7e,0x9a,0x43,0x2b] ++fst.s $f30, $r19, 230 ++ ++# CHECK: fld.d $f22, $r17, 114 ++# CHECK: encoding: [0x36,0xca,0x81,0x2b] ++fld.d $f22, $r17, 114 ++ ++# CHECK: fst.d $f28, $r7, 198 ++# CHECK: encoding: [0xfc,0x18,0xc3,0x2b] ++fst.d $f28, $r7, 198 ++ ++# CHECK: ldx.b $r24, $ra, $tp ++# CHECK: encoding: [0x38,0x08,0x00,0x38] ++ldx.b $r24, $ra, $tp ++ ++# CHECK: ldx.h $r22, $r22, $r17 ++# CHECK: encoding: [0xd6,0x46,0x04,0x38] ++ldx.h $r22, $r22, $r17 ++ ++# CHECK: ldx.w $r25, $r11, $r23 ++# CHECK: encoding: [0x79,0x5d,0x08,0x38] ++ldx.w $r25, $r11, $r23 ++ ++# CHECK: ldx.d $r18, $r23, $r20 ++# CHECK: encoding: [0xf2,0x52,0x0c,0x38] ++ldx.d $r18, $r23, $r20 ++ ++# CHECK: stx.b $r19, $ra, $sp ++# CHECK: encoding: [0x33,0x0c,0x10,0x38] ++stx.b $r19, $ra, $sp ++ ++# CHECK: stx.h $zero, $r28, $r26 ++# CHECK: encoding: [0x80,0x6b,0x14,0x38] ++stx.h $zero, $r28, $r26 ++ ++# CHECK: stx.w $r7, $r4, $r31 ++# CHECK: encoding: [0x87,0x7c,0x18,0x38] ++stx.w $r7, $r4, $r31 ++ ++# CHECK: stx.d $r7, $r31, $r10 ++# CHECK: encoding: [0xe7,0x2b,0x1c,0x38] ++stx.d $r7, $r31, $r10 ++ ++# CHECK: ldx.bu $r11, $r9, $r9 ++# CHECK: encoding: [0x2b,0x25,0x20,0x38] ++ldx.bu $r11, $r9, $r9 ++ ++# CHECK: ldx.hu $r22, $r23, $r27 ++# CHECK: encoding: [0xf6,0x6e,0x24,0x38] ++ldx.hu $r22, $r23, $r27 ++ ++# CHECK: ldx.wu $r8, $r24, $r28 ++# CHECK: encoding: [0x08,0x73,0x28,0x38] ++ldx.wu $r8, $r24, $r28 ++ ++# CHECK: fldx.s $f1, $r15, $r19 ++# CHECK: encoding: [0xe1,0x4d,0x30,0x38] ++fldx.s $f1, $r15, $r19 ++ ++# CHECK: fldx.d $f27, $r13, $r31 ++# CHECK: encoding: [0xbb,0x7d,0x34,0x38] ++fldx.d $f27, $r13, $r31 ++ ++# CHECK: fstx.s $f26, $sp, $r22 ++# CHECK: encoding: [0x7a,0x58,0x38,0x38] ++fstx.s $f26, $sp, $r22 ++ ++# CHECK: fstx.d $f6, $r15, $r17 ++# CHECK: encoding: [0xe6,0x45,0x3c,0x38] ++fstx.d $f6, $r15, $r17 ++ ++# CHECK: amswap_db.w $r6, $r12, $r24, 0 ++# CHECK: encoding: [0x06,0x33,0x69,0x38] ++amswap_db.w $r6, $r12, $r24, 0 ++ ++# CHECK: amswap_db.d $tp, $r14, $r22, 0 ++# CHECK: encoding: [0xc2,0xba,0x69,0x38] ++amswap_db.d $tp, $r14, $r22, 0 ++ ++# CHECK: amadd_db.w $r8, $r12, $r21, 0 ++# CHECK: encoding: [0xa8,0x32,0x6a,0x38] ++amadd_db.w $r8, $r12, $r21, 0 ++ ++# CHECK: amadd_db.d $r5, $r17, $r29, 0 ++# CHECK: encoding: [0xa5,0xc7,0x6a,0x38] ++amadd_db.d $r5, $r17, $r29, 0 ++ ++# CHECK: amand_db.w $r4, $r19, $r22, 0 ++# CHECK: encoding: [0xc4,0x4e,0x6b,0x38] ++amand_db.w $r4, $r19, $r22, 0 ++ ++# CHECK: amand_db.d $r10, $r18, $r29, 0 ++# CHECK: encoding: [0xaa,0xcb,0x6b,0x38] ++amand_db.d $r10, $r18, $r29, 0 ++ ++# CHECK: amor_db.w $r6, $r16, $r23, 0 ++# CHECK: encoding: [0xe6,0x42,0x6c,0x38] ++amor_db.w $r6, $r16, $r23, 0 ++ ++# CHECK: amor_db.d $sp, $r16, $r24, 0 ++# CHECK: encoding: [0x03,0xc3,0x6c,0x38] ++amor_db.d $sp, $r16, $r24, 0 ++ ++# CHECK: amxor_db.w $tp, $r15, $r23, 0 ++# CHECK: encoding: [0xe2,0x3e,0x6d,0x38] ++amxor_db.w $tp, $r15, $r23, 0 ++ ++# CHECK: amxor_db.d $r8, $r20, $r28, 0 ++# CHECK: encoding: [0x88,0xd3,0x6d,0x38] ++amxor_db.d $r8, $r20, $r28, 0 ++ ++# CHECK: ammax_db.w $ra, $r11, $r23, 0 ++# CHECK: encoding: [0xe1,0x2e,0x6e,0x38] ++ammax_db.w $ra, $r11, $r23, 0 ++ ++# CHECK: ammax_db.d $r9, $r20, $r27, 0 ++# CHECK: encoding: [0x69,0xd3,0x6e,0x38] ++ammax_db.d $r9, $r20, $r27, 0 ++ ++# CHECK: ammin_db.w $r9, $r14, $r23, 0 ++# CHECK: encoding: [0xe9,0x3a,0x6f,0x38] ++ammin_db.w $r9, $r14, $r23, 0 ++ ++# CHECK: ammin_db.d $r9, $r13, $r22, 0 ++# CHECK: encoding: [0xc9,0xb6,0x6f,0x38] ++ammin_db.d $r9, $r13, $r22, 0 ++ ++# CHECK: ammax_db.wu $r9, $r11, $r22, 0 ++# CHECK: encoding: [0xc9,0x2e,0x70,0x38] ++ammax_db.wu $r9, $r11, $r22, 0 ++ ++# CHECK: ammax_db.du $r6, $r16, $r25, 0 ++# CHECK: encoding: [0x26,0xc3,0x70,0x38] ++ammax_db.du $r6, $r16, $r25, 0 ++ ++# CHECK: ammin_db.wu $r8, $r18, $r30, 0 ++# CHECK: encoding: [0xc8,0x4b,0x71,0x38] ++ammin_db.wu $r8, $r18, $r30, 0 ++ ++# CHECK: ammin_db.du $r7, $r16, $r25, 0 ++# CHECK: encoding: [0x27,0xc3,0x71,0x38] ++ammin_db.du $r7, $r16, $r25, 0 ++ ++# CHECK: amswap.w $r6, $r12, $r24, 0 ++# CHECK: encoding: [0x06,0x33,0x60,0x38] ++amswap.w $r6, $r12, $r24, 0 ++ ++# CHECK: amswap.d $tp, $r14, $r22, 0 ++# CHECK: encoding: [0xc2,0xba,0x60,0x38] ++amswap.d $tp, $r14, $r22, 0 ++ ++# CHECK: amadd.w $r8, $r12, $r21, 0 ++# CHECK: encoding: [0xa8,0x32,0x61,0x38] ++amadd.w $r8, $r12, $r21, 0 ++ ++# CHECK: amadd.d $r5, $r17, $r29, 0 ++# CHECK: encoding: [0xa5,0xc7,0x61,0x38] ++amadd.d $r5, $r17, $r29, 0 ++ ++# CHECK: amand.w $r4, $r19, $r22, 0 ++# CHECK: encoding: [0xc4,0x4e,0x62,0x38] ++amand.w $r4, $r19, $r22, 0 ++ ++# CHECK: amand.d $r10, $r18, $r29, 0 ++# CHECK: encoding: [0xaa,0xcb,0x62,0x38] ++amand.d $r10, $r18, $r29, 0 ++ ++# CHECK: amor.w $r6, $r16, $r23, 0 ++# CHECK: encoding: [0xe6,0x42,0x63,0x38] ++amor.w $r6, $r16, $r23, 0 ++ ++# CHECK: amor.d $sp, $r16, $r24, 0 ++# CHECK: encoding: [0x03,0xc3,0x63,0x38] ++amor.d $sp, $r16, $r24, 0 ++ ++# CHECK: amxor.w $tp, $r15, $r23, 0 ++# CHECK: encoding: [0xe2,0x3e,0x64,0x38] ++amxor.w $tp, $r15, $r23, 0 ++ ++# CHECK: amxor.d $r8, $r20, $r28, 0 ++# CHECK: encoding: [0x88,0xd3,0x64,0x38] ++amxor.d $r8, $r20, $r28, 0 ++ ++# CHECK: ammax.w $ra, $r11, $r23, 0 ++# CHECK: encoding: [0xe1,0x2e,0x65,0x38] ++ammax.w $ra, $r11, $r23, 0 ++ ++# CHECK: ammax.d $r9, $r20, $r27, 0 ++# CHECK: encoding: [0x69,0xd3,0x65,0x38] ++ammax.d $r9, $r20, $r27, 0 ++ ++# CHECK: ammin.w $r9, $r14, $r23, 0 ++# CHECK: encoding: [0xe9,0x3a,0x66,0x38] ++ammin.w $r9, $r14, $r23, 0 ++ ++# CHECK: ammin.d $r9, $r13, $r22, 0 ++# CHECK: encoding: [0xc9,0xb6,0x66,0x38] ++ammin.d $r9, $r13, $r22, 0 ++ ++# CHECK: ammax.wu $r9, $r11, $r22, 0 ++# CHECK: encoding: [0xc9,0x2e,0x67,0x38] ++ammax.wu $r9, $r11, $r22, 0 ++ ++# CHECK: ammax.du $r6, $r16, $r25, 0 ++# CHECK: encoding: [0x26,0xc3,0x67,0x38] ++ammax.du $r6, $r16, $r25, 0 ++ ++# CHECK: ammin.wu $r8, $r18, $r30, 0 ++# CHECK: encoding: [0xc8,0x4b,0x68,0x38] ++ammin.wu $r8, $r18, $r30, 0 ++ ++# CHECK: ammin.du $r7, $r16, $r25, 0 ++# CHECK: encoding: [0x27,0xc3,0x68,0x38] ++ammin.du $r7, $r16, $r25, 0 ++ ++# CHECK: fldgt.s $f3, $r27, $r13 ++# CHECK: encoding: [0x63,0x37,0x74,0x38] ++fldgt.s $f3, $r27, $r13 ++ ++# CHECK: fldgt.d $f26, $r5, $r31 ++# CHECK: encoding: [0xba,0xfc,0x74,0x38] ++fldgt.d $f26, $r5, $r31 ++ ++# CHECK: fldle.s $f24, $r29, $r17 ++# CHECK: encoding: [0xb8,0x47,0x75,0x38] ++fldle.s $f24, $r29, $r17 ++ ++# CHECK: fldle.d $f3, $r15, $r22 ++# CHECK: encoding: [0xe3,0xd9,0x75,0x38] ++fldle.d $f3, $r15, $r22 ++ ++# CHECK: fstgt.s $f31, $r13, $r30 ++# CHECK: encoding: [0xbf,0x79,0x76,0x38] ++fstgt.s $f31, $r13, $r30 ++ ++# CHECK: fstgt.d $f13, $r11, $r26 ++# CHECK: encoding: [0x6d,0xe9,0x76,0x38] ++fstgt.d $f13, $r11, $r26 ++ ++# CHECK: fstle.s $f13, $r13, $r7 ++# CHECK: encoding: [0xad,0x1d,0x77,0x38] ++fstle.s $f13, $r13, $r7 ++ ++# CHECK: fstle.d $f18, $r9, $r13 ++# CHECK: encoding: [0x32,0xb5,0x77,0x38] ++fstle.d $f18, $r9, $r13 ++ ++# CHECK: preld 10, $zero, 23 ++# CHECK: encoding: [0x0a,0x5c,0xc0,0x2a] ++preld 10, $zero, 23 ++ ++# CHECK: ldgt.b $r6, $r6, $r29 ++# CHECK: encoding: [0xc6,0x74,0x78,0x38] ++ldgt.b $r6, $r6, $r29 ++ ++# CHECK: ldgt.h $r5, $r31, $ra ++# CHECK: encoding: [0xe5,0x87,0x78,0x38] ++ldgt.h $r5, $r31, $ra ++ ++# CHECK: ldgt.w $r15, $r26, $r8 ++# CHECK: encoding: [0x4f,0x23,0x79,0x38] ++ldgt.w $r15, $r26, $r8 ++ ++# CHECK: ldgt.d $r23, $r25, $r31 ++# CHECK: encoding: [0x37,0xff,0x79,0x38] ++ldgt.d $r23, $r25, $r31 ++ ++# CHECK: ldle.b $r9, $r12, $r15 ++# CHECK: encoding: [0x89,0x3d,0x7a,0x38] ++ldle.b $r9, $r12, $r15 ++ ++# CHECK: ldle.h $r11, $r11, $r23 ++# CHECK: encoding: [0x6b,0xdd,0x7a,0x38] ++ldle.h $r11, $r11, $r23 ++ ++# CHECK: ldle.w $r24, $tp, $tp ++# CHECK: encoding: [0x58,0x08,0x7b,0x38] ++ldle.w $r24, $tp, $tp ++ ++# CHECK: ldle.d $r20, $r15, $r16 ++# CHECK: encoding: [0xf4,0xc1,0x7b,0x38] ++ldle.d $r20, $r15, $r16 ++ ++# CHECK: stgt.b $r27, $r19, $r20 ++# CHECK: encoding: [0x7b,0x52,0x7c,0x38] ++stgt.b $r27, $r19, $r20 ++ ++# CHECK: stgt.h $r16, $r4, $r6 ++# CHECK: encoding: [0x90,0x98,0x7c,0x38] ++stgt.h $r16, $r4, $r6 ++ ++# CHECK: stgt.w $r31, $r28, $r14 ++# CHECK: encoding: [0x9f,0x3b,0x7d,0x38] ++stgt.w $r31, $r28, $r14 ++ ++# CHECK: stgt.d $r30, $r21, $r24 ++# CHECK: encoding: [0xbe,0xe2,0x7d,0x38] ++stgt.d $r30, $r21, $r24 ++ ++# CHECK: stle.b $r10, $r4, $r16 ++# CHECK: encoding: [0x8a,0x40,0x7e,0x38] ++stle.b $r10, $r4, $r16 ++ ++# CHECK: stle.h $r17, $r17, $r21 ++# CHECK: encoding: [0x31,0xd6,0x7e,0x38] ++stle.h $r17, $r17, $r21 ++ ++# CHECK: stle.w $r23, $r28, $r29 ++# CHECK: encoding: [0x97,0x77,0x7f,0x38] ++stle.w $r23, $r28, $r29 ++ ++# CHECK: stle.d $r25, $r24, $r29 ++# CHECK: encoding: [0x19,0xf7,0x7f,0x38] ++stle.d $r25, $r24, $r29 ++ +diff --git a/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s b/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s +new file mode 100644 +index 000000000..57a252a8d +--- /dev/null ++++ b/src/llvm-project/llvm/test/MC/LoongArch/valid_priv.s +@@ -0,0 +1,125 @@ ++# RUN: llvm-mc %s -triple=loongarch64-unknown-linux-gnu -show-encoding | FileCheck %s ++# CHECK: csrrd $r26, 30 ++# CHECK: encoding: [0x1a,0x78,0x00,0x04] ++csrrd $r26, 30 ++ ++# CHECK: csrwr $r24, 194 ++# CHECK: encoding: [0x38,0x08,0x03,0x04] ++csrwr $r24, 194 ++ ++# CHECK: csrxchg $r6, $r27, 214 ++# CHECK: encoding: [0x66,0x5b,0x03,0x04] ++csrxchg $r6, $r27, 214 ++ ++# CHECK: cacop 0, $r10, 27 ++# CHECK: encoding: [0x40,0x6d,0x00,0x06] ++cacop 0, $r10, 27 ++ ++# CHECK: lddir $r12, $r30, 92 ++# CHECK: encoding: [0xcc,0x73,0x41,0x06] ++lddir $r12, $r30, 92 ++ ++# CHECK: ldpte $r18, 200 ++# CHECK: encoding: [0x40,0x22,0x47,0x06] ++ldpte $r18, 200 ++ ++# CHECK: iocsrrd.b $r26, $r24 ++# CHECK: encoding: [0x1a,0x03,0x48,0x06] ++iocsrrd.b $r26, $r24 ++ ++# CHECK: iocsrrd.h $r5, $r27 ++# CHECK: encoding: [0x65,0x07,0x48,0x06] ++iocsrrd.h $r5, $r27 ++ ++# CHECK: iocsrrd.w $r10, $r20 ++# CHECK: encoding: [0x8a,0x0a,0x48,0x06] ++iocsrrd.w $r10, $r20 ++ ++# CHECK: iocsrrd.d $r17, $r25 ++# CHECK: encoding: [0x31,0x0f,0x48,0x06] ++iocsrrd.d $r17, $r25 ++ ++# CHECK: iocsrwr.b $r4, $r23 ++# CHECK: encoding: [0xe4,0x12,0x48,0x06] ++iocsrwr.b $r4, $r23 ++ ++# CHECK: iocsrwr.h $r11, $zero ++# CHECK: encoding: [0x0b,0x14,0x48,0x06] ++iocsrwr.h $r11, $zero ++ ++# CHECK: iocsrwr.w $r20, $r26 ++# CHECK: encoding: [0x54,0x1b,0x48,0x06] ++iocsrwr.w $r20, $r26 ++ ++# CHECK: iocsrwr.d $r20, $r7 ++# CHECK: encoding: [0xf4,0x1c,0x48,0x06] ++iocsrwr.d $r20, $r7 ++ ++# CHECK: tlbclr ++# CHECK: encoding: [0x00,0x20,0x48,0x06] ++tlbclr ++ ++# CHECK: tlbflush ++# CHECK: encoding: [0x00,0x24,0x48,0x06] ++tlbflush ++ ++# CHECK: tlbsrch ++# CHECK: encoding: [0x00,0x28,0x48,0x06] ++tlbsrch ++ ++# CHECK: tlbrd ++# CHECK: encoding: [0x00,0x2c,0x48,0x06] ++tlbrd ++ ++# CHECK: tlbwr ++# CHECK: encoding: [0x00,0x30,0x48,0x06] ++tlbwr ++ ++# CHECK: tlbfill ++# CHECK: encoding: [0x00,0x34,0x48,0x06] ++tlbfill ++ ++# CHECK: ertn ++# CHECK: encoding: [0x00,0x38,0x48,0x06] ++ertn ++ ++# CHECK: idle 204 ++# CHECK: encoding: [0xcc,0x80,0x48,0x06] ++idle 204 ++ ++# CHECK: invtlb 16, $r29, $r25 ++# CHECK: encoding: [0xb0,0xe7,0x49,0x06] ++invtlb 16, $r29, $r25 ++ ++# CHECK: rdtimel.w $r30, $r19 ++# CHECK: encoding: [0x7e,0x62,0x00,0x00] ++rdtimel.w $r30, $r19 ++ ++# CHECK: rdtimeh.w $r19, $r14 ++# CHECK: encoding: [0xd3,0x65,0x00,0x00] ++rdtimeh.w $r19, $r14 ++ ++# CHECK: rdtime.d $tp, $r15 ++# CHECK: encoding: [0xe2,0x69,0x00,0x00] ++rdtime.d $tp, $r15 ++ ++# CHECK: asrtle.d $r12, $r17 ++# CHECK: encoding: [0x80,0x45,0x01,0x00] ++asrtle.d $r12, $r17 ++ ++# CHECK: asrtgt.d $r20, $r20 ++# CHECK: encoding: [0x80,0xd2,0x01,0x00] ++asrtgt.d $r20, $r20 ++ ++# CHECK: break 199 ++# CHECK: encoding: [0xc7,0x00,0x2a,0x00] ++break 199 ++ ++# CHECK: dbcl 201 ++# CHECK: encoding: [0xc9,0x80,0x2a,0x00] ++dbcl 201 ++ ++# CHECK: syscall 100 ++# CHECK: encoding: [0x64,0x00,0x2b,0x00] ++syscall 100 ++ +diff --git a/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test b/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test +deleted file mode 100644 +index 01680841d..000000000 +--- a/src/llvm-project/llvm/test/Support/unix03-sigpipe-exit.test ++++ /dev/null +@@ -1,26 +0,0 @@ +-## Test that when writing to a closed stdout, LLVM tools finish with a non-zero +-## exit code and an error message on stderr. The test uses llvm-cxxfilt, but +-## it's a logic from the default SIGPIPE handler, so it applies to all the tools. +-## This is required for UNIX03 conformance. +- +-# UNSUPPORTED: system-windows +- +-# RUN: not %python %s llvm-cxxfilt 2>&1 | FileCheck %s +-# CHECK: error: write on a pipe with no reader +- +-import subprocess +-import sys +- +-with subprocess.Popen([sys.argv[1]], stdout=subprocess.PIPE, stdin=subprocess.PIPE) as process: +- process.stdout.close() +- +- # llvm-cxxfilt with no extra arguments runs interactively and writes input +- # to output. Writing continuously to stdin should trigger SIGPIPE when the +- # subprocess attempts to write out bytes to a closed stdout. +- try: +- while True: +- process.stdin.write("foo\n".encode("utf-8")) +- except BrokenPipeError: +- # Clear stdin, pipe is broken and closing it on cleanup will raise an exception. +- process.stdin = None +-sys.exit(process.returncode) +diff --git a/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg b/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg +deleted file mode 100644 +index 31902e060..000000000 +--- a/src/llvm-project/llvm/test/Transforms/AtomicExpand/LoongArch/lit.local.cfg ++++ /dev/null +@@ -1,5 +0,0 @@ +-config.suffixes = ['.ll'] +- +-targets = set(config.root.targets_to_build.split()) +-if not 'LoongArch' in targets: +- config.unsupported = True +diff --git a/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll b/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll +new file mode 100644 +index 000000000..188210782 +--- /dev/null ++++ b/src/llvm-project/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll +@@ -0,0 +1,38 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature ++; RUN: opt -passes=globalopt -S < %s | FileCheck %s ++ ++define i32 @main(ptr %a) { ++; CHECK-LABEL: define {{[^@]+}}@main ++; CHECK-SAME: (ptr [[A:%.*]]) local_unnamed_addr { ++; CHECK-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ ptr, i32 }>, align 4 ++; CHECK-NEXT: store ptr [[A]], ptr [[ARGMEM]], align 8 ++; CHECK-NEXT: [[G0:%.*]] = getelementptr inbounds <{ ptr, i32 }>, ptr [[ARGMEM]], i32 0, i32 1 ++; CHECK-NEXT: store i32 5, ptr [[G0]], align 4 ++; CHECK-NEXT: [[CALL3:%.*]] = call i32 (ptr, ...) @i(ptr inalloca(ptr) [[ARGMEM]]) ++; CHECK-NEXT: ret i32 [[CALL3]] ++; ++ %argmem = alloca inalloca <{ ptr, i32 }>, align 4 ++ store ptr %a, ptr %argmem, align 8 ++ %g0 = getelementptr inbounds <{ ptr, i32 }>, ptr %argmem, i32 0, i32 1 ++ store i32 5, ptr %g0, align 4 ++ %call3 = call i32 (ptr, ...) @i(ptr inalloca(ptr) %argmem) ++ ret i32 %call3 ++} ++ ++define internal i32 @i(ptr inalloca(ptr) %a, ...) { ++; CHECK-LABEL: define {{[^@]+}}@i ++; CHECK-SAME: (ptr inalloca(ptr) [[A:%.*]], ...) unnamed_addr { ++; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4 ++; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) ++; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[AP]], align 4 ++; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 ++; CHECK-NEXT: ret i32 [[L]] ++; ++ %ap = alloca ptr, align 4 ++ call void @llvm.va_start(ptr %ap) ++ %argp.cur = load ptr, ptr %ap, align 4 ++ %l = load i32, ptr %argp.cur, align 4 ++ ret i32 %l ++} ++ ++declare void @llvm.va_start(ptr) +diff --git a/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll b/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll +new file mode 100644 +index 000000000..b3e305583 +--- /dev/null ++++ b/src/llvm-project/llvm/test/Transforms/InstCombine/cast-byval.ll +@@ -0,0 +1,31 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; Check that function calls involving conversion from/to byval aren't transformed. ++; RUN: opt < %s -passes=instcombine -S | FileCheck %s ++ ++%Foo = type { i64 } ++define i64 @foo (ptr byval(%Foo) %foo) { ++; CHECK-LABEL: @foo( ++; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[FOO:%.*]], align 4 ++; CHECK-NEXT: ret i64 [[TMP1]] ++; ++ %1 = load i64, ptr %foo, align 4 ++ ret i64 %1 ++} ++ ++define i64 @bar(i64 %0) { ++; CHECK-LABEL: @bar( ++; CHECK-NEXT: [[TMP2:%.*]] = tail call i64 @foo(i64 [[TMP0:%.*]]) ++; CHECK-NEXT: ret i64 [[TMP2]] ++; ++ %2 = tail call i64 @foo(i64 %0) ++ ret i64 %2 ++} ++ ++define i64 @qux(ptr byval(%Foo) %qux) { ++; CHECK-LABEL: @qux( ++; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @bar(ptr nonnull byval([[FOO:%.*]]) [[QUX:%.*]]) ++; CHECK-NEXT: ret i64 [[TMP1]] ++; ++ %1 = tail call i64 @bar(ptr byval(%Foo) %qux) ++ ret i64 %1 ++} +diff --git a/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll b/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll +new file mode 100644 +index 000000000..4b0bc908e +--- /dev/null ++++ b/src/llvm-project/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll +@@ -0,0 +1,125 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; RUN: opt -force-vector-width=4 -force-vector-interleave=1 -passes='loop-vectorize,loop-load-elim' -S %s | FileCheck %s ++ ++@glob.1 = external global [100 x double] ++@glob.2 = external global [100 x double] ++ ++define void @g(ptr %dst.1, ptr %start, i64 %N) { ++; CHECK-LABEL: @g( ++; CHECK-NEXT: loop.1.lver.check: ++; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[N:%.*]], 3 ++; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 16 ++; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr @glob.2, i64 [[TMP1]] ++; CHECK-NEXT: [[UGLYGEP2:%.*]] = getelementptr i8, ptr [[DST_1:%.*]], i64 8 ++; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr @glob.2, [[UGLYGEP2]] ++; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[DST_1]], [[UGLYGEP]] ++; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] ++; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[LOOP_1_PH_LVER_ORIG:%.*]], label [[LOOP_1_PH:%.*]] ++; CHECK: loop.1.ph.lver.orig: ++; CHECK-NEXT: br label [[LOOP_1_LVER_ORIG:%.*]] ++; CHECK: loop.1.lver.orig: ++; CHECK-NEXT: [[IV_LVER_ORIG:%.*]] = phi i64 [ 0, [[LOOP_1_PH_LVER_ORIG]] ], [ [[IV_NEXT_LVER_ORIG:%.*]], [[LOOP_1_LVER_ORIG]] ] ++; CHECK-NEXT: [[PTR_IV_1_LVER_ORIG:%.*]] = phi ptr [ @glob.1, [[LOOP_1_PH_LVER_ORIG]] ], [ [[PTR_IV_1_NEXT_LVER_ORIG:%.*]], [[LOOP_1_LVER_ORIG]] ] ++; CHECK-NEXT: [[GEP_IV_LVER_ORIG:%.*]] = getelementptr inbounds double, ptr @glob.2, i64 [[IV_LVER_ORIG]] ++; CHECK-NEXT: [[L_1_LVER_ORIG:%.*]] = load double, ptr [[GEP_IV_LVER_ORIG]], align 8 ++; CHECK-NEXT: [[GEP_IV_1_LVER_ORIG:%.*]] = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 [[IV_LVER_ORIG]] ++; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_IV_1_LVER_ORIG]], align 8 ++; CHECK-NEXT: store double 0.000000e+00, ptr [[DST_1]], align 8 ++; CHECK-NEXT: [[PTR_IV_1_NEXT_LVER_ORIG]] = getelementptr inbounds double, ptr [[PTR_IV_1_LVER_ORIG]], i64 1 ++; CHECK-NEXT: [[IV_NEXT_LVER_ORIG]] = add nuw nsw i64 [[IV_LVER_ORIG]], 1 ++; CHECK-NEXT: [[EXITCOND_NOT_LVER_ORIG:%.*]] = icmp eq i64 [[IV_LVER_ORIG]], [[N]] ++; CHECK-NEXT: br i1 [[EXITCOND_NOT_LVER_ORIG]], label [[LOOP_2_PH_LOOPEXIT:%.*]], label [[LOOP_1_LVER_ORIG]] ++; CHECK: loop.1.ph: ++; CHECK-NEXT: [[LOAD_INITIAL:%.*]] = load double, ptr @glob.2, align 8 ++; CHECK-NEXT: br label [[LOOP_1:%.*]] ++; CHECK: loop.1: ++; CHECK-NEXT: [[STORE_FORWARDED:%.*]] = phi double [ [[LOAD_INITIAL]], [[LOOP_1_PH]] ], [ 0.000000e+00, [[LOOP_1]] ] ++; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[LOOP_1_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_1]] ] ++; CHECK-NEXT: [[PTR_IV_1:%.*]] = phi ptr [ @glob.1, [[LOOP_1_PH]] ], [ [[PTR_IV_1_NEXT:%.*]], [[LOOP_1]] ] ++; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds double, ptr @glob.2, i64 [[IV]] ++; CHECK-NEXT: [[L_1:%.*]] = load double, ptr [[GEP_IV]], align 8 ++; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 [[IV]] ++; CHECK-NEXT: store double 0.000000e+00, ptr [[GEP_IV_1]], align 8 ++; CHECK-NEXT: store double 0.000000e+00, ptr [[DST_1]], align 8 ++; CHECK-NEXT: [[PTR_IV_1_NEXT]] = getelementptr inbounds double, ptr [[PTR_IV_1]], i64 1 ++; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ++; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[N]] ++; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[LOOP_2_PH_LOOPEXIT3:%.*]], label [[LOOP_1]] ++; CHECK: loop.2.ph.loopexit: ++; CHECK-NEXT: [[LCSSA_PTR_IV_1_PH:%.*]] = phi ptr [ [[PTR_IV_1_LVER_ORIG]], [[LOOP_1_LVER_ORIG]] ] ++; CHECK-NEXT: br label [[LOOP_2_PH:%.*]] ++; CHECK: loop.2.ph.loopexit3: ++; CHECK-NEXT: [[LCSSA_PTR_IV_1_PH4:%.*]] = phi ptr [ [[PTR_IV_1]], [[LOOP_1]] ] ++; CHECK-NEXT: br label [[LOOP_2_PH]] ++; CHECK: loop.2.ph: ++; CHECK-NEXT: [[LCSSA_PTR_IV_1:%.*]] = phi ptr [ [[LCSSA_PTR_IV_1_PH]], [[LOOP_2_PH_LOOPEXIT]] ], [ [[LCSSA_PTR_IV_1_PH4]], [[LOOP_2_PH_LOOPEXIT3]] ] ++; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 ++; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ++; CHECK: vector.ph: ++; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 ++; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] ++; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[N_VEC]], 8 ++; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[LCSSA_PTR_IV_1]], i64 [[TMP2]] ++; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ++; CHECK: vector.body: ++; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ++; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0 ++; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[TMP3]], 8 ++; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[LCSSA_PTR_IV_1]], i64 [[TMP4]] ++; CHECK-NEXT: [[TMP5:%.*]] = getelementptr double, ptr [[NEXT_GEP]], i32 0 ++; CHECK-NEXT: store <4 x double> zeroinitializer, ptr [[TMP5]], align 8 ++; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ++; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] ++; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ++; CHECK: middle.block: ++; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] ++; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] ++; CHECK: scalar.ph: ++; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_2_PH]] ] ++; CHECK-NEXT: [[BC_RESUME_VAL1:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[LCSSA_PTR_IV_1]], [[LOOP_2_PH]] ] ++; CHECK-NEXT: br label [[LOOP_2:%.*]] ++; CHECK: loop.2: ++; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_2_NEXT:%.*]], [[LOOP_2]] ] ++; CHECK-NEXT: [[PTR_IV_2:%.*]] = phi ptr [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[PTR_IV_2_NEXT:%.*]], [[LOOP_2]] ] ++; CHECK-NEXT: store double 0.000000e+00, ptr [[PTR_IV_2]], align 8 ++; CHECK-NEXT: [[PTR_IV_2_NEXT]] = getelementptr inbounds double, ptr [[PTR_IV_2]], i64 1 ++; CHECK-NEXT: [[IV_2_NEXT]] = add nuw nsw i64 [[IV_2]], 1 ++; CHECK-NEXT: [[EXITCOND_1_NOT:%.*]] = icmp eq i64 [[IV_2_NEXT]], [[N]] ++; CHECK-NEXT: br i1 [[EXITCOND_1_NOT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_2]], !llvm.loop [[LOOP2:![0-9]+]] ++; CHECK: exit.loopexit: ++; CHECK-NEXT: br label [[EXIT]] ++; CHECK: exit: ++; CHECK-NEXT: ret void ++; ++entry: ++ br label %loop.1 ++ ++loop.1: ++ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.1 ] ++ %ptr.iv.1 = phi ptr [ @glob.1, %entry ], [ %ptr.iv.1.next, %loop.1 ] ++ %gep.iv = getelementptr inbounds double, ptr @glob.2, i64 %iv ++ %l.1 = load double, ptr %gep.iv, align 8 ++ %gep.iv.1 = getelementptr inbounds double, ptr getelementptr inbounds (double, ptr @glob.2, i64 1), i64 %iv ++ store double 0.000000e+00, ptr %gep.iv.1, align 8 ++ store double 0.000000e+00, ptr %dst.1, align 8 ++ %ptr.iv.1.next = getelementptr inbounds double, ptr %ptr.iv.1, i64 1 ++ %iv.next = add nuw nsw i64 %iv, 1 ++ %exitcond.not = icmp eq i64 %iv, %N ++ br i1 %exitcond.not, label %loop.2.ph, label %loop.1 ++ ++loop.2.ph: ++ %lcssa.ptr.iv.1 = phi ptr [ %ptr.iv.1, %loop.1 ] ++ br label %loop.2 ++ ++loop.2: ++ %iv.2 = phi i64 [ 0, %loop.2.ph ] , [ %iv.2.next, %loop.2 ] ++ %ptr.iv.2 = phi ptr [ %lcssa.ptr.iv.1, %loop.2.ph ], [ %ptr.iv.2.next, %loop.2 ] ++ store double 0.000000e+00, ptr %ptr.iv.2, align 8 ++ %ptr.iv.2.next = getelementptr inbounds double, ptr %ptr.iv.2, i64 1 ++ %iv.2.next = add nuw nsw i64 %iv.2, 1 ++ %exitcond.1.not = icmp eq i64 %iv.2.next, %N ++ br i1 %exitcond.1.not, label %exit, label %loop.2 ++ ++exit: ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll b/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll +new file mode 100644 +index 000000000..32ca12ee7 +--- /dev/null ++++ b/src/llvm-project/llvm/test/Transforms/LoopVectorize/AArch64/interleave-allocsize-not-equal-typesize.ll +@@ -0,0 +1,141 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; RUN: opt -passes=loop-vectorize -S %s | FileCheck %s ++ ++target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" ++target triple = "aarch64-unknown-linux-gnu" ++ ++; Make sure LV does not crash when analyzing potential interleave groups with ++; accesses where the typesize doesn't match to allocsize. ++define void @pr58722_load_interleave_group(ptr %src, ptr %dst) { ++; CHECK-LABEL: @pr58722_load_interleave_group( ++; CHECK-NEXT: entry: ++; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]] ++; CHECK: vector.memcheck: ++; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 40004 ++; CHECK-NEXT: [[UGLYGEP1:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 80007 ++; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[DST]], [[UGLYGEP1]] ++; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SRC]], [[UGLYGEP]] ++; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] ++; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] ++; CHECK: vector.ph: ++; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ++; CHECK: vector.body: ++; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ++; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 ++; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 1 ++; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 2 ++; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 3 ++; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP0]] ++; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP1]] ++; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP2]] ++; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP3]] ++; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP4]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x i32> poison, i32 [[TMP8]], i32 0 ++; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP9]], i32 1 ++; CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP6]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP7]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> poison, i32 [[TMP12]], i32 0 ++; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x i32> [[TMP14]], i32 [[TMP13]], i32 1 ++; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i64 1 ++; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i64 1 ++; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 1 ++; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i64 1 ++; CHECK-NEXT: [[TMP20:%.*]] = load i24, ptr [[TMP16]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP21:%.*]] = load i24, ptr [[TMP17]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP22:%.*]] = insertelement <2 x i24> poison, i24 [[TMP20]], i32 0 ++; CHECK-NEXT: [[TMP23:%.*]] = insertelement <2 x i24> [[TMP22]], i24 [[TMP21]], i32 1 ++; CHECK-NEXT: [[TMP24:%.*]] = load i24, ptr [[TMP18]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP25:%.*]] = load i24, ptr [[TMP19]], align 4, !alias.scope !0 ++; CHECK-NEXT: [[TMP26:%.*]] = insertelement <2 x i24> poison, i24 [[TMP24]], i32 0 ++; CHECK-NEXT: [[TMP27:%.*]] = insertelement <2 x i24> [[TMP26]], i24 [[TMP25]], i32 1 ++; CHECK-NEXT: [[TMP28:%.*]] = zext <2 x i24> [[TMP23]] to <2 x i32> ++; CHECK-NEXT: [[TMP29:%.*]] = zext <2 x i24> [[TMP27]] to <2 x i32> ++; CHECK-NEXT: [[TMP30:%.*]] = add <2 x i32> [[TMP11]], [[TMP28]] ++; CHECK-NEXT: [[TMP31:%.*]] = add <2 x i32> [[TMP15]], [[TMP29]] ++; CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP0]] ++; CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP2]] ++; CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds i32, ptr [[TMP32]], i32 0 ++; CHECK-NEXT: store <2 x i32> [[TMP30]], ptr [[TMP34]], align 4, !alias.scope !3, !noalias !0 ++; CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds i32, ptr [[TMP32]], i32 2 ++; CHECK-NEXT: store <2 x i32> [[TMP31]], ptr [[TMP35]], align 4, !alias.scope !3, !noalias !0 ++; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ++; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10000 ++; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] ++; CHECK: middle.block: ++; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 10001, 10000 ++; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] ++; CHECK: scalar.ph: ++; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 10000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_MEMCHECK]] ] ++; CHECK-NEXT: br label [[LOOP:%.*]] ++; CHECK: loop: ++; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] ++; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV]] ++; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP_IV]], align 4 ++; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[GEP_IV]], i64 1 ++; CHECK-NEXT: [[V2:%.*]] = load i24, ptr [[GEP]], align 4 ++; CHECK-NEXT: [[V2_EXT:%.*]] = zext i24 [[V2]] to i32 ++; CHECK-NEXT: [[SUM:%.*]] = add i32 [[V1]], [[V2_EXT]] ++; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] ++; CHECK-NEXT: store i32 [[SUM]], ptr [[GEP_DST]], align 4 ++; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ++; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV]], 10000 ++; CHECK-NEXT: br i1 [[CMP]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] ++; CHECK: exit: ++; CHECK-NEXT: ret void ++; ++entry: ++ br label %loop ++ ++loop: ++ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] ++ %gep.iv = getelementptr inbounds i64, ptr %src, i64 %iv ++ %v1 = load i32, ptr %gep.iv, align 4 ++ %gep = getelementptr inbounds i32, ptr %gep.iv, i64 1 ++ %v2 = load i24, ptr %gep, align 4 ++ %v2.ext = zext i24 %v2 to i32 ++ %sum = add i32 %v1, %v2.ext ++ %gep.dst = getelementptr inbounds i32, ptr %dst, i64 %iv ++ store i32 %sum, ptr %gep.dst ++ %iv.next = add i64 %iv, 1 ++ %cmp = icmp eq i64 %iv, 10000 ++ br i1 %cmp, label %exit, label %loop ++ ++exit: ++ ret void ++} ++ ++define void @pr58722_store_interleave_group(ptr %src, ptr %dst) { ++; CHECK-LABEL: @pr58722_store_interleave_group( ++; CHECK-NEXT: entry: ++; CHECK-NEXT: br label [[LOOP:%.*]] ++; CHECK: loop: ++; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] ++; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i32 [[IV]] ++; CHECK-NEXT: store i32 [[IV]], ptr [[GEP_IV]], align 4 ++; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[GEP_IV]], i64 1 ++; CHECK-NEXT: [[TRUNC_IV:%.*]] = trunc i32 [[IV]] to i24 ++; CHECK-NEXT: store i24 [[TRUNC_IV]], ptr [[GEP]], align 4 ++; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 2 ++; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[IV]], 10000 ++; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] ++; CHECK: exit: ++; CHECK-NEXT: ret void ++; ++entry: ++ br label %loop ++ ++loop: ++ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ++ %gep.iv = getelementptr inbounds i64, ptr %src, i32 %iv ++ store i32 %iv, ptr %gep.iv ++ %gep = getelementptr inbounds i64, ptr %gep.iv, i64 1 ++ %trunc.iv = trunc i32 %iv to i24 ++ store i24 %trunc.iv, ptr %gep ++ %iv.next = add i32 %iv, 2 ++ %cmp = icmp eq i32 %iv, 10000 ++ br i1 %cmp, label %exit, label %loop ++ ++exit: ++ ret void ++} +diff --git a/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll b/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll +new file mode 100644 +index 000000000..7893da340 +--- /dev/null ++++ b/src/llvm-project/llvm/test/Transforms/SROA/phi-speculate-different-load-types.ll +@@ -0,0 +1,41 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; RUN: opt -passes=sroa < %s -S | FileCheck %s ++ ++define void @f(i1 %i) { ++; CHECK-LABEL: @f( ++; CHECK-NEXT: [[A1:%.*]] = alloca i64, align 8 ++; CHECK-NEXT: [[A2:%.*]] = alloca i64, align 8 ++; CHECK-NEXT: br i1 [[I:%.*]], label [[BB1:%.*]], label [[BB:%.*]] ++; CHECK: bb: ++; CHECK-NEXT: br label [[BB2:%.*]] ++; CHECK: bb1: ++; CHECK-NEXT: br label [[BB2]] ++; CHECK: bb2: ++; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ [[A1]], [[BB1]] ], [ [[A2]], [[BB]] ] ++; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP3]], align 4 ++; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 ++; CHECK-NEXT: call void @use32(i32 [[TMP5]]) ++; CHECK-NEXT: call void @use64(i64 [[TMP4]]) ++; CHECK-NEXT: ret void ++; ++ %a1 = alloca i64 ++ %a2 = alloca i64 ++ br i1 %i, label %bb1, label %bb ++ ++bb: ++ br label %bb2 ++ ++bb1: ++ br label %bb2 ++ ++bb2: ++ %tmp3 = phi ptr [ %a1, %bb1 ], [ %a2, %bb ] ++ %tmp5 = load i32, ptr %tmp3 ++ %tmp4 = load i64, ptr %tmp3 ++ call void @use32(i32 %tmp5) ++ call void @use64(i64 %tmp4) ++ ret void ++} ++ ++declare void @use32(i32) ++declare void @use64(i64) +diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected +index 692941b50..306b22ebb 100644 +--- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected ++++ b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_function_name.ll.expected +@@ -1,13 +1,13 @@ + ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + ; Check that we accept functions with '$' in the name. + +-; RUN: llc -mtriple=loongarch32-unknown-linux < %s | FileCheck %s ++; RUN: llc -mtriple=loongarch64-unknown-linux < %s | FileCheck %s + + define hidden i32 @"_Z54bar$ompvariant$bar"() { + ; CHECK-LABEL: _Z54bar$ompvariant$bar: + ; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: jirl $zero, $ra, 0 ++; CHECK-NEXT: ori $r4, $zero, 2 ++; CHECK-NEXT: jr $ra + entry: + ret i32 2 + } +diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected +deleted file mode 100644 +index 5d091d735..000000000 +--- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected ++++ /dev/null +@@ -1,148 +0,0 @@ +-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --include-generated-funcs +-; RUN: llc --enable-machine-outliner --mtriple=loongarch32-unknown-linux < %s | FileCheck %s +-@x = dso_local global i32 0, align 4 +- +-define dso_local i32 @check_boundaries() #0 { +- %1 = alloca i32, align 4 +- %2 = alloca i32, align 4 +- %3 = alloca i32, align 4 +- %4 = alloca i32, align 4 +- %5 = alloca i32, align 4 +- store i32 0, ptr %1, align 4 +- store i32 0, ptr %2, align 4 +- %6 = load i32, ptr %2, align 4 +- %7 = icmp ne i32 %6, 0 +- br i1 %7, label %9, label %8 +- +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- br label %10 +- +- store i32 1, ptr %4, align 4 +- br label %10 +- +- %11 = load i32, ptr %2, align 4 +- %12 = icmp ne i32 %11, 0 +- br i1 %12, label %14, label %13 +- +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- br label %15 +- +- store i32 1, ptr %4, align 4 +- br label %15 +- +- ret i32 0 +-} +- +-define dso_local i32 @main() #0 { +- %1 = alloca i32, align 4 +- %2 = alloca i32, align 4 +- %3 = alloca i32, align 4 +- %4 = alloca i32, align 4 +- %5 = alloca i32, align 4 +- +- store i32 0, ptr %1, align 4 +- store i32 0, ptr @x, align 4 +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- store i32 1, ptr @x, align 4 +- call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"() +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- ret i32 0 +-} +- +-attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } +-; CHECK-LABEL: check_boundaries: +-; CHECK: # %bb.0: +-; CHECK-NEXT: addi.w $sp, $sp, -32 +-; CHECK-NEXT: .cfi_def_cfa_offset 32 +-; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +-; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill +-; CHECK-NEXT: .cfi_offset 1, -4 +-; CHECK-NEXT: .cfi_offset 22, -8 +-; CHECK-NEXT: addi.w $fp, $sp, 32 +-; CHECK-NEXT: .cfi_def_cfa 22, 0 +-; CHECK-NEXT: st.w $zero, $fp, -16 +-; CHECK-NEXT: st.w $zero, $fp, -12 +-; CHECK-NEXT: bnez $zero, .LBB0_2 +-; CHECK-NEXT: b .LBB0_1 +-; CHECK-NEXT: .LBB0_2: +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: .LBB0_3: +-; CHECK-NEXT: ld.w $a0, $fp, -16 +-; CHECK-NEXT: bne $a0, $zero, .LBB0_5 +-; CHECK-NEXT: b .LBB0_4 +-; CHECK-NEXT: .LBB0_5: +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: .LBB0_6: +-; CHECK-NEXT: move $a0, $zero +-; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload +-; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +-; CHECK-NEXT: addi.w $sp, $sp, 32 +-; CHECK-NEXT: jirl $zero, $ra, 0 +-; CHECK-NEXT: .LBB0_1: +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 3 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: ori $a0, $zero, 4 +-; CHECK-NEXT: st.w $a0, $fp, -28 +-; CHECK-NEXT: b .LBB0_3 +-; CHECK-NEXT: .LBB0_4: +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 3 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: ori $a0, $zero, 4 +-; CHECK-NEXT: st.w $a0, $fp, -28 +-; CHECK-NEXT: b .LBB0_6 +-; +-; CHECK-LABEL: main: +-; CHECK: # %bb.0: +-; CHECK-NEXT: addi.w $sp, $sp, -32 +-; CHECK-NEXT: .cfi_def_cfa_offset 32 +-; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +-; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill +-; CHECK-NEXT: .cfi_offset 1, -4 +-; CHECK-NEXT: .cfi_offset 22, -8 +-; CHECK-NEXT: addi.w $fp, $sp, 32 +-; CHECK-NEXT: .cfi_def_cfa 22, 0 +-; CHECK-NEXT: pcalau12i $a0, x +-; CHECK-NEXT: addi.w $a0, $a0, x +-; CHECK-NEXT: ori $a1, $zero, 1 +-; CHECK-NEXT: st.w $a1, $a0, 0 +-; CHECK-NEXT: st.w $zero, $fp, -12 +-; CHECK-NEXT: st.w $a1, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a2, $zero, 3 +-; CHECK-NEXT: st.w $a2, $fp, -24 +-; CHECK-NEXT: ori $a3, $zero, 4 +-; CHECK-NEXT: st.w $a3, $fp, -28 +-; CHECK-NEXT: #APP +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: st.w $a1, $fp, -16 +-; CHECK-NEXT: st.w $a2, $fp, -24 +-; CHECK-NEXT: st.w $a3, $fp, -28 +-; CHECK-NEXT: move $a0, $zero +-; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload +-; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +-; CHECK-NEXT: addi.w $sp, $sp, 32 +-; CHECK-NEXT: jirl $zero, $ra, 0 +diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected +deleted file mode 100644 +index d4edfe5e0..000000000 +--- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected ++++ /dev/null +@@ -1,147 +0,0 @@ +-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +-; RUN: llc --enable-machine-outliner --mtriple=loongarch32-unknown-linux < %s | FileCheck %s +-@x = dso_local global i32 0, align 4 +- +-define dso_local i32 @check_boundaries() #0 { +-; CHECK-LABEL: check_boundaries: +-; CHECK: # %bb.0: +-; CHECK-NEXT: addi.w $sp, $sp, -32 +-; CHECK-NEXT: .cfi_def_cfa_offset 32 +-; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +-; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill +-; CHECK-NEXT: .cfi_offset 1, -4 +-; CHECK-NEXT: .cfi_offset 22, -8 +-; CHECK-NEXT: addi.w $fp, $sp, 32 +-; CHECK-NEXT: .cfi_def_cfa 22, 0 +-; CHECK-NEXT: st.w $zero, $fp, -16 +-; CHECK-NEXT: st.w $zero, $fp, -12 +-; CHECK-NEXT: bnez $zero, .LBB0_2 +-; CHECK-NEXT: b .LBB0_1 +-; CHECK-NEXT: .LBB0_2: +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: .LBB0_3: +-; CHECK-NEXT: ld.w $a0, $fp, -16 +-; CHECK-NEXT: bne $a0, $zero, .LBB0_5 +-; CHECK-NEXT: b .LBB0_4 +-; CHECK-NEXT: .LBB0_5: +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: .LBB0_6: +-; CHECK-NEXT: move $a0, $zero +-; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload +-; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +-; CHECK-NEXT: addi.w $sp, $sp, 32 +-; CHECK-NEXT: jirl $zero, $ra, 0 +-; CHECK-NEXT: .LBB0_1: +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 3 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: ori $a0, $zero, 4 +-; CHECK-NEXT: st.w $a0, $fp, -28 +-; CHECK-NEXT: b .LBB0_3 +-; CHECK-NEXT: .LBB0_4: +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a0, $zero, 1 +-; CHECK-NEXT: st.w $a0, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 3 +-; CHECK-NEXT: st.w $a0, $fp, -24 +-; CHECK-NEXT: ori $a0, $zero, 4 +-; CHECK-NEXT: st.w $a0, $fp, -28 +-; CHECK-NEXT: b .LBB0_6 +- %1 = alloca i32, align 4 +- %2 = alloca i32, align 4 +- %3 = alloca i32, align 4 +- %4 = alloca i32, align 4 +- %5 = alloca i32, align 4 +- store i32 0, ptr %1, align 4 +- store i32 0, ptr %2, align 4 +- %6 = load i32, ptr %2, align 4 +- %7 = icmp ne i32 %6, 0 +- br i1 %7, label %9, label %8 +- +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- br label %10 +- +- store i32 1, ptr %4, align 4 +- br label %10 +- +- %11 = load i32, ptr %2, align 4 +- %12 = icmp ne i32 %11, 0 +- br i1 %12, label %14, label %13 +- +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- br label %15 +- +- store i32 1, ptr %4, align 4 +- br label %15 +- +- ret i32 0 +-} +- +-define dso_local i32 @main() #0 { +-; CHECK-LABEL: main: +-; CHECK: # %bb.0: +-; CHECK-NEXT: addi.w $sp, $sp, -32 +-; CHECK-NEXT: .cfi_def_cfa_offset 32 +-; CHECK-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +-; CHECK-NEXT: st.w $fp, $sp, 24 # 4-byte Folded Spill +-; CHECK-NEXT: .cfi_offset 1, -4 +-; CHECK-NEXT: .cfi_offset 22, -8 +-; CHECK-NEXT: addi.w $fp, $sp, 32 +-; CHECK-NEXT: .cfi_def_cfa 22, 0 +-; CHECK-NEXT: pcalau12i $a0, x +-; CHECK-NEXT: addi.w $a0, $a0, x +-; CHECK-NEXT: ori $a1, $zero, 1 +-; CHECK-NEXT: st.w $a1, $a0, 0 +-; CHECK-NEXT: st.w $zero, $fp, -12 +-; CHECK-NEXT: st.w $a1, $fp, -16 +-; CHECK-NEXT: ori $a0, $zero, 2 +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: ori $a2, $zero, 3 +-; CHECK-NEXT: st.w $a2, $fp, -24 +-; CHECK-NEXT: ori $a3, $zero, 4 +-; CHECK-NEXT: st.w $a3, $fp, -28 +-; CHECK-NEXT: #APP +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: st.w $a0, $fp, -20 +-; CHECK-NEXT: st.w $a1, $fp, -16 +-; CHECK-NEXT: st.w $a2, $fp, -24 +-; CHECK-NEXT: st.w $a3, $fp, -28 +-; CHECK-NEXT: move $a0, $zero +-; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload +-; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +-; CHECK-NEXT: addi.w $sp, $sp, 32 +-; CHECK-NEXT: jirl $zero, $ra, 0 +- %1 = alloca i32, align 4 +- %2 = alloca i32, align 4 +- %3 = alloca i32, align 4 +- %4 = alloca i32, align 4 +- %5 = alloca i32, align 4 +- +- store i32 0, ptr %1, align 4 +- store i32 0, ptr @x, align 4 +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- store i32 1, ptr @x, align 4 +- call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"() +- store i32 1, ptr %2, align 4 +- store i32 2, ptr %3, align 4 +- store i32 3, ptr %4, align 4 +- store i32 4, ptr %5, align 4 +- ret i32 0 +-} +- +-attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } +diff --git a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test b/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test +deleted file mode 100644 +index 2209d3036..000000000 +--- a/src/llvm-project/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/loongarch_generated_funcs.test ++++ /dev/null +@@ -1,17 +0,0 @@ +-# REQUIRES: loongarch-registered-target +- +-## Check that generated functions are included. +-# RUN: cp -f %S/Inputs/loongarch_generated_funcs.ll %t.ll && %update_llc_test_checks --include-generated-funcs %t.ll +-# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.generated.expected +- +-## Check that running the script again does not change the result: +-# RUN: %update_llc_test_checks --include-generated-funcs %t.ll +-# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.generated.expected +- +-## Check that generated functions are not included. +-# RUN: cp -f %S/Inputs/loongarch_generated_funcs.ll %t.ll && %update_llc_test_checks %t.ll +-# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.nogenerated.expected +- +-## Check that running the script again does not change the result: +-# RUN: %update_llc_test_checks %t.ll +-# RUN: diff -u %t.ll %S/Inputs/loongarch_generated_funcs.ll.nogenerated.expected +diff --git a/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test b/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test +deleted file mode 100644 +index b66273640..000000000 +--- a/src/llvm-project/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test ++++ /dev/null +@@ -1,64 +0,0 @@ +-## Check llvm-readobj is able to decode all possible LoongArch e_flags field values. +- +-# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S +-# RUN: llvm-readobj -h %t-lp64s | FileCheck --check-prefix=READOBJ-LP64S %s +-# RUN: llvm-readelf -h %t-lp64s | FileCheck --check-prefix=READELF-LP64S --match-full-lines %s +- +-# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F +-# RUN: llvm-readobj -h %t-lp64f | FileCheck --check-prefix=READOBJ-LP64F %s +-# RUN: llvm-readelf -h %t-lp64f | FileCheck --check-prefix=READELF-LP64F --match-full-lines %s +- +-# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D +-# RUN: llvm-readobj -h %t-lp64d | FileCheck --check-prefix=READOBJ-LP64D %s +-# RUN: llvm-readelf -h %t-lp64d | FileCheck --check-prefix=READELF-LP64D --match-full-lines %s +- +-# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S +-# RUN: llvm-readobj -h %t-ilp32s | FileCheck --check-prefix=READOBJ-ILP32S %s +-# RUN: llvm-readelf -h %t-ilp32s | FileCheck --check-prefix=READELF-ILP32S --match-full-lines %s +- +-# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F +-# RUN: llvm-readobj -h %t-ilp32f | FileCheck --check-prefix=READOBJ-ILP32F %s +-# RUN: llvm-readelf -h %t-ilp32f | FileCheck --check-prefix=READELF-ILP32F --match-full-lines %s +- +-# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D +-# RUN: llvm-readobj -h %t-ilp32d | FileCheck --check-prefix=READOBJ-ILP32D %s +-# RUN: llvm-readelf -h %t-ilp32d | FileCheck --check-prefix=READELF-ILP32D --match-full-lines %s +- +-# READOBJ-LP64S: Flags [ (0x1) +-# READOBJ-LP64S-NEXT: EF_LOONGARCH_BASE_ABI_LP64S (0x1) +-# READOBJ-LP64S-NEXT: ] +- +-# READOBJ-LP64F: Flags [ (0x2) +-# READOBJ-LP64F-NEXT: EF_LOONGARCH_BASE_ABI_LP64F (0x2) +-# READOBJ-LP64F-NEXT: ] +- +-# READOBJ-LP64D: Flags [ (0x3) +-# READOBJ-LP64D-NEXT: EF_LOONGARCH_BASE_ABI_LP64D (0x3) +-# READOBJ-LP64D-NEXT: ] +- +-# READOBJ-ILP32S: Flags [ (0x5) +-# READOBJ-ILP32S-NEXT: EF_LOONGARCH_BASE_ABI_ILP32S (0x5) +-# READOBJ-ILP32S-NEXT: ] +- +-# READOBJ-ILP32F: Flags [ (0x6) +-# READOBJ-ILP32F-NEXT: EF_LOONGARCH_BASE_ABI_ILP32F (0x6) +-# READOBJ-ILP32F-NEXT: ] +- +-# READOBJ-ILP32D: Flags [ (0x7) +-# READOBJ-ILP32D-NEXT: EF_LOONGARCH_BASE_ABI_ILP32D (0x7) +-# READOBJ-ILP32D-NEXT: ] +- +-# READELF-LP64S: Flags: 0x1, LP64, SOFT-FLOAT +-# READELF-LP64F: Flags: 0x2, LP64, SINGLE-FLOAT +-# READELF-LP64D: Flags: 0x3, LP64, DOUBLE-FLOAT +-# READELF-ILP32S: Flags: 0x5, ILP32, SOFT-FLOAT +-# READELF-ILP32F: Flags: 0x6, ILP32, SINGLE-FLOAT +-# READELF-ILP32D: Flags: 0x7, ILP32, DOUBLE-FLOAT +- +---- !ELF +-FileHeader: +- Class: ELFCLASS[[CLASS]] +- Data: ELFDATA2LSB +- Type: ET_EXEC +- Machine: EM_LOONGARCH +- Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] +diff --git a/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml b/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml +deleted file mode 100644 +index e4c4c292e..000000000 +--- a/src/llvm-project/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml ++++ /dev/null +@@ -1,29 +0,0 @@ +-## Check obj2yaml is able to decode all possible LoongArch e_flags field values. +- +-# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S +-# RUN: obj2yaml %t-lp64s | FileCheck -DFLAG=LP64S %s +- +-# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F +-# RUN: obj2yaml %t-lp64f | FileCheck -DFLAG=LP64F %s +- +-# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D +-# RUN: obj2yaml %t-lp64d | FileCheck -DFLAG=LP64D %s +- +-# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S +-# RUN: obj2yaml %t-ilp32s | FileCheck -DFLAG=ILP32S %s +- +-# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F +-# RUN: obj2yaml %t-ilp32f | FileCheck -DFLAG=ILP32F %s +- +-# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D +-# RUN: obj2yaml %t-ilp32d | FileCheck -DFLAG=ILP32D %s +- +-# CHECK: Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] +- +---- !ELF +-FileHeader: +- Class: ELFCLASS[[CLASS]] +- Data: ELFDATA2LSB +- Type: ET_EXEC +- Machine: EM_LOONGARCH +- Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] +diff --git a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt +index a255c1c5d..38028cd3d 100644 +--- a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt ++++ b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt +@@ -40,6 +40,4 @@ if(APPLE) + target_link_libraries(dsymutil PRIVATE "-framework CoreFoundation") + endif(APPLE) + +-if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB) +- target_link_libraries(dsymutil PRIVATE atomic) +-endif() ++target_link_libraries(dsymutil PRIVATE ${LLVM_ATOMIC_LIB}) +diff --git a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt +index aa5aa2025..6faee031a 100644 +--- a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt ++++ b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt +@@ -17,9 +17,14 @@ add_llvm_tool(llvm-config + # Compute the substitution values for various items. + get_property(SUPPORT_SYSTEM_LIBS TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) + get_property(WINDOWSMANIFEST_SYSTEM_LIBS TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS) ++ + foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) + if(MSVC) +- set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") ++ if(IS_ABSOLUTE ${l}) ++ set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}") ++ else() ++ set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") ++ endif() + else() + if (l MATCHES "^-") + # If it's an option, pass it without changes. +@@ -34,6 +39,7 @@ foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) + endif() + endif() + endforeach() ++ + string(REPLACE ";" " " SYSTEM_LIBS "${SYSTEM_LIBS}") + + # Fetch target specific compile options, e.g. RTTI option +diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp +index ba7bae96a..ae2dec5d1 100644 +--- a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp ++++ b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp +@@ -1648,15 +1648,6 @@ const EnumEntry ElfHeaderAVRFlags[] = { + ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"), + }; + +-const EnumEntry ElfHeaderLoongArchFlags[] = { +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32S, "ILP32, SOFT-FLOAT"), +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32F, "ILP32, SINGLE-FLOAT"), +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32D, "ILP32, DOUBLE-FLOAT"), +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64S, "LP64, SOFT-FLOAT"), +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64F, "LP64, SINGLE-FLOAT"), +- ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64D, "LP64, DOUBLE-FLOAT"), +-}; +- + + const EnumEntry ElfSymOtherFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), +@@ -3366,9 +3357,6 @@ template void GNUELFDumper::printFileHeaders() { + else if (e.e_machine == EM_AVR) + ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderAVRFlags), + unsigned(ELF::EF_AVR_ARCH_MASK)); +- else if (e.e_machine == EM_LOONGARCH) +- ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), +- unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); + Str = "0x" + utohexstr(e.e_flags); + if (!ElfFlags.empty()) + Str = Str + ", " + ElfFlags; +@@ -6519,9 +6507,6 @@ template void LLVMELFDumper::printFileHeaders() { + else if (E.e_machine == EM_AVR) + W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAVRFlags), + unsigned(ELF::EF_AVR_ARCH_MASK)); +- else if (E.e_machine == EM_LOONGARCH) +- W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), +- unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); + else + W.printFlags("Flags", E.e_flags); + W.printNumber("HeaderSize", E.e_ehsize); +diff --git a/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn b/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn +index c8506d9ef..7431a507c 100644 +--- a/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn ++++ b/src/llvm-project/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/misc/BUILD.gn +@@ -1,7 +1,7 @@ + import("//llvm/utils/gn/build/compiled_action.gni") + + compiled_action("Confusables.inc") { +- tool = "ConfusableTable:make-confusable-table" ++ tool = "ConfusableTable:clang-tidy-confusable-chars-gen" + inputs = [ "ConfusableTable/confusables.txt" ] + outputs = [ "$target_gen_dir/$target_name" ] + args = [ +diff --git a/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni b/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni +index ac79ba5bb..d485a133f 100644 +--- a/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni ++++ b/src/llvm-project/llvm/utils/gn/secondary/llvm/version.gni +@@ -1,4 +1,4 @@ + llvm_version_major = 15 + llvm_version_minor = 0 +-llvm_version_patch = 2 ++llvm_version_patch = 7 + llvm_version = "$llvm_version_major.$llvm_version_minor.$llvm_version_patch" +diff --git a/src/llvm-project/llvm/utils/lit/lit/__init__.py b/src/llvm-project/llvm/utils/lit/lit/__init__.py +index 2ee97f578..928d6db8d 100644 +--- a/src/llvm-project/llvm/utils/lit/lit/__init__.py ++++ b/src/llvm-project/llvm/utils/lit/lit/__init__.py +@@ -2,7 +2,7 @@ + + __author__ = 'Daniel Dunbar' + __email__ = 'daniel@minormatter.com' +-__versioninfo__ = (15, 0, 2) ++__versioninfo__ = (15, 0, 7) + __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' + + __all__ = [] +diff --git a/src/llvm-project/llvm/utils/lit/lit/llvm/config.py b/src/llvm-project/llvm/utils/lit/lit/llvm/config.py +index b65316128..7dae83733 100644 +--- a/src/llvm-project/llvm/utils/lit/lit/llvm/config.py ++++ b/src/llvm-project/llvm/utils/lit/lit/llvm/config.py +@@ -609,7 +609,7 @@ class LLVMConfig(object): + self.with_environment('PATH', paths, append_path=True) + + lib_dir_props = [self.config.name.lower() + '_libs_dir', +- 'lld_libs_dir', 'llvm_libs_dir'] ++ 'lld_libs_dir', 'llvm_shlib_dir', 'llvm_libs_dir'] + lib_paths = [getattr(self.config, pp) for pp in lib_dir_props + if getattr(self.config, pp, None)] + +-- +2.41.0 + diff --git a/0006-rust-add-loongarch64-support.patch b/0006-rust-add-loongarch64-support.patch new file mode 100644 index 0000000..2b91418 --- /dev/null +++ b/0006-rust-add-loongarch64-support.patch @@ -0,0 +1,1691 @@ +From d81a20d98d9fd47edb762a1716b65d4bfeffae60 Mon Sep 17 00:00:00 2001 +From: WANG Rui +Date: Wed, 26 Apr 2023 14:26:58 +0800 +Subject: [PATCH 6/6] rust: add loongarch64 support + +--- + compiler/rustc_ast_lowering/src/asm.rs | 1 + + .../rustc_codegen_gcc/example/alloc_system.rs | 1 + + compiler/rustc_codegen_gcc/src/asm.rs | 5 + + compiler/rustc_codegen_llvm/src/asm.rs | 17 + + .../rustc_codegen_ssa/src/back/metadata.rs | 6 + + .../rustc_codegen_ssa/src/target_features.rs | 6 + + compiler/rustc_feature/src/active.rs | 1 + + compiler/rustc_hir_analysis/src/collect.rs | 1 + + compiler/rustc_llvm/build.rs | 3 +- + .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 + + compiler/rustc_llvm/src/lib.rs | 8 + + compiler/rustc_span/src/symbol.rs | 1 + + .../rustc_target/src/abi/call/loongarch.rs | 342 ++++++++++++++++++ + compiler/rustc_target/src/abi/call/mod.rs | 2 + + compiler/rustc_target/src/asm/loongarch.rs | 131 +++++++ + compiler/rustc_target/src/asm/mod.rs | 44 +++ + .../src/spec/loongarch64_unknown_linux_gnu.rs | 18 + + compiler/rustc_target/src/spec/mod.rs | 2 + + library/std/src/env.rs | 1 + + library/std/src/os/linux/raw.rs | 1 + + library/std/src/personality/gcc.rs | 3 + + library/std/src/sys/common/alloc.rs | 1 + + library/unwind/src/libunwind.rs | 3 + + src/bootstrap/bootstrap.py | 1 + + src/bootstrap/lib.rs | 2 +- + src/bootstrap/native.rs | 2 +- + src/ci/github-actions/ci.yml | 3 + + src/doc/rustc/src/platform-support.md | 1 + + src/librustdoc/clean/cfg.rs | 1 + + src/test/assembly/asm/loongarch-types.rs | 194 ++++++++++ + .../codegen/abi-main-signature-16bit-c-int.rs | 1 + + src/test/codegen/call-llvm-intrinsics.rs | 1 + + src/test/codegen/global_asm.rs | 1 + + src/test/codegen/global_asm_include.rs | 1 + + src/test/codegen/global_asm_x2.rs | 1 + + .../loongarch-abi/call-llvm-intrinsics.rs | 30 ++ + .../codegen/repr-transparent-aggregates-1.rs | 1 + + .../codegen/repr-transparent-aggregates-2.rs | 1 + + src/test/codegen/repr-transparent.rs | 1 + + .../atomic-lock-free/Makefile | 4 + + src/test/ui/abi/stack-probes-lto.rs | 1 + + src/test/ui/cfg/conditional-compile-arch.rs | 3 + + src/test/ui/check-cfg/compact-values.stderr | 2 +- + src/test/ui/process/nofile-limit.rs | 3 +- + src/test/ui/target-feature/gate.rs | 2 + + .../ui/target-feature/invalid-attribute.rs | 1 + + src/tools/build-manifest/src/main.rs | 2 + + src/tools/clippy/tests/ui/asm_syntax.rs | 1 + + src/tools/compiletest/src/common.rs | 2 +- + 49 files changed, 862 insertions(+), 6 deletions(-) + create mode 100644 compiler/rustc_target/src/abi/call/loongarch.rs + create mode 100644 compiler/rustc_target/src/asm/loongarch.rs + create mode 100644 compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs + create mode 100644 src/test/assembly/asm/loongarch-types.rs + create mode 100644 src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs + +diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs +index 450cdf246..260a0b24b 100644 +--- a/compiler/rustc_ast_lowering/src/asm.rs ++++ b/compiler/rustc_ast_lowering/src/asm.rs +@@ -44,6 +44,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { + | asm::InlineAsmArch::AArch64 + | asm::InlineAsmArch::RiscV32 + | asm::InlineAsmArch::RiscV64 ++ | asm::InlineAsmArch::LoongArch64 + ); + if !is_stable && !self.tcx.features().asm_experimental_arch { + feature_err( +diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs +index 89661918d..df960c4b8 100644 +--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs ++++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs +@@ -21,6 +21,7 @@ + const MIN_ALIGN: usize = 8; + #[cfg(all(any(target_arch = "x86_64", + target_arch = "aarch64", ++ target_arch = "loongarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64")))] +diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs +index c346dbd63..58563ac9a 100644 +--- a/compiler/rustc_codegen_gcc/src/asm.rs ++++ b/compiler/rustc_codegen_gcc/src/asm.rs +@@ -582,6 +582,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { + InlineAsmRegClass::Avr(_) => unimplemented!(), + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(), ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => unimplemented!(), ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::Msp430(_) => unimplemented!(), +@@ -646,6 +648,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl + InlineAsmRegClass::Avr(_) => unimplemented!(), + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Msp430(_) => unimplemented!(), +@@ -773,6 +777,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option + InlineAsmRegClass::Avr(_) => unimplemented!(), + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(_) => unimplemented!(), ++ InlineAsmRegClass::LoongArch(_) => unimplemented!(), + InlineAsmRegClass::Mips(_) => unimplemented!(), + InlineAsmRegClass::Msp430(_) => unimplemented!(), + InlineAsmRegClass::Nvptx(_) => unimplemented!(), +diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs +index 017513721..2d380f1c4 100644 +--- a/compiler/rustc_codegen_llvm/src/asm.rs ++++ b/compiler/rustc_codegen_llvm/src/asm.rs +@@ -235,6 +235,18 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { + InlineAsmArch::Msp430 => { + constraints.push("~{sr}".to_string()); + } ++ InlineAsmArch::LoongArch64 => { ++ constraints.extend_from_slice(&[ ++ "~{$fcc0}".to_string(), ++ "~{$fcc1}".to_string(), ++ "~{$fcc2}".to_string(), ++ "~{$fcc3}".to_string(), ++ "~{$fcc4}".to_string(), ++ "~{$fcc5}".to_string(), ++ "~{$fcc6}".to_string(), ++ "~{$fcc7}".to_string(), ++ ]); ++ } + } + } + if !options.contains(InlineAsmOptions::NOMEM) { +@@ -614,6 +626,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Err => unreachable!(), + } + .to_string(), +@@ -708,6 +722,7 @@ fn modifier_to_llvm( + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } ++ InlineAsmRegClass::LoongArch(_) => None, + InlineAsmRegClass::Err => unreachable!(), + } + } +@@ -782,6 +797,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), ++ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Err => unreachable!(), + } + } +diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs +index 99ddd1764..ae639d064 100644 +--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs ++++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs +@@ -121,6 +121,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Architecture::Msp430, + "hexagon" => Architecture::Hexagon, + "bpf" => Architecture::Bpf, ++ "loongarch64" => Architecture::LoongArch64, + // Unsupported architecture. + _ => return None, + }; +@@ -172,6 +173,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option { ++ // copied from `loongarch64-linux-gnu-gcc foo.c -c` ++ let e_flags = elf::EF_LARCH_ABI; ++ e_flags ++ } + _ => 0, + }; + // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` +diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs +index 83407ee8f..93d5b79c4 100644 +--- a/compiler/rustc_codegen_ssa/src/target_features.rs ++++ b/compiler/rustc_codegen_ssa/src/target_features.rs +@@ -209,6 +209,10 @@ const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-end + ]; + ++const LOONGARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ ++ ("fp64", Some(sym::loongarch64_target_feature)), ++]; ++ + const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-start + ("altivec", Some(sym::powerpc_target_feature)), +@@ -292,6 +296,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Opt + "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, + "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, + "bpf" => BPF_ALLOWED_FEATURES, ++ "loongarch64" => LOONGARCH64_ALLOWED_FEATURES, + _ => &[], + } + } +diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs +index 647ccdec7..546a24164 100644 +--- a/compiler/rustc_feature/src/active.rs ++++ b/compiler/rustc_feature/src/active.rs +@@ -254,6 +254,7 @@ declare_features! ( + (active, ermsb_target_feature, "1.49.0", Some(44839), None), + (active, f16c_target_feature, "1.36.0", Some(44839), None), + (active, hexagon_target_feature, "1.27.0", Some(44839), None), ++ (active, loongarch64_target_feature, "1.57.0", Some(44839), None), + (active, mips_target_feature, "1.27.0", Some(44839), None), + (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, powerpc_target_feature, "1.27.0", Some(44839), None), +diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs +index 346d2e2fc..083f661c8 100644 +--- a/compiler/rustc_hir_analysis/src/collect.rs ++++ b/compiler/rustc_hir_analysis/src/collect.rs +@@ -1538,6 +1538,7 @@ fn from_target_feature( + let allowed = match feature_gate.as_ref().copied() { + Some(sym::arm_target_feature) => rust_features.arm_target_feature, + Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, ++ Some(sym::loongarch64_target_feature) => rust_features.loongarch64_target_feature, + Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, + Some(sym::mips_target_feature) => rust_features.mips_target_feature, + Some(sym::riscv_target_feature) => rust_features.riscv_target_feature, +diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs +index 28e092c1e..c0c60bc0c 100644 +--- a/compiler/rustc_llvm/build.rs ++++ b/compiler/rustc_llvm/build.rs +@@ -10,6 +10,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[ + "aarch64", + "amdgpu", + "avr", ++ "loongarch", + "m68k", + "mips", + "powerpc", +@@ -240,7 +241,7 @@ fn main() { + } else if target.contains("windows-gnu") { + println!("cargo:rustc-link-lib=shell32"); + println!("cargo:rustc-link-lib=uuid"); +- } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") { ++ } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") || target.contains("loongarch") { + println!("cargo:rustc-link-lib=z"); + } else if target.starts_with("arm") + || target.starts_with("mips-") +diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +index 18d37d95a..ac91ee420 100644 +--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp ++++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +@@ -166,6 +166,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { + #define SUBTARGET_HEXAGON + #endif + ++#ifdef LLVM_COMPONENT_LOONGARCH ++#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch) ++#else ++#define SUBTARGET_LOONGARCH ++#endif ++ + #define GEN_SUBTARGETS \ + SUBTARGET_X86 \ + SUBTARGET_ARM \ +@@ -179,6 +185,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { + SUBTARGET_SPARC \ + SUBTARGET_HEXAGON \ + SUBTARGET_RISCV \ ++ SUBTARGET_LOONGARCH \ + + #define SUBTARGET(x) \ + namespace llvm { \ +diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs +index 8542dcf5b..06351731b 100644 +--- a/compiler/rustc_llvm/src/lib.rs ++++ b/compiler/rustc_llvm/src/lib.rs +@@ -102,6 +102,14 @@ pub fn initialize_available_targets() { + LLVMInitializeM68kAsmPrinter, + LLVMInitializeM68kAsmParser + ); ++ init_target!( ++ llvm_component = "loongarch", ++ LLVMInitializeLoongArchTargetInfo, ++ LLVMInitializeLoongArchTarget, ++ LLVMInitializeLoongArchTargetMC, ++ LLVMInitializeLoongArchAsmPrinter, ++ LLVMInitializeLoongArchAsmParser ++ ); + init_target!( + llvm_component = "mips", + LLVMInitializeMipsTargetInfo, +diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs +index 7f16da52b..b0c040f72 100644 +--- a/compiler/rustc_span/src/symbol.rs ++++ b/compiler/rustc_span/src/symbol.rs +@@ -900,6 +900,7 @@ symbols! { + log_syntax, + logf32, + logf64, ++ loongarch64_target_feature, + loop_break_value, + lt, + macro_at_most_once_rep, +diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs +new file mode 100644 +index 000000000..018fe7d15 +--- /dev/null ++++ b/compiler/rustc_target/src/abi/call/loongarch.rs +@@ -0,0 +1,342 @@ ++use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; ++use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; ++use crate::spec::HasTargetSpec; ++ ++#[derive(Copy, Clone)] ++enum RegPassKind { ++ Float(Reg), ++ Integer(Reg), ++ Unknown, ++} ++ ++#[derive(Copy, Clone)] ++enum FloatConv { ++ FloatPair(Reg, Reg), ++ Float(Reg), ++ MixedPair(Reg, Reg), ++} ++ ++#[derive(Copy, Clone)] ++struct CannotUseFpConv; ++ ++fn is_loongarch_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool { ++ match arg.layout.abi { ++ Abi::Vector { .. } => true, ++ _ => arg.layout.is_aggregate(), ++ } ++} ++ ++fn should_use_fp_conv_helper<'a, Ty, C>( ++ cx: &C, ++ arg_layout: &TyAndLayout<'a, Ty>, ++ xlen: u64, ++ flen: u64, ++ field1_kind: &mut RegPassKind, ++ field2_kind: &mut RegPassKind, ++) -> Result<(), CannotUseFpConv> ++where ++ Ty: TyAbiInterface<'a, C> + Copy, ++{ ++ match arg_layout.abi { ++ Abi::Scalar(scalar) => match scalar.primitive() { ++ abi::Int(..) | abi::Pointer => { ++ if arg_layout.size.bits() > xlen { ++ return Err(CannotUseFpConv); ++ } ++ match (*field1_kind, *field2_kind) { ++ (RegPassKind::Unknown, _) => { ++ *field1_kind = RegPassKind::Integer(Reg { ++ kind: RegKind::Integer, ++ size: arg_layout.size, ++ }); ++ } ++ (RegPassKind::Float(_), RegPassKind::Unknown) => { ++ *field2_kind = RegPassKind::Integer(Reg { ++ kind: RegKind::Integer, ++ size: arg_layout.size, ++ }); ++ } ++ _ => return Err(CannotUseFpConv), ++ } ++ } ++ abi::F32 | abi::F64 => { ++ if arg_layout.size.bits() > flen { ++ return Err(CannotUseFpConv); ++ } ++ match (*field1_kind, *field2_kind) { ++ (RegPassKind::Unknown, _) => { ++ *field1_kind = ++ RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); ++ } ++ (_, RegPassKind::Unknown) => { ++ *field2_kind = ++ RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); ++ } ++ _ => return Err(CannotUseFpConv), ++ } ++ } ++ }, ++ Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv), ++ Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields { ++ FieldsShape::Primitive => { ++ unreachable!("aggregates can't have `FieldsShape::Primitive`") ++ } ++ FieldsShape::Union(_) => { ++ if !arg_layout.is_zst() { ++ return Err(CannotUseFpConv); ++ } ++ } ++ FieldsShape::Array { count, .. } => { ++ for _ in 0..count { ++ let elem_layout = arg_layout.field(cx, 0); ++ should_use_fp_conv_helper( ++ cx, ++ &elem_layout, ++ xlen, ++ flen, ++ field1_kind, ++ field2_kind, ++ )?; ++ } ++ } ++ FieldsShape::Arbitrary { .. } => { ++ match arg_layout.variants { ++ abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), ++ abi::Variants::Single { .. } => (), ++ } ++ for i in arg_layout.fields.index_by_increasing_offset() { ++ let field = arg_layout.field(cx, i); ++ should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; ++ } ++ } ++ }, ++ } ++ Ok(()) ++} ++ ++fn should_use_fp_conv<'a, Ty, C>( ++ cx: &C, ++ arg: &TyAndLayout<'a, Ty>, ++ xlen: u64, ++ flen: u64, ++) -> Option ++where ++ Ty: TyAbiInterface<'a, C> + Copy, ++{ ++ let mut field1_kind = RegPassKind::Unknown; ++ let mut field2_kind = RegPassKind::Unknown; ++ if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { ++ return None; ++ } ++ match (field1_kind, field2_kind) { ++ (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), ++ (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), ++ (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), ++ (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), ++ _ => None, ++ } ++} ++ ++fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool ++where ++ Ty: TyAbiInterface<'a, C> + Copy, ++{ ++ if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) { ++ match conv { ++ FloatConv::Float(f) => { ++ arg.cast_to(f); ++ } ++ FloatConv::FloatPair(l, r) => { ++ arg.cast_to(CastTarget::pair(l, r)); ++ } ++ FloatConv::MixedPair(l, r) => { ++ arg.cast_to(CastTarget::pair(l, r)); ++ } ++ } ++ return false; ++ } ++ ++ let total = arg.layout.size; ++ ++ // "Scalars wider than 2✕XLEN are passed by reference and are replaced in ++ // the argument list with the address." ++ // "Aggregates larger than 2✕XLEN bits are passed by reference and are ++ // replaced in the argument list with the address, as are C++ aggregates ++ // with nontrivial copy constructors, destructors, or vtables." ++ if total.bits() > 2 * xlen { ++ // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. ++ if is_loongarch_aggregate(arg) { ++ arg.make_indirect(); ++ } ++ return true; ++ } ++ ++ let xlen_reg = match xlen { ++ 32 => Reg::i32(), ++ 64 => Reg::i64(), ++ _ => unreachable!("Unsupported XLEN: {}", xlen), ++ }; ++ if is_loongarch_aggregate(arg) { ++ if total.bits() <= xlen { ++ arg.cast_to(xlen_reg); ++ } else { ++ arg.cast_to(Uniform { unit: xlen_reg, total: Size::from_bits(xlen * 2) }); ++ } ++ return false; ++ } ++ ++ // "When passed in registers, scalars narrower than XLEN bits are widened ++ // according to the sign of their type up to 32 bits, then sign-extended to ++ // XLEN bits." ++ extend_integer_width(arg, xlen); ++ false ++} ++ ++fn classify_arg<'a, Ty, C>( ++ cx: &C, ++ arg: &mut ArgAbi<'a, Ty>, ++ xlen: u64, ++ flen: u64, ++ is_vararg: bool, ++ avail_gprs: &mut u64, ++ avail_fprs: &mut u64, ++) where ++ Ty: TyAbiInterface<'a, C> + Copy, ++{ ++ if !is_vararg { ++ match should_use_fp_conv(cx, &arg.layout, xlen, flen) { ++ Some(FloatConv::Float(f)) if *avail_fprs >= 1 => { ++ *avail_fprs -= 1; ++ arg.cast_to(f); ++ return; ++ } ++ Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { ++ *avail_fprs -= 2; ++ arg.cast_to(CastTarget::pair(l, r)); ++ return; ++ } ++ Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { ++ *avail_gprs -= 1; ++ *avail_fprs -= 1; ++ arg.cast_to(CastTarget::pair(l, r)); ++ return; ++ } ++ _ => (), ++ } ++ } ++ ++ let total = arg.layout.size; ++ let align = arg.layout.align.abi.bits(); ++ ++ // "Scalars wider than 2✕XLEN are passed by reference and are replaced in ++ // the argument list with the address." ++ // "Aggregates larger than 2✕XLEN bits are passed by reference and are ++ // replaced in the argument list with the address, as are C++ aggregates ++ // with nontrivial copy constructors, destructors, or vtables." ++ if total.bits() > 2 * xlen { ++ // We rely on the LLVM backend lowering code to lower passing a scalar larger than 2*XLEN. ++ if is_loongarch_aggregate(arg) { ++ arg.make_indirect(); ++ } ++ if *avail_gprs >= 1 { ++ *avail_gprs -= 1; ++ } ++ return; ++ } ++ ++ let double_xlen_reg = match xlen { ++ 32 => Reg::i64(), ++ 64 => Reg::i128(), ++ _ => unreachable!("Unsupported XLEN: {}", xlen), ++ }; ++ ++ let xlen_reg = match xlen { ++ 32 => Reg::i32(), ++ 64 => Reg::i64(), ++ _ => unreachable!("Unsupported XLEN: {}", xlen), ++ }; ++ ++ if total.bits() > xlen { ++ let align_regs = align > xlen; ++ if is_loongarch_aggregate(arg) { ++ arg.cast_to(Uniform { ++ unit: if align_regs { double_xlen_reg } else { xlen_reg }, ++ total: Size::from_bits(xlen * 2), ++ }); ++ } ++ if align_regs && is_vararg { ++ *avail_gprs -= *avail_gprs % 2; ++ } ++ if *avail_gprs >= 2 { ++ *avail_gprs -= 2; ++ } else { ++ *avail_gprs = 0; ++ } ++ return; ++ } else if is_loongarch_aggregate(arg) { ++ arg.cast_to(xlen_reg); ++ if *avail_gprs >= 1 { ++ *avail_gprs -= 1; ++ } ++ return; ++ } ++ ++ // "When passed in registers, scalars narrower than XLEN bits are widened ++ // according to the sign of their type up to 32 bits, then sign-extended to ++ // XLEN bits." ++ if *avail_gprs >= 1 { ++ extend_integer_width(arg, xlen); ++ *avail_gprs -= 1; ++ } ++} ++ ++fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { ++ if let Abi::Scalar(scalar) = arg.layout.abi { ++ if let abi::Int(i, _) = scalar.primitive() { ++ // 32-bit integers are always sign-extended ++ if i.size().bits() == 32 && xlen > 32 { ++ if let PassMode::Direct(ref mut attrs) = arg.mode { ++ attrs.ext(ArgExtension::Sext); ++ return; ++ } ++ } ++ } ++ } ++ ++ arg.extend_integer_width_to(xlen); ++} ++ ++pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) ++where ++ Ty: TyAbiInterface<'a, C> + Copy, ++ C: HasDataLayout + HasTargetSpec, ++{ ++ let xlen = cx.data_layout().pointer_size.bits(); ++ let flen = match &cx.target_spec().llvm_abiname[..] { ++ "lp64" => 64, ++ "lp32" | "lpx32" => 32, ++ _ => 0, ++ }; ++ ++ let mut avail_gprs = 8; ++ let mut avail_fprs = 8; ++ ++ if !fn_abi.ret.is_ignore() && classify_ret(cx, &mut fn_abi.ret, xlen, flen) { ++ avail_gprs -= 1; ++ } ++ ++ for (i, arg) in fn_abi.args.iter_mut().enumerate() { ++ if arg.is_ignore() { ++ continue; ++ } ++ classify_arg( ++ cx, ++ arg, ++ xlen, ++ flen, ++ i >= fn_abi.fixed_count as usize, ++ &mut avail_gprs, ++ &mut avail_fprs, ++ ); ++ } ++} +diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs +index 9e5f0e4d1..c5a6f9893 100644 +--- a/compiler/rustc_target/src/abi/call/mod.rs ++++ b/compiler/rustc_target/src/abi/call/mod.rs +@@ -10,6 +10,7 @@ mod arm; + mod avr; + mod bpf; + mod hexagon; ++mod loongarch; + mod m68k; + mod mips; + mod mips64; +@@ -696,6 +697,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { + "amdgpu" => amdgpu::compute_abi_info(cx, self), + "arm" => arm::compute_abi_info(cx, self), + "avr" => avr::compute_abi_info(self), ++ "loongarch64" => loongarch::compute_abi_info(cx, self), + "m68k" => m68k::compute_abi_info(self), + "mips" => mips::compute_abi_info(cx, self), + "mips64" => mips64::compute_abi_info(cx, self), +diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs +new file mode 100644 +index 000000000..f1b879662 +--- /dev/null ++++ b/compiler/rustc_target/src/asm/loongarch.rs +@@ -0,0 +1,131 @@ ++use super::{InlineAsmArch, InlineAsmType}; ++use rustc_macros::HashStable_Generic; ++use rustc_span::Symbol; ++use std::fmt; ++ ++def_reg_class! { ++ LoongArch LoongArchInlineAsmRegClass { ++ reg, ++ freg, ++ } ++} ++ ++impl LoongArchInlineAsmRegClass { ++ pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { ++ &[] ++ } ++ ++ pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { ++ None ++ } ++ ++ pub fn suggest_modifier( ++ self, ++ _arch: InlineAsmArch, ++ _ty: InlineAsmType, ++ ) -> Option<(char, &'static str)> { ++ None ++ } ++ ++ pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { ++ None ++ } ++ ++ pub fn supported_types( ++ self, ++ arch: InlineAsmArch, ++ ) -> &'static [(InlineAsmType, Option)] { ++ match (self, arch) { ++ (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; }, ++ (Self::reg, _) => types! { _: I8, I16, I32, F32; }, ++ (Self::freg, _) => types! { _: F32, F64; }, ++ } ++ } ++} ++ ++// The reserved registers are taken from ++def_regs! { ++ LoongArch LoongArchInlineAsmReg LoongArchInlineAsmRegClass { ++ r1: reg = ["$r1","$ra"], ++ r4: reg = ["$r4","$a0"], ++ r5: reg = ["$r5","$a1"], ++ r6: reg = ["$r6","$a2"], ++ r7: reg = ["$r7","$a3"], ++ r8: reg = ["$r8","$a4"], ++ r9: reg = ["$r9","$a5"], ++ r10: reg = ["$r10","$a6"], ++ r11: reg = ["$r11","$a7"], ++ r12: reg = ["$r12","$t0"], ++ r13: reg = ["$r13","$t1"], ++ r14: reg = ["$r14","$t2"], ++ r15: reg = ["$r15","$t3"], ++ r16: reg = ["$r16","$t4"], ++ r17: reg = ["$r17","$t5"], ++ r18: reg = ["$r18","$t6"], ++ r19: reg = ["$r19","$t7"], ++ r20: reg = ["$r20","$t8"], ++ r23: reg = ["$r23","$s0"], ++ r24: reg = ["$r24","$s1"], ++ r25: reg = ["$r25","$s2"], ++ r26: reg = ["$r26","$s3"], ++ r27: reg = ["$r27","$s4"], ++ r28: reg = ["$r28","$s5"], ++ r29: reg = ["$r29","$s6"], ++ r30: reg = ["$r30","$s7"], ++ f0: freg = ["$f0","$fa0"], ++ f1: freg = ["$f1","$fa1"], ++ f2: freg = ["$f2","$fa2"], ++ f3: freg = ["$f3","$fa3"], ++ f4: freg = ["$f4","$fa4"], ++ f5: freg = ["$f5","$fa5"], ++ f6: freg = ["$f6","$fa6"], ++ f7: freg = ["$f7","$fa7"], ++ f8: freg = ["$f8","$ft0"], ++ f9: freg = ["$f9","$ft1"], ++ f10: freg = ["$f10","$ft2"], ++ f11: freg = ["$f11","$ft3"], ++ f12: freg = ["$f12","$ft4"], ++ f13: freg = ["$f13","$ft5"], ++ f14: freg = ["$f14","$ft6"], ++ f15: freg = ["$f15","$ft7"], ++ f16: freg = ["$f16","$ft8"], ++ f17: freg = ["$f17","$ft9"], ++ f18: freg = ["$f18","$ft10"], ++ f19: freg = ["$f19","$ft11"], ++ f20: freg = ["$f20","$ft12"], ++ f21: freg = ["$f21","$ft13"], ++ f22: freg = ["$f22","$ft14"], ++ f23: freg = ["$f23","$ft15"], ++ f24: freg = ["$f24","$fs0"], ++ f25: freg = ["$f25","$fs1"], ++ f26: freg = ["$f26","$fs2"], ++ f27: freg = ["$f27","$fs3"], ++ f28: freg = ["$f28","$fs4"], ++ f29: freg = ["$f29","$fs5"], ++ f30: freg = ["$f30","$fs6"], ++ f31: freg = ["$f31","$fs7"], ++ #error = ["$r0", "$zero"] => ++ "constant zero cannot be used as an operand for inline asm", ++ #error = ["$r2", "$tp"] => ++ "reserved for TLS", ++ #error = ["$r3", "$sp"] => ++ "the stack pointer cannot be used as an operand for inline asm", ++ #error = ["$r21", "$x"] => ++ "reserved for ABI extension", ++ #error = ["$r22", "$fp"] => ++ "the frame pointer cannot be used as an operand for inline asm", ++ #error = ["$r31", "$s8"] => ++ "r31 is used internally by LLVM and cannot be used as an operand for inline asm", ++ } ++} ++ ++impl LoongArchInlineAsmReg { ++ pub fn emit( ++ self, ++ out: &mut dyn fmt::Write, ++ _arch: InlineAsmArch, ++ _modifier: Option, ++ ) -> fmt::Result { ++ out.write_str(self.name()) ++ } ++} +diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs +index 65d2cd64b..2438ac3e8 100644 +--- a/compiler/rustc_target/src/asm/mod.rs ++++ b/compiler/rustc_target/src/asm/mod.rs +@@ -167,6 +167,7 @@ mod arm; + mod avr; + mod bpf; + mod hexagon; ++mod loongarch; + mod mips; + mod msp430; + mod nvptx; +@@ -182,6 +183,7 @@ pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; + pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; + pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; + pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; ++pub use loongarch::{LoongArchInlineAsmReg, LoongArchInlineAsmRegClass}; + pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; + pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}; + pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; +@@ -213,6 +215,7 @@ pub enum InlineAsmArch { + Bpf, + Avr, + Msp430, ++ LoongArch64, + } + + impl FromStr for InlineAsmArch { +@@ -230,6 +233,7 @@ impl FromStr for InlineAsmArch { + "powerpc" => Ok(Self::PowerPC), + "powerpc64" => Ok(Self::PowerPC64), + "hexagon" => Ok(Self::Hexagon), ++ "loongarch64" => Ok(Self::LoongArch64), + "mips" => Ok(Self::Mips), + "mips64" => Ok(Self::Mips64), + "s390x" => Ok(Self::S390x), +@@ -254,6 +258,7 @@ pub enum InlineAsmReg { + Nvptx(NvptxInlineAsmReg), + PowerPC(PowerPCInlineAsmReg), + Hexagon(HexagonInlineAsmReg), ++ LoongArch(LoongArchInlineAsmReg), + Mips(MipsInlineAsmReg), + S390x(S390xInlineAsmReg), + SpirV(SpirVInlineAsmReg), +@@ -274,6 +279,7 @@ impl InlineAsmReg { + Self::RiscV(r) => r.name(), + Self::PowerPC(r) => r.name(), + Self::Hexagon(r) => r.name(), ++ Self::LoongArch(r) => r.name(), + Self::Mips(r) => r.name(), + Self::S390x(r) => r.name(), + Self::Bpf(r) => r.name(), +@@ -291,6 +297,7 @@ impl InlineAsmReg { + Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), + Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), + Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), ++ Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()), + Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), + Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), + Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), +@@ -316,6 +323,7 @@ impl InlineAsmReg { + Self::PowerPC(PowerPCInlineAsmReg::parse(name)?) + } + InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?), ++ InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmReg::parse(name)?), + InlineAsmArch::Mips | InlineAsmArch::Mips64 => { + Self::Mips(MipsInlineAsmReg::parse(name)?) + } +@@ -345,6 +353,7 @@ impl InlineAsmReg { + Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), ++ Self::LoongArch(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), +@@ -369,6 +378,7 @@ impl InlineAsmReg { + Self::RiscV(r) => r.emit(out, arch, modifier), + Self::PowerPC(r) => r.emit(out, arch, modifier), + Self::Hexagon(r) => r.emit(out, arch, modifier), ++ Self::LoongArch(r) => r.emit(out, arch, modifier), + Self::Mips(r) => r.emit(out, arch, modifier), + Self::S390x(r) => r.emit(out, arch, modifier), + Self::Bpf(r) => r.emit(out, arch, modifier), +@@ -386,6 +396,7 @@ impl InlineAsmReg { + Self::RiscV(_) => cb(self), + Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), + Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), ++ Self::LoongArch(_) => cb(self), + Self::Mips(_) => cb(self), + Self::S390x(_) => cb(self), + Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), +@@ -406,6 +417,7 @@ pub enum InlineAsmRegClass { + Nvptx(NvptxInlineAsmRegClass), + PowerPC(PowerPCInlineAsmRegClass), + Hexagon(HexagonInlineAsmRegClass), ++ LoongArch(LoongArchInlineAsmRegClass), + Mips(MipsInlineAsmRegClass), + S390x(S390xInlineAsmRegClass), + SpirV(SpirVInlineAsmRegClass), +@@ -427,6 +439,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.name(), + Self::PowerPC(r) => r.name(), + Self::Hexagon(r) => r.name(), ++ Self::LoongArch(r) => r.name(), + Self::Mips(r) => r.name(), + Self::S390x(r) => r.name(), + Self::SpirV(r) => r.name(), +@@ -450,6 +463,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), + Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), + Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), ++ Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch), + Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), + Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), + Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), +@@ -480,6 +494,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.suggest_modifier(arch, ty), + Self::PowerPC(r) => r.suggest_modifier(arch, ty), + Self::Hexagon(r) => r.suggest_modifier(arch, ty), ++ Self::LoongArch(r) => r.suggest_modifier(arch, ty), + Self::Mips(r) => r.suggest_modifier(arch, ty), + Self::S390x(r) => r.suggest_modifier(arch, ty), + Self::SpirV(r) => r.suggest_modifier(arch, ty), +@@ -506,6 +521,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.default_modifier(arch), + Self::PowerPC(r) => r.default_modifier(arch), + Self::Hexagon(r) => r.default_modifier(arch), ++ Self::LoongArch(r) => r.default_modifier(arch), + Self::Mips(r) => r.default_modifier(arch), + Self::S390x(r) => r.default_modifier(arch), + Self::SpirV(r) => r.default_modifier(arch), +@@ -531,6 +547,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.supported_types(arch), + Self::PowerPC(r) => r.supported_types(arch), + Self::Hexagon(r) => r.supported_types(arch), ++ Self::LoongArch(r) => r.supported_types(arch), + Self::Mips(r) => r.supported_types(arch), + Self::S390x(r) => r.supported_types(arch), + Self::SpirV(r) => r.supported_types(arch), +@@ -557,6 +574,7 @@ impl InlineAsmRegClass { + Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?) + } + InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?), ++ InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmRegClass::parse(name)?), + InlineAsmArch::Mips | InlineAsmArch::Mips64 => { + Self::Mips(MipsInlineAsmRegClass::parse(name)?) + } +@@ -582,6 +600,7 @@ impl InlineAsmRegClass { + Self::Nvptx(r) => r.valid_modifiers(arch), + Self::PowerPC(r) => r.valid_modifiers(arch), + Self::Hexagon(r) => r.valid_modifiers(arch), ++ Self::LoongArch(r) => r.valid_modifiers(arch), + Self::Mips(r) => r.valid_modifiers(arch), + Self::S390x(r) => r.valid_modifiers(arch), + Self::SpirV(r) => r.valid_modifiers(arch), +@@ -740,6 +759,11 @@ pub fn allocatable_registers( + hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map); + map + } ++ InlineAsmArch::LoongArch64 => { ++ let mut map = loongarch::regclass_map(); ++ loongarch::fill_reg_map(arch, reloc_model, target_features, target, &mut map); ++ map ++ } + InlineAsmArch::Mips | InlineAsmArch::Mips64 => { + let mut map = mips::regclass_map(); + mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map); +@@ -788,6 +812,7 @@ pub enum InlineAsmClobberAbi { + AArch64, + AArch64NoX18, + RiscV, ++ LoongArch, + } + + impl InlineAsmClobberAbi { +@@ -829,6 +854,10 @@ impl InlineAsmClobberAbi { + "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), + _ => Err(&["C", "system", "efiapi"]), + }, ++ InlineAsmArch::LoongArch64 => match name { ++ "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::LoongArch), ++ _ => Err(&["C", "system", "efiapi"]), ++ }, + _ => Err(&[]), + } + } +@@ -971,6 +1000,21 @@ impl InlineAsmClobberAbi { + v24, v25, v26, v27, v28, v29, v30, v31, + } + }, ++ InlineAsmClobberAbi::LoongArch => clobbered_regs! { ++ LoongArch LoongArchInlineAsmReg { ++ // ra ++ r1, ++ // a0-a7 ++ r4, r5, r6, r7, r8, r9, r10, r11, ++ // t0-t8 ++ r12, r13, r14, r15, r16, r17, r18, r19, r20, ++ // fa0-fa7 ++ f0, f1, f2, f3, f4, f5, f6, f7, ++ // ft0-ft15 ++ f8, f9, f10, f11, f12, f13, f14, f15, ++ f16, f17, f18, f19, f20, f21, f22, f23, ++ } ++ }, + } + } + } +diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs +new file mode 100644 +index 000000000..4dc785dac +--- /dev/null ++++ b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs +@@ -0,0 +1,18 @@ ++use crate::spec::{Target, TargetOptions}; ++ ++pub fn target() -> Target { ++ Target { ++ llvm_target: "loongarch64-unknown-linux-gnu".into(), ++ pointer_width: 64, ++ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), ++ arch: "loongarch64".into(), ++ options: TargetOptions { ++ abi: "abilp64".into(), ++ cpu: "la464".into(), ++ max_atomic_width: Some(64), ++ llvm_abiname: "lp64".into(), ++ ++ ..super::linux_gnu_base::opts() ++ }, ++ } ++} +diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs +index 8909cf33a..5f43e4faa 100644 +--- a/compiler/rustc_target/src/spec/mod.rs ++++ b/compiler/rustc_target/src/spec/mod.rs +@@ -1245,6 +1245,8 @@ supported_targets! { + ("x86_64-unknown-none", x86_64_unknown_none), + + ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), ++ ++ ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu), + } + + /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> +diff --git a/library/std/src/env.rs b/library/std/src/env.rs +index 6eb7cbea6..d149d7cda 100644 +--- a/library/std/src/env.rs ++++ b/library/std/src/env.rs +@@ -888,6 +888,7 @@ pub mod consts { + /// - x86_64 + /// - arm + /// - aarch64 ++ /// - loongarch64 + /// - m68k + /// - mips + /// - mips64 +diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs +index c73791d14..4d0607d19 100644 +--- a/library/std/src/os/linux/raw.rs ++++ b/library/std/src/os/linux/raw.rs +@@ -232,6 +232,7 @@ mod arch { + } + + #[cfg(any( ++ target_arch = "loongarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64", +diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs +index 7f0b0439c..047aa07df 100644 +--- a/library/std/src/personality/gcc.rs ++++ b/library/std/src/personality/gcc.rs +@@ -76,6 +76,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 + #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] + const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 + ++#[cfg(target_arch = "loongarch64")] ++const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 ++ + // The following code is based on GCC's C and C++ personality routines. For reference, see: + // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc + // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c +diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs +index e8e7c51cb..3b0c6d4a2 100644 +--- a/library/std/src/sys/common/alloc.rs ++++ b/library/std/src/sys/common/alloc.rs +@@ -24,6 +24,7 @@ pub const MIN_ALIGN: usize = 8; + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64", ++ target_arch = "loongarch64", + target_arch = "riscv64", + target_arch = "wasm64", + )))] +diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs +index a5b6193b0..2da4dc286 100644 +--- a/library/unwind/src/libunwind.rs ++++ b/library/unwind/src/libunwind.rs +@@ -69,6 +69,9 @@ pub const unwinder_private_data_size: usize = 20; + #[cfg(all(target_arch = "hexagon", target_os = "linux"))] + pub const unwinder_private_data_size: usize = 35; + ++#[cfg(target_arch = "loongarch64")] ++pub const unwinder_private_data_size: usize = 2; ++ + #[repr(C)] + pub struct _Unwind_Exception { + pub exception_class: _Unwind_Exception_Class, +diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py +index 57128685d..93d53b2a3 100644 +--- a/src/bootstrap/bootstrap.py ++++ b/src/bootstrap/bootstrap.py +@@ -303,6 +303,7 @@ def default_build_triple(verbose): + 'i486': 'i686', + 'i686': 'i686', + 'i786': 'i686', ++ 'loongarch64': 'loongarch64', + 'm68k': 'm68k', + 'powerpc': 'powerpc', + 'powerpc64': 'powerpc64', +diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs +index 7e70e99bb..52cb9dc77 100644 +--- a/src/bootstrap/lib.rs ++++ b/src/bootstrap/lib.rs +@@ -213,7 +213,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] + ( + Some(Mode::Std), + "target_arch", +- Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa"]), ++ Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa", "loongarch64"]), + ), + /* Extra names used by dependencies */ + // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set +diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs +index 2f856c276..7c4da4d23 100644 +--- a/src/bootstrap/native.rs ++++ b/src/bootstrap/native.rs +@@ -357,7 +357,7 @@ impl Step for Llvm { + let llvm_targets = match &builder.config.llvm_targets { + Some(s) => s, + None => { +- "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\ ++ "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\ + Sparc;SystemZ;WebAssembly;X86" + } + }; +diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml +index 10de2e8d5..b34437f01 100644 +--- a/src/ci/github-actions/ci.yml ++++ b/src/ci/github-actions/ci.yml +@@ -346,6 +346,9 @@ jobs: + - name: dist-i686-linux + <<: *job-linux-xl + ++ - name: dist-loongarch64-linux ++ <<: *job-linux-xl ++ + - name: dist-mips-linux + <<: *job-linux-xl + +diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md +index a36518cc8..3724253a8 100644 +--- a/src/doc/rustc/src/platform-support.md ++++ b/src/doc/rustc/src/platform-support.md +@@ -86,6 +86,7 @@ target | notes + `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17) + `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17) + `armv7-unknown-linux-gnueabihf` | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17) ++`loongarch64-unknown-linux-gnu` | LOONGARCH64 Linux (kernel 4.19, glibc 2.28) + `mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23) + `mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23) + `mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23) +diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs +index f33f5d27d..11f713419 100644 +--- a/src/librustdoc/clean/cfg.rs ++++ b/src/librustdoc/clean/cfg.rs +@@ -515,6 +515,7 @@ impl<'a> fmt::Display for Display<'a> { + "aarch64" => "AArch64", + "arm" => "ARM", + "asmjs" => "JavaScript", ++ "loongarch64" => "LoongArch64", + "m68k" => "M68k", + "mips" => "MIPS", + "mips64" => "MIPS-64", +diff --git a/src/test/assembly/asm/loongarch-types.rs b/src/test/assembly/asm/loongarch-types.rs +new file mode 100644 +index 000000000..9c116f730 +--- /dev/null ++++ b/src/test/assembly/asm/loongarch-types.rs +@@ -0,0 +1,194 @@ ++// min-llvm-version: 10.0.1 ++// assembly-output: emit-asm ++// compile-flags: --target loongarch64-unknown-linux-gnu ++// needs-llvm-components: loongarch ++ ++#![feature(no_core, lang_items, rustc_attrs, asm_sym)] ++#![crate_type = "rlib"] ++#![no_core] ++#![allow(asm_sub_register)] ++ ++#[rustc_builtin_macro] ++macro_rules! asm { ++ () => {}; ++} ++#[rustc_builtin_macro] ++macro_rules! concat { ++ () => {}; ++} ++#[rustc_builtin_macro] ++macro_rules! stringify { ++ () => {}; ++} ++ ++#[lang = "sized"] ++trait Sized {} ++#[lang = "copy"] ++trait Copy {} ++ ++type ptr = *const i32; ++ ++impl Copy for i8 {} ++impl Copy for i16 {} ++impl Copy for i32 {} ++impl Copy for i64 {} ++impl Copy for f32 {} ++impl Copy for f64 {} ++impl Copy for ptr {} ++extern "C" { ++ fn extern_func(); ++ static extern_static: u8; ++} ++ ++// Hack to avoid function merging ++extern "Rust" { ++ fn dont_merge(s: &str); ++} ++ ++// CHECK-LABEL: sym_fn: ++// CHECK: #APP ++// CHECK: la.got $r12, extern_func ++// CHECK: #NO_APP ++#[no_mangle] ++pub unsafe fn sym_fn() { ++ asm!("la.got $r12, {}", sym extern_func); ++} ++ ++// CHECK-LABEL: sym_static: ++// CHECK: #APP ++// CHECK: la.got $r12, extern_static ++// CHECK: #NO_APP ++#[no_mangle] ++pub unsafe fn sym_static() { ++ asm!("la.got $r12, {}", sym extern_static); ++} ++ ++macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { ++ #[no_mangle] ++ pub unsafe fn $func(x: $ty) -> $ty { ++ dont_merge(stringify!($func)); ++ ++ let y; ++ asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); ++ y ++ } ++};} ++ ++macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { ++ #[no_mangle] ++ pub unsafe fn $func(x: $ty) -> $ty { ++ dont_merge(stringify!($func)); ++ ++ let y; ++ asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); ++ y ++ } ++};} ++ ++// CHECK-LABEL: reg_i8: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_i8, i8, reg, "move"); ++ ++// CHECK-LABEL: reg_i16: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_i16, i16, reg, "move"); ++ ++// CHECK-LABEL: reg_i32: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_i32, i32, reg, "move"); ++ ++// CHECK-LABEL: reg_f32: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_f32, f32, reg, "move"); ++ ++// CHECK-LABEL: reg_i64: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_i64, i64, reg, "move"); ++ ++// CHECK-LABEL: reg_f64: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_f64, f64, reg, "move"); ++ ++// CHECK-LABEL: reg_ptr: ++// CHECK: #APP ++// CHECK: move $r{{[0-9]+}}, $r{{[0-9]+}} ++// CHECK: #NO_APP ++check!(reg_ptr, ptr, reg, "move"); ++ ++// CHECK-LABEL: freg_f32: ++// CHECK: #APP ++// CHECK: fmov.s $f{{[0-9]+}}, $f{{[0-9]+}} ++// CHECK: #NO_APP ++check!(freg_f32, f32, freg, "fmov.s"); ++ ++// CHECK-LABEL: freg_f64: ++// CHECK: #APP ++// CHECK: fmov.d $f{{[0-9]+}}, $f{{[0-9]+}} ++// CHECK: #NO_APP ++check!(freg_f64, f64, freg, "fmov.d"); ++ ++// CHECK-LABEL: r4_i8: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_i8, i8, "$r4", "move"); ++ ++// CHECK-LABEL: r4_i16: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_i16, i16, "$r4", "move"); ++ ++// CHECK-LABEL: r4_i32: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_i32, i32, "$r4", "move"); ++ ++// CHECK-LABEL: r4_f32: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_f32, f32, "$r4", "move"); ++ ++// CHECK-LABEL: r4_i64: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_i64, i64, "$r4", "move"); ++ ++// CHECK-LABEL: r4_f64: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_f64, f64, "$r4", "move"); ++ ++// CHECK-LABEL: r4_ptr: ++// CHECK: #APP ++// CHECK: move $r4, $r4 ++// CHECK: #NO_APP ++check_reg!(r4_ptr, ptr, "$r4", "move"); ++ ++// CHECK-LABEL: f0_f32: ++// CHECK: #APP ++// CHECK: fmov.s $f{{[0-9]+}}, $f{{[0-9]+}} ++// CHECK: #NO_APP ++check_reg!(f0_f32, f32, "$f0", "fmov.s"); ++ ++// CHECK-LABEL: f0_f64: ++// CHECK: #APP ++// CHECK: fmov.d $f{{[0-9]+}}, $f{{[0-9]+}} ++// CHECK: #NO_APP ++check_reg!(f0_f64, f64, "$f0", "fmov.d"); +diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs +index 4ed491dfb..1b79aa221 100644 +--- a/src/test/codegen/abi-main-signature-16bit-c-int.rs ++++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs +@@ -6,6 +6,7 @@ + // ignore-arm + // ignore-asmjs + // ignore-hexagon ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-powerpc +diff --git a/src/test/codegen/call-llvm-intrinsics.rs b/src/test/codegen/call-llvm-intrinsics.rs +index 998099c23..77a11ad9f 100644 +--- a/src/test/codegen/call-llvm-intrinsics.rs ++++ b/src/test/codegen/call-llvm-intrinsics.rs +@@ -1,6 +1,7 @@ + // compile-flags: -C no-prepopulate-passes + + // ignore-riscv64 ++// ignore-loongarch64 + + #![feature(link_llvm_intrinsics)] + #![crate_type = "lib"] +diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs +index fab84868f..ab47178b0 100644 +--- a/src/test/codegen/global_asm.rs ++++ b/src/test/codegen/global_asm.rs +@@ -6,6 +6,7 @@ + // ignore-bpfel + // ignore-bpfeb + // ignore-hexagon ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-msp430 +diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs +index 02ee91645..0eaecfde5 100644 +--- a/src/test/codegen/global_asm_include.rs ++++ b/src/test/codegen/global_asm_include.rs +@@ -6,6 +6,7 @@ + // ignore-bpfel + // ignore-bpfeb + // ignore-hexagon ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-msp430 +diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs +index bdcf0ea84..de2b03336 100644 +--- a/src/test/codegen/global_asm_x2.rs ++++ b/src/test/codegen/global_asm_x2.rs +@@ -6,6 +6,7 @@ + // ignore-bpfel + // ignore-bpfeb + // ignore-hexagon ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-msp430 +diff --git a/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs b/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs +new file mode 100644 +index 000000000..bfc4620d8 +--- /dev/null ++++ b/src/test/codegen/loongarch-abi/call-llvm-intrinsics.rs +@@ -0,0 +1,30 @@ ++// compile-flags: -C no-prepopulate-passes ++ ++// only-loongarch64 ++ ++#![feature(link_llvm_intrinsics)] ++#![crate_type = "lib"] ++ ++struct A; ++ ++impl Drop for A { ++ fn drop(&mut self) { ++ println!("A"); ++ } ++} ++ ++extern "C" { ++ #[link_name = "llvm.sqrt.f32"] ++ fn sqrt(x: f32) -> f32; ++} ++ ++pub fn do_call() { ++ let _a = A; ++ ++ unsafe { ++ // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them ++ // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4 ++ // CHECK: call float @llvm.sqrt.f32(float %{{.}} ++ sqrt(4.0); ++ } ++} +diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs +index 9d18c5f03..97ce1ccbd 100644 +--- a/src/test/codegen/repr-transparent-aggregates-1.rs ++++ b/src/test/codegen/repr-transparent-aggregates-1.rs +@@ -3,6 +3,7 @@ + + // ignore-arm + // ignore-aarch64 ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-powerpc +diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs +index df7e88f08..09ee567cd 100644 +--- a/src/test/codegen/repr-transparent-aggregates-2.rs ++++ b/src/test/codegen/repr-transparent-aggregates-2.rs +@@ -4,6 +4,7 @@ + // ignore-aarch64 + // ignore-emscripten + // ignore-mips64 ++// ignore-loongarch64 + // ignore-powerpc + // ignore-powerpc64 + // ignore-powerpc64le +diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs +index c68ba8460..5d5ebfc4b 100644 +--- a/src/test/codegen/repr-transparent.rs ++++ b/src/test/codegen/repr-transparent.rs +@@ -2,6 +2,7 @@ + + // ignore-riscv64 riscv64 has an i128 type used with test_Vector + // see codegen/riscv-abi for riscv functiona call tests ++// ignore-loongarch64 + + #![crate_type="lib"] + #![feature(repr_simd, transparent_unions)] +diff --git a/src/test/run-make-fulldeps/atomic-lock-free/Makefile b/src/test/run-make-fulldeps/atomic-lock-free/Makefile +index 37e59624a..dcca7f8f7 100644 +--- a/src/test/run-make-fulldeps/atomic-lock-free/Makefile ++++ b/src/test/run-make-fulldeps/atomic-lock-free/Makefile +@@ -25,6 +25,10 @@ ifeq ($(filter aarch64,$(LLVM_COMPONENTS)),aarch64) + $(RUSTC) --target=aarch64-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + endif ++ifeq ($(filter loongarch64,$(LLVM_COMPONENTS)),loongarch64) ++ $(RUSTC) --target=loongarch64-unknown-linux-gnu atomic_lock_free.rs ++ nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add ++endif + ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips) + $(RUSTC) --target=mips-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +diff --git a/src/test/ui/abi/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs +index 6d934538f..e1b89d950 100644 +--- a/src/test/ui/abi/stack-probes-lto.rs ++++ b/src/test/ui/abi/stack-probes-lto.rs +@@ -1,6 +1,7 @@ + // run-pass + // ignore-arm + // ignore-aarch64 ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-sparc +diff --git a/src/test/ui/cfg/conditional-compile-arch.rs b/src/test/ui/cfg/conditional-compile-arch.rs +index 7de561df1..34172b8c9 100644 +--- a/src/test/ui/cfg/conditional-compile-arch.rs ++++ b/src/test/ui/cfg/conditional-compile-arch.rs +@@ -13,6 +13,9 @@ pub fn main() { } + #[cfg(target_arch = "aarch64")] + pub fn main() { } + ++#[cfg(target_arch = "loongarch64")] ++pub fn main() { } ++ + #[cfg(target_arch = "mips")] + pub fn main() { } + +diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr +index 9864aa385..5ca4d3b3d 100644 +--- a/src/test/ui/check-cfg/compact-values.stderr ++++ b/src/test/ui/check-cfg/compact-values.stderr +@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value + LL | #[cfg(target(os = "linux", arch = "X"))] + | ^^^^^^^^^^ + | +- = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 ++ = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, loongarch64, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 + = note: `#[warn(unexpected_cfgs)]` on by default + + warning: 1 warning emitted +diff --git a/src/test/ui/process/nofile-limit.rs b/src/test/ui/process/nofile-limit.rs +index 3ddf8d6ef..79a6be731 100644 +--- a/src/test/ui/process/nofile-limit.rs ++++ b/src/test/ui/process/nofile-limit.rs +@@ -1,7 +1,8 @@ + // Check that statically linked binary executes successfully + // with RLIMIT_NOFILE resource lowered to zero. Regression + // test for issue #96621. +-// ++// loongarch64 has no setrlimit ++// ignore-loongarch64 + // run-pass + // dont-check-compiler-stderr + // only-linux +diff --git a/src/test/ui/target-feature/gate.rs b/src/test/ui/target-feature/gate.rs +index 2382c98f8..15d1af6f7 100644 +--- a/src/test/ui/target-feature/gate.rs ++++ b/src/test/ui/target-feature/gate.rs +@@ -2,6 +2,7 @@ + // ignore-aarch64 + // ignore-wasm + // ignore-emscripten ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-powerpc +@@ -28,6 +29,7 @@ + // gate-test-ermsb_target_feature + // gate-test-bpf_target_feature + // gate-test-aarch64_ver_target_feature ++// gate-test-loongarch64_target_feature + + #[target_feature(enable = "avx512bw")] + //~^ ERROR: currently unstable +diff --git a/src/test/ui/target-feature/invalid-attribute.rs b/src/test/ui/target-feature/invalid-attribute.rs +index ad1b6e96b..040f3a365 100644 +--- a/src/test/ui/target-feature/invalid-attribute.rs ++++ b/src/test/ui/target-feature/invalid-attribute.rs +@@ -2,6 +2,7 @@ + // ignore-aarch64 + // ignore-wasm + // ignore-emscripten ++// ignore-loongarch64 + // ignore-mips + // ignore-mips64 + // ignore-powerpc +diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs +index b0006cb90..0c2b4b1ed 100644 +--- a/src/tools/build-manifest/src/main.rs ++++ b/src/tools/build-manifest/src/main.rs +@@ -28,6 +28,7 @@ static HOSTS: &[&str] = &[ + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", ++ "loongarch64-unknown-linux-gnu", + "mips-unknown-linux-gnu", + "mips64-unknown-linux-gnuabi64", + "mips64el-unknown-linux-gnuabi64", +@@ -99,6 +100,7 @@ static TARGETS: &[&str] = &[ + "i686-unknown-freebsd", + "i686-unknown-linux-gnu", + "i686-unknown-linux-musl", ++ "loongarch64-unknown-linux-gnu", + "m68k-unknown-linux-gnu", + "mips-unknown-linux-gnu", + "mips-unknown-linux-musl", +diff --git a/src/tools/clippy/tests/ui/asm_syntax.rs b/src/tools/clippy/tests/ui/asm_syntax.rs +index 0220bf333..03748de7b 100644 +--- a/src/tools/clippy/tests/ui/asm_syntax.rs ++++ b/src/tools/clippy/tests/ui/asm_syntax.rs +@@ -1,5 +1,6 @@ + // only-x86_64 + // ignore-aarch64 ++// ignore-loongarch64 + + #[warn(clippy::inline_asm_x86_intel_syntax)] + mod warn_intel { +diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs +index 0260f6848..f4fb9fcdf 100644 +--- a/src/tools/compiletest/src/common.rs ++++ b/src/tools/compiletest/src/common.rs +@@ -430,7 +430,7 @@ impl Config { + pub fn has_asm_support(&self) -> bool { + static ASM_SUPPORTED_ARCHS: &[&str] = &[ + "x86", "x86_64", "arm", "aarch64", "riscv32", +- "riscv64", ++ "riscv64", "loongarch64", + // These targets require an additional asm_experimental_arch feature. + // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32", + ]; +-- +2.41.0 + diff --git a/rust.spec b/rust.spec index a6c5c42..b09c752 100644 --- a/rust.spec +++ b/rust.spec @@ -1,6 +1,7 @@ +%define anolis_release .0.1 # Only x86_64, i686, and aarch64 are Tier 1 platforms at this time. # https://doc.rust-lang.org/nightly/rustc/platform-support.html -%global rust_arches x86_64 i686 aarch64 ppc64le s390x +%global rust_arches x86_64 i686 aarch64 ppc64le s390x loongarch64 # The channel can be stable, beta, or nightly %{!?channel: %global channel stable} @@ -88,7 +89,7 @@ Name: rust Version: 1.71.1 -Release: 1%{?dist} +Release: 1%{anolis_release}%{?dist} Summary: The Rust Programming Language License: (ASL 2.0 or MIT) and (BSD and MIT) # ^ written as: (rust itself) and (bundled libraries) @@ -133,6 +134,14 @@ Patch100: rustc-1.71.0-disable-libssh2.patch # will try to build it statically -- instead we turn off the feature. Patch101: rustc-1.71.0-disable-http2.patch +#patch for loongarch64 +Patch103: 0001-vendor-cc-add-loongarch64-support.patch +Patch104: 0002-vendor-libc-update-loongarch64-support.patch +Patch105: 0003-vendor-psm-add-loongarch64-support.patch +Patch106: 0004-vendor-object-add-loongarch64-support.patch +Patch107: 0005-llvm-update-loongarch64-support.patch +Patch108: 0006-rust-add-loongarch64-support.patch + # Get the Rust triple for any arch. %{lua: function rust_triple(arch) local abi = "gnu" @@ -608,6 +617,12 @@ test -f '%{local_rust_root}/bin/rustc' rm -rf vendor/libnghttp2-sys*/ %endif +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 # Use our explicit python3 first sed -i.try-python -e '/^try python3 /i try "%{__python3}" "$@"' ./configure @@ -696,7 +711,7 @@ end} %build %{export_rust_env} -%ifarch %{arm} %{ix86} +%ifarch %{arm} %{ix86} loongarch64 # full debuginfo is exhausting memory; just do libstd for now # https://github.com/rust-lang/rust/issues/45854 %if 0%{?rhel} && 0%{?rhel} < 8 @@ -1082,6 +1097,10 @@ end} %changelog +* Mon Dec 25 2023 WANG Rui - 1.71.1-1.0.1 +- Add support for loongarch64. +- Fix CVE-2023-38497 (liwei.glw@alibaba-inc.com) + * Tue Aug 08 2023 Josh Stone - 1.71.1-1 - Update to 1.71.1. - Security fix for CVE-2023-38497 -- Gitee